From mboxrd@z Thu Jan 1 00:00:00 1970 To: 9fans@cse.psu.edu From: "Russ Cox" MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Message-Id: <20020116034426.F0943199EE@mail.cse.psu.edu> Subject: [9fans] semaphores Date: Tue, 15 Jan 2002 22:44:21 -0500 Topicbox-Message-UUID: 3ddfdfe4-eaca-11e9-9e20-41e7f4b1d025 I just wrote these for a porting project and then discovered that I didn't need them. However, they seem a little subtle to me (I gave up the first couple times I tried) so I figured I'd toss them out for others and to see if anyone noticed any problems. Russ /* * Semaphore support. * * The data QLock could be a Lock if you care; * it protects the n and need values. * * The wait QLock manages the line of people waiting to * acquire the semaphore. If you manage to qlock it, * it's your turn. If n isn't big enough for you, record * your needs and rendezvous on the Sema; once incsema * makes n big enough, it will rendezvous with you. */ typedef struct Sema Sema; struct Semaphore { QLock data; QLock wait; int n; int need; }; void incsema(Sema *s, int c) { qlock(&s->data); s->n += c; if(s->need > 0 && s->n >= s->need){ rendezvous(s, 0); s->need = 0; } qunlock(&s->data); } void decsema(Sema *s, int c) { qlock(&s->wait); qlock(&s->data); if(s->n < c){ s->need = c; qunlock(&s->data); rendezvous(s, 0); qlock(&s->data); } assert(s->n >= c); s->n -= c; qunlock(&s->data); qunlock(&s->wait); } int candecsema(Sema *s, int c) { int ret; if(!canqlock(&s->wait)) return 0; qlock(&s->data); /* won't block for long */ if(s->n >= c){ ret = 1; s->n -= c; }else ret = 0; qunlock(&s->data); qunlock(&s->wait); return ret; }