aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/acme/exec.c2
-rw-r--r--src/cmd/acme/rows.c4
-rw-r--r--src/cmd/acme/text.c5
-rw-r--r--src/lib9/rendez-futex.c167
-rw-r--r--src/libdraw/md-alloc.c8
-rw-r--r--src/libfs/fs.c14
-rw-r--r--src/libfs/ns.c3
-rw-r--r--src/libthread/fdwait.c8
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);