diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/acme/exec.c | 2 | ||||
-rw-r--r-- | src/cmd/acme/rows.c | 4 | ||||
-rw-r--r-- | src/cmd/acme/text.c | 5 | ||||
-rw-r--r-- | src/lib9/rendez-futex.c | 167 | ||||
-rw-r--r-- | src/libdraw/md-alloc.c | 8 | ||||
-rw-r--r-- | src/libfs/fs.c | 14 | ||||
-rw-r--r-- | src/libfs/ns.c | 3 | ||||
-rw-r--r-- | src/libthread/fdwait.c | 8 |
8 files changed, 202 insertions, 9 deletions
diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c index 7dc1e88b..3bc10371 100644 --- a/src/cmd/acme/exec.c +++ b/src/cmd/acme/exec.c @@ -1308,7 +1308,7 @@ runproc(void *argvp) name[e-t] = 0; e = utfrrune(name, '/'); if(e) - strcpy(name, e+1); + memmove(name, e+1, strlen(e+1)+1); /* strcpy but overlaps */ strcat(name, " "); /* add blank here for ease in waittask */ c->name = bytetorune(name, &c->nname); free(name); diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c index 11014c2c..9fa54248 100644 --- a/src/cmd/acme/rows.c +++ b/src/cmd/acme/rows.c @@ -663,12 +663,12 @@ rowload(Row *row, char *file, int initing) break; wincleartag(w); textinsert(&w->tag, w->tag.file->b.nc, r+n+1, nr-(n+1), TRUE); - free(r); if(ndumped >= 0){ /* simplest thing is to put it in a file and load that */ sprint(buf, "/tmp/d%d.%.4sacme", getpid(), getuser()); fd = create(buf, OWRITE|ORCLOSE, 0600); if(fd < 0){ + free(r); warning(nil, "can't create temp file: %r\n"); goto Rescue2; } @@ -679,6 +679,7 @@ rowload(Row *row, char *file, int initing) if(rune == '\n') line++; if(rune == (Rune)Beof){ + free(r); Bterm(bout); free(bout); close(fd); @@ -696,6 +697,7 @@ rowload(Row *row, char *file, int initing) winsettag(w); }else if(dumpid==0 && r[ns+1]!='+' && r[ns+1]!='-') get(&w->body, nil, nil, FALSE, XXX, nil, 0); + free(r); if(fontr){ fontx(&w->body, nil, nil, 0, 0, fontr, nfontr); free(fontr); diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c index aa58be1a..37613d80 100644 --- a/src/cmd/acme/text.c +++ b/src/cmd/acme/text.c @@ -963,8 +963,11 @@ textshow(Text *t, uint q0, uint q1, int doselect) int nl; uint q; - if(t->what != Body) + if(t->what != Body){ + if(doselect) + textsetselect(t, q0, q1); return; + } if(t->w!=nil && t->fr.maxlines==0) colgrow(t->col, t->w, 1); if(doselect) diff --git a/src/lib9/rendez-futex.c b/src/lib9/rendez-futex.c new file mode 100644 index 00000000..7d5e21eb --- /dev/null +++ b/src/lib9/rendez-futex.c @@ -0,0 +1,167 @@ +/* + 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, pause, and SIGUSR1. + */ + +#include <u.h> +typedef u32int u32; +#include <errno.h> +#include <sys/time.h> +#define __user +#include <linux/linkage.h> +#include <linux/futex.h> +#include <libc.h> + +enum +{ + VOUSHASH = 257, +}; + +typedef struct Vous Vous; +struct Vous +{ + Vous *link; + Lock lk; + int pid; + ulong val; + ulong tag; +}; + +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 + abort(); + return v; +} + +static void +putvous(Vous *v) +{ + lock(&vouslock); + v->link = vousfree; + vousfree = v; + unlock(&vouslock); +} + +static Vous* +findvous(ulong tag, ulong val, int pid) +{ + int h; + Vous *v, **l; + + lock(&vouslock); + h = tag%VOUSHASH; + for(l=&voushash[h], v=*l; v; l=&(*l)->link, v=*l){ + if(v->tag == tag){ + *l = v->link; + unlock(&vouslock); + return v; + } + } + v = getvous(); + v->pid = pid; + v->link = voushash[h]; + v->val = val; + v->tag = tag; + lock(&v->lk); + voushash[h] = v; + unlock(&vouslock); + return v; +} + +#define DBG 0 +ulong +rendezvous(ulong tag, ulong val) +{ + int me, vpid; + ulong rval; + Vous *v; + + me = getpid(); + v = findvous(tag, val, me); + if(v->pid == me){ + if(DBG)fprint(2, "pid is %d tag %lux, sleeping\n", me, tag); + /* + * No rendezvous partner was found; the next guy + * through will find v and wake us, so we must go + * to sleep. + * + * To go to sleep: + * 1. disable USR1 signals. + * 2. unlock v->lk (tells waker okay to signal us). + * 3. atomically suspend and enable USR1 signals. + * + * The call to ignusr1() could be done once at + * process creation instead of every time through rendezvous. + */ + v->val = val; + unlock(&v->lk); + while(sys_futex((u32int*)&v->tag, FUTEX_WAIT, tag, nil, nil) < 0 && errno==EINTR) + ; + rval = v->val; + if(DBG)fprint(2, "pid is %d, awake\n", me); + putvous(v); + }else{ + /* + * Found someone to meet. Wake him: + * + * A. lock v->lk (waits for him to get to his step 2) + * B. send a USR1 + * + * He won't get the USR1 until he suspends, which + * means it must wake him up (it can't get delivered + * before he sleeps). + */ + vpid = v->pid; + lock(&v->lk); + rval = v->val; + v->val = val; + v->tag++; + unlock(&v->lk); + sys_futex((u32int*)&v->tag, FUTEX_WAKE, 1, nil, nil); + } + return rval; +} + diff --git a/src/libdraw/md-alloc.c b/src/libdraw/md-alloc.c index 801c3930..b4204f4e 100644 --- a/src/libdraw/md-alloc.c +++ b/src/libdraw/md-alloc.c @@ -86,7 +86,13 @@ _allocmemimage(Rectangle r, u32int chan) return nil; md->ref = 1; - md->base = poolalloc(imagmem, (2+nw)*sizeof(u32int)); + /* + * The first two words are the md and the callerpc. + * Then nw words of data. + * The final word lets the drawing routines be a little + * sloppy about reading past the end of the block. + */ + md->base = poolalloc(imagmem, (2+nw+1)*sizeof(u32int)); if(md->base == nil){ free(md); return nil; diff --git a/src/libfs/fs.c b/src/libfs/fs.c index 31515250..a42af96b 100644 --- a/src/libfs/fs.c +++ b/src/libfs/fs.c @@ -86,19 +86,27 @@ fsunmount(Fsys *fs) void _fsdecref(Fsys *fs) { - Fid *f, *next; + Fid *f, **l, *next; qlock(&fs->lk); --fs->ref; //fprint(2, "fsdecref %p to %d\n", fs, fs->ref); if(fs->ref == 0){ close(fs->fd); + /* trim the list down to just the first in each chunk */ + for(l=&fs->freefid; *l; ){ + if((*l)->fid%Fidchunk == 0) + l = &(*l)->next; + else + *l = (*l)->next; + } + /* now free the list */ for(f=fs->freefid; f; f=next){ next = f->next; - if(f->fid%Fidchunk == 0) - free(f); + free(f); } free(fs); + return; } qunlock(&fs->lk); } diff --git a/src/libfs/ns.c b/src/libfs/ns.c index 28c9d1cf..763080ba 100644 --- a/src/libfs/ns.c +++ b/src/libfs/ns.c @@ -23,8 +23,11 @@ nsmount(char *name, char *aname) fd = dial(addr, 0, 0, 0); if(fd < 0){ werrstr("dial %s: %r", addr); + free(addr); return nil; } + free(addr); + fcntl(fd, F_SETFL, FD_CLOEXEC); fs = fsmount(fd, aname); diff --git a/src/libthread/fdwait.c b/src/libthread/fdwait.c index e583da60..b544f16d 100644 --- a/src/libthread/fdwait.c +++ b/src/libthread/fdwait.c @@ -174,8 +174,8 @@ _threadfdwait(int fd, int rw, ulong pc) struct { Channel c; - Alt *qentry[2]; ulong x; + Alt *qentry[2]; } s; threadfdwaitsetup(); @@ -214,11 +214,15 @@ threadsleep(int ms) struct { Channel c; ulong x; + Alt *qentry[2]; } s; threadfdwaitsetup(); chaninit(&s.c, sizeof(ulong), 1); - + s.c.qentry = (volatile Alt**)s.qentry; + s.c.nentry = 2; + memset(s.qentry, 0, sizeof s.qentry); + sleepchan[nsleep] = &s.c; sleeptime[nsleep++] = p9nsec()/1000000+ms; recvul(&s.c); |