Fixed bug with self loopback packets in multithreaded environments

This commit is contained in:
Mark Pizzolato 2011-04-18 16:07:23 -07:00
parent bafbba4df8
commit b577841d03
3 changed files with 27 additions and 4 deletions

View file

@ -2567,7 +2567,7 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
if (status != SCPE_OK) {
free(tptr);
free(xq->var->etherface);
xq->var->etherface = 0;
xq->var->etherface = NULL;
return status;
}
if (xq->var->poll == 0) {
@ -2575,7 +2575,7 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
if (status != SCPE_OK) {
free(tptr);
free(xq->var->etherface);
xq->var->etherface = 0;
xq->var->etherface = NULL;
return status;
}
xq->var->must_poll = 0;
@ -2589,6 +2589,8 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
printf("%s: MAC Address Conflict on LAN for address %s, change the MAC address to a unique value\n", xq->dev->name, buf);
if (sim_log) fprintf (sim_log, "%s: MAC Address Conflict on LAN for address %s, change the MAC address to a unique value\n", xq->dev->name, buf);
eth_close(xq->var->etherface);
free(xq->var->etherface);
xq->var->etherface = NULL;
return SCPE_NOATT;
}
uptr->filename = tptr;
@ -2613,7 +2615,7 @@ t_stat xq_detach(UNIT* uptr)
if (uptr->flags & UNIT_ATT) {
eth_close (xq->var->etherface);
free(xq->var->etherface);
xq->var->etherface = 0;
xq->var->etherface = NULL;
free(uptr->filename);
uptr->filename = NULL;
uptr->flags &= ~UNIT_ATT;

View file

@ -151,6 +151,8 @@
Modification history:
18-Apr-11 MP Fixed race condition with self loopback packets in
multithreaded environments
09-Jan-11 MP Fixed missing crc data when USE_READER_THREAD is defined and
crc's are needed (only the pdp11_xu)
16-Dec-10 MP added priority boost for read and write threads when
@ -1444,6 +1446,7 @@ t_stat eth_open(ETH_DEV* dev, char* name, DEVICE* dptr, uint32 dbit)
ethq_init (&dev->read_queue, 200); /* initialize FIFO queue */
pthread_mutex_init (&dev->lock, NULL);
pthread_mutex_init (&dev->writer_lock, NULL);
pthread_mutex_init (&dev->self_lock, NULL);
pthread_cond_init (&dev->writer_cond, NULL);
pthread_attr_init(&attr);
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
@ -1495,6 +1498,7 @@ t_stat eth_close(ETH_DEV* dev)
pthread_mutex_destroy (&dev->lock);
pthread_cond_signal (&dev->writer_cond);
pthread_join (dev->writer_thread, NULL);
pthread_mutex_destroy (&dev->self_lock);
pthread_mutex_destroy (&dev->writer_lock);
pthread_cond_destroy (&dev->writer_cond);
if (1) {
@ -1534,8 +1538,10 @@ t_stat eth_check_address_conflict (ETH_DEV* dev,
ETH_PACK send, recv;
t_stat status;
int responses = 0;
char mac_string[32];
sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict...\n");
eth_mac_fmt(mac, mac_string);
sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string);
/* build a loopback forward request packet */
memset (&send, 0, sizeof(ETH_PACK));
@ -1617,8 +1623,14 @@ t_stat _eth_write(ETH_DEV* dev, ETH_PACK* packet, ETH_PCALLBACK routine)
/* detect sending of loopback packet */
if ((status == 0) && (LOOPBACK_SELF_FRAME(dev->physical_addr, packet->msg))) {
#ifdef USE_READER_THREAD
pthread_mutex_lock (&dev->self_lock);
#endif
dev->loopback_self_sent += dev->reflections;
dev->loopback_self_sent_total++;
#ifdef USE_READER_THREAD
pthread_mutex_unlock (&dev->self_lock);
#endif
}
} /* if packet->len */
@ -2122,6 +2134,9 @@ _eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data
/* detect reception of loopback packet to our physical address */
if (LOOPBACK_SELF_FRAME(dev->physical_addr, data)) {
#ifdef USE_READER_THREAD
pthread_mutex_lock (&dev->self_lock);
#endif
dev->loopback_self_rcvd_total++;
/* lower reflection count - if already zero, pass it on */
if (dev->loopback_self_sent > 0) {
@ -2132,6 +2147,9 @@ _eth_callback(u_char* info, const struct pcap_pkthdr* header, const u_char* data
#ifndef USE_BPF
else
from_me = 0;
#endif
#ifdef USE_READER_THREAD
pthread_mutex_unlock (&dev->self_lock);
#endif
}

View file

@ -28,6 +28,8 @@
Modification history:
18-Apr-11 MP Fixed race condition with self loopback packets in
multithreaded environments
09-Dec-10 MP Added support to determine if network address conflicts exist
07-Dec-10 MP Reworked DECnet self detection to the more general approach
of loopback self when any Physical Address is being set.
@ -203,6 +205,7 @@ struct eth_device {
pthread_t reader_thread; /* Reader Thread Id */
pthread_t writer_thread; /* Writer Thread Id */
pthread_mutex_t writer_lock;
pthread_mutex_t self_lock;
pthread_cond_t writer_cond;
struct write_request {
struct write_request *next;