unsigned pa_aupdate_write_begin(pa_aupdate *a) { unsigned n; pa_assert(a); pa_mutex_lock(a->write_lock); n = (unsigned) pa_atomic_load(&a->read_lock); a->swapped = false; return !WHICH(n); }
unsigned pa_aupdate_read_begin(pa_aupdate *a) { unsigned n; pa_assert(a); /* Increase the lock counter */ n = (unsigned) pa_atomic_inc(&a->read_lock); /* When n is 0 we have about 2^31 threads running that all try to * access the data at the same time, oh my! */ pa_assert(COUNTER(n)+1 > 0); /* The uppermost bit tells us which data to look at */ return WHICH(n); }
unsigned pa_aupdate_write_swap(pa_aupdate *a) { unsigned n; pa_assert(a); for (;;) { n = (unsigned) pa_atomic_load(&a->read_lock); /* If the read counter is > 0 wait; if it is 0 try to swap the lists */ if (COUNTER(n) > 0) pa_semaphore_wait(a->semaphore); else if (pa_atomic_cmpxchg(&a->read_lock, (int) n, (int) (n ^ MSB))) break; } a->swapped = true; return WHICH(n); }
void check_topology(int Tflag, int argc, char **argv) { extern int application_bounds(int *minmsg, int *maxmsg); extern int check_ethernets(BOOL **adj); CnetAddr a; NODEATTR *na; int n, p, nrouters; int x, y, rootn; int appl_minmsg, appl_maxmsg; LINK *lp; BOOL **adj; for(n=0, nrouters=0 ; n<_NNODES ; n++) { extern char *random_osname(int randint); /* ASSIGN A RANDOM OPERATING SYSTEM TYPE IF NECESSARY */ if(NP[n].nodetype == NT_ROUTER) ++nrouters; else if(NP[n].nattr.osname == (char *)NULL) NP[n].nattr.osname = random_osname((int)nrand48(xsubi)); } n = _NNODES - nrouters; if(dflag) fprintf(stderr,"%d host%s, %d router%s and %d link%s\n", P(n), P(nrouters), P(_NLINKS) ); /* ENSURE THAT WE HAVE AT LEAST 2 HOSTS (APPLICATION LAYERS) */ if(n < 2) { fputs("A network must have >= 2 hosts\n",stderr); ++nerrors; } application_bounds(&appl_minmsg, &appl_maxmsg); for(n=0 ; n<(_NNODES-1) ; n++) { int my_minmsg; int my_maxmsg; /* NEXT, CHECK FOR DUPLICATE USER-SPECIFIED NODE ADDRESSES */ na = &NP[n].nattr; a = na->address; for(p=n+1 ; p<_NNODES ; p++) if(a == NP[p].nattr.address) { fprintf(stderr, "%s and %s have the same node address (%u)\n", NP[n].nodename, NP[p].nodename, a); ++nerrors; } /* CHECK THAT USER-REQUESTED MESSAGE SIZES ARE NEITHER TOO BIG NOR TOO SMALL */ my_minmsg = WHICH(na->minmessagesize, DEFAULTNODE.minmessagesize); my_maxmsg = WHICH(na->maxmessagesize, DEFAULTNODE.maxmessagesize); if(my_minmsg < appl_minmsg) { fprintf(stderr, "%s has minmessagesize(=%d) < application layer requirements(=%d)\n", NP[n].nodename, my_minmsg, appl_minmsg); ++nerrors; } if(my_maxmsg > appl_maxmsg) { fprintf(stderr, "%s has maxmessagesize(=%d) > application layer requirements(=%d)\n", NP[n].nodename, my_maxmsg, appl_maxmsg); ++nerrors; } if(my_minmsg > my_maxmsg) { fprintf(stderr,"%s has minmessagesize(=%d) > maxmessagesize(=%d)\n", NP[n].nodename, my_minmsg, my_maxmsg); ++nerrors; } } /* ALLOCATE AND INITIALIZE THE ADJACENCY MATIRX (CHECK FOR ETHERNETS TOO) */ adj = (BOOL **)malloc(_NNODES * sizeof(BOOL *)); for(n=0 ; n<_NNODES ; ++n) { adj[n] = (BOOL *)malloc(_NNODES * sizeof(BOOL)); memset(adj[n], 0, _NNODES * sizeof(BOOL)); } check_ethernets(adj); /* IF ANY SIGNIFICANT ERRORS OCCURED, TERMINATE THE PROGRAM */ if(nerrors) cleanup(1); rootn = (int)sqrt((double)(_NNODES-1)) + 1; for(n=0 ; n < _NNODES ; n++) { na = &NP[n].nattr; x = n%rootn; y = n/rootn; /* GIVE SOME DEFAULT X,Y COORDINATES IF THEY HAVE NOT BEEN SPECIFIED */ if(na->x == 0) na->x = (2*x+1) * DEF_NODE_X; if(na->y == 0) na->y = (2*y+1) * DEF_NODE_Y; if(na->winx == 0) na->winx = (5*x+1) * DEF_NODE_X; if(na->winy == 0) na->winy = (5*y+1) * DEF_NODE_Y; /* ADD ANY REBOOT ARGUMENTS IF NOT PROVIDED BY TOPOLOGY FILE */ if(na->reboot_args == (char **)NULL) init_reboot_args(na, argc, argv); } /* NEXT, PROVIDE A WARNING (ONLY) IF THE TOPOLOGY IS NOT CONNECTED */ for(n=0, lp=LP ; n<_NLINKS ; n++, lp++) if(LP[n].linktype == LT_POINT2POINT) { int from = lp->endmin; int to = lp->endmax; adj[from][to] = adj[to][from] = TRUE; } if(!connected(_NNODES, adj)) fprintf(stderr, "*** warning: this topology is not connected\n"); for(n=0 ; n<_NNODES ; ++n) free(adj[n]); free(adj); /* IF ATTEMPTING TO DRAWN FRAMES IN A 2-NODE WORLD (ONLY), POSITION NODES */ if(_NNODES == 2 && gattr.drawframes && nethernets == 0 && !Tflag && Wflag) { NP[0].nattr.x = DEF_NODE_X; NP[0].nattr.y = DEF_NODE_Y; NP[1].nattr.x = DRAWFRAME_WIDTH - DEF_NODE_X; NP[1].nattr.y = DEF_NODE_Y; } else gattr.drawframes = FALSE; }