summaryrefslogtreecommitdiffstats
path: root/src/lib9/rendez-signal.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-09-17 03:34:32 +0000
committerrsc <devnull@localhost>2004-09-17 03:34:32 +0000
commitbcf527a98e295548629620a7cb06ada951db7822 (patch)
tree0c459268d6391745a7acc3fefb82ba1e62ed858e /src/lib9/rendez-signal.c
parent06bb4ed20d855b60e39c1125d8d715ba8892265b (diff)
downloadplan9port-bcf527a98e295548629620a7cb06ada951db7822.tar.gz
plan9port-bcf527a98e295548629620a7cb06ada951db7822.zip
Continue switching library over to pthreads when possible.
Tprimes works on Linux 2.6. You can only have 128 procs though.
Diffstat (limited to 'src/lib9/rendez-signal.c')
-rw-r--r--src/lib9/rendez-signal.c199
1 files changed, 31 insertions, 168 deletions
diff --git a/src/lib9/rendez-signal.c b/src/lib9/rendez-signal.c
index 5709dd76..e2abc3d3 100644
--- a/src/lib9/rendez-signal.c
+++ b/src/lib9/rendez-signal.c
@@ -1,58 +1,9 @@
-/*
- NAME
- rendezvous - user level process synchronization
-
- SYNOPSIS
- ulong rendezvous(ulong tag, ulong value)
-
- DESCRIPTION
- The rendezvous system call allows two processes to synchro-
- nize and exchange a value. In conjunction with the shared
- memory system calls (see segattach(2) and fork(2)), it
- enables parallel programs to control their scheduling.
-
- Two processes wishing to synchronize call rendezvous with a
- common tag, typically an address in memory they share. One
- process will arrive at the rendezvous first; it suspends
- execution until a second arrives. When a second process
- meets the rendezvous the value arguments are exchanged
- between the processes and returned as the result of the
- respective rendezvous system calls. Both processes are
- awakened when the rendezvous succeeds.
-
- The set of tag values which two processes may use to
- rendezvous-their tag space-is inherited when a process
- forks, unless RFREND is set in the argument to rfork; see
- fork(2).
-
- If a rendezvous is interrupted the return value is ~0, so
- that value should not be used in normal communication.
-
- * This simulates rendezvous with shared memory, sigsuspend, and SIGUSR1.
- */
-
#include <u.h>
#include <signal.h>
#include <libc.h>
#define DBG 0
-enum
-{
- VOUSHASH = 257,
-};
-
-typedef struct Vous Vous;
-struct Vous
-{
- Vous *link;
- int pid;
- int wokeup;
- ulong tag;
- ulong val1; /* value for the sleeper */
- ulong val2; /* value for the waker */
-};
-
static void
ign(int x)
{
@@ -73,128 +24,40 @@ ignusr1(int restart)
sigaction(SIGUSR1, &sa, nil);
}
-static Vous vouspool[2048];
-static int nvousused;
-static Vous *vousfree;
-static Vous *voushash[VOUSHASH];
-static Lock vouslock;
-
-static Vous*
-getvous(void)
-{
- Vous *v;
-
- if(vousfree){
- v = vousfree;
- vousfree = v->link;
- }else if(nvousused < nelem(vouspool))
- v = &vouspool[nvousused++];
- else{
- fprint(2, "rendezvous: out of vous!\n");
- abort();
- }
- return v;
-}
-
-static void
-putvous(Vous *v)
-{
- v->link = vousfree;
- vousfree = v;
-}
-
-static Vous*
-findvous(ulong tag)
-{
- int h;
- Vous *v, **l;
-
- h = tag%VOUSHASH;
- for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){
- if(v->tag == tag){
- *l = v->link;
- v->link = nil;
- return v;
- }
- }
- return nil;
-}
-
-static Vous*
-mkvous(ulong tag)
+void
+_procsleep(_Procrend *r)
{
- Vous *v;
- int h;
+ sigset_t mask;
- h = tag%VOUSHASH;
- v = getvous();
- v->link = voushash[h];
- v->tag = tag;
- voushash[h] = v;
- return v;
+ /*
+ * Go to sleep.
+ *
+ * Block USR1, set the handler to interrupt system calls,
+ * unlock the vouslock so our waker can wake us,
+ * and then suspend.
+ */
+ r->asleep = 1;
+ r->pid = getpid();
+
+ sigprocmask(SIG_SETMASK, nil, &mask);
+ sigaddset(&mask, SIGUSR1);
+ sigprocmask(SIG_SETMASK, &mask, nil);
+ ignusr1(0);
+ unlock(r->l);
+ sigdelset(&mask, SIGUSR1);
+ sigsuspend(&mask);
+
+ /*
+ * We're awake. Make USR1 not interrupt system calls.
+ */
+ ignusr1(1);
+ assert(r->asleep == 0);
}
-ulong
-rendezvous(ulong tag, ulong val)
+void
+_procwakeup(_Procrend *r)
{
- int vpid, pid;
- ulong rval;
- Vous *v;
- sigset_t mask;
-
- pid = getpid();
- lock(&vouslock);
- if((v = findvous(tag)) == nil){
- /*
- * Go to sleep.
- *
- * Block USR1, set the handler to interrupt system calls,
- * unlock the vouslock so our waker can wake us,
- * and then suspend.
- */
- v = mkvous(tag);
- v->pid = pid;
- v->val2 = val;
- v->wokeup = 0;
- sigprocmask(SIG_SETMASK, nil, &mask);
- sigaddset(&mask, SIGUSR1);
- sigprocmask(SIG_SETMASK, &mask, nil);
- ignusr1(0);
- if(DBG) fprint(2, "%d rv(%lux, %lux) -> s\n", pid, tag, val);
- unlock(&vouslock);
- sigdelset(&mask, SIGUSR1);
- sigsuspend(&mask);
-
- /*
- * We're awake. Make USR1 not interrupt system calls.
- * Were we awakened or interrupted?
- */
- ignusr1(1);
- lock(&vouslock);
- if(v->wokeup){
- rval = v->val1;
- if(DBG) fprint(2, "%d rv(%lux, %lux) -> g %lux\n", pid, tag, val, rval);
- }else{
- if(findvous(tag) != v){
- fprint(2, "rendezvous: interrupted but not found in hash table\n");
- abort();
- }
- rval = ~(ulong)0;
- if(DBG) fprint(2, "%d rv(%lux, %lux) -> g i\n", pid, tag, val);
- }
- putvous(v);
- unlock(&vouslock);
- }else{
- /*
- * Wake up sleeper.
- */
- rval = v->val2;
- v->val1 = val;
- vpid = v->pid;
- v->wokeup = 1;
- if(DBG) fprint(2, "%d rv(%lux, %lux) -> g %lux, w %d\n", pid, tag, val, rval, vpid);
- unlock(&vouslock);
- kill(vpid, SIGUSR1);
- }
- return rval;
+ r->asleep = 0;
+ assert(r->pid >= 1);
+ kill(r->pid, SIGUSR1);
}