From 4c54893156cf2489081fe63eb37a0e4d3ede1e05 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 12:06:34 -0500 Subject: devdraw: do not force-hide menu and dock during full screen on mac This hides the menu on dock on all screens which is more than we want. The code was added to fix a problem with Catalina that I can no longer reproduce, so I guess it works now. Fixes #336. --- src/cmd/devdraw/mac-screen.m | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m index e02a2524..5e23c43a 100644 --- a/src/cmd/devdraw/mac-screen.m +++ b/src/cmd/devdraw/mac-screen.m @@ -930,6 +930,13 @@ rpc_setmouse(Client *c, Point p) - (NSApplicationPresentationOptions)window:(id)arg willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions { + // The default for full-screen is to auto-hide the dock and menu bar, + // but the menu bar in particular comes back when the cursor is just + // near the top of the screen, which makes acme's top tag line very difficult to use. + // Disable the menu bar entirely. + // In theory this code disables the dock entirely too, but if you drag the mouse + // down far enough off the bottom of the screen the dock still unhides. + // That's OK. NSApplicationPresentationOptions o; o = proposedOptions; o &= ~(NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar); @@ -938,16 +945,21 @@ rpc_setmouse(Client *c, Point p) } - (void)windowWillEnterFullScreen:(NSNotification*)notification { - // TODO: This should only be done if the window - // is on the screen with the dock. - // But how can you tell which window has the dock? + // This is a heavier-weight way to make sure the menu bar and dock go away, + // but this affects all screens even though the app is running on full screen + // on only one screen, so it's not great. The behavior from the + // willUseFullScreenPresentationOptions seems to be enough for now. + /* [[NSApplication sharedApplication] setPresentationOptions:NSApplicationPresentationHideMenuBar | NSApplicationPresentationHideDock]; + */ } - (void)windowDidExitFullScreen:(NSNotification*)notification { + /* [[NSApplication sharedApplication] setPresentationOptions:NSApplicationPresentationDefault]; + */ } @end -- cgit v1.2.3 From 4ae529dbfe8573ae105d0d66f7f453c4f850fa1f Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 13:18:29 -0500 Subject: libdraw: use proper pipe for default font data May fix a deadlock / missing font on OpenBSD. Fixes #308. --- src/libdraw/getsubfont.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/libdraw/getsubfont.c b/src/libdraw/getsubfont.c index ec4ccfe3..1cc234ef 100644 --- a/src/libdraw/getsubfont.c +++ b/src/libdraw/getsubfont.c @@ -53,15 +53,25 @@ _getsubfont(Display *d, char *name) static int defaultpipe(void) { - int p[2]; + int p[2], pid; - // assuming defontdata (<5k) fits in pipe buffer. - // especially reasonable since p9pipe is actually - // a socket pair. + // Used to assume that defontdata (<5k) fit in the + // pipe buffer, especially since p9pipe is actually + // a socket pair. But OpenBSD in particular saw hangs, + // so feed the pipe it the "right" way with a subprocess. if(pipe(p) < 0) return -1; - write(p[1], defontdata, sizeof defontdata); - close(p[1]); + if((pid = fork()) < 0) { + close(p[0]); + close(p[1]); + return -1; + } + if(pid == 0) { + close(p[0]); + write(p[1], defontdata, sizeof defontdata); + close(p[1]); + _exit(0); + } return p[0]; } -- cgit v1.2.3 From 8c573cab6819c69142389d36b978b3c683771afe Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 12:40:09 -0500 Subject: libthread: use mmap to allocate OpenBSD stacks Should fix faults on OpenBSD. Fixes #218. Fixes #226. --- src/libthread/Darwin-x86_64-swapcontext.c | 8 ++++++++ src/libthread/stkmalloc.c | 13 +++++++++++++ src/libthread/stkmmap.c | 25 +++++++++++++++++++++++++ src/libthread/sysofiles.sh | 12 ++++++------ src/libthread/thread.c | 9 +++++++-- src/libthread/threadimpl.h | 2 ++ 6 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 src/libthread/stkmalloc.c create mode 100644 src/libthread/stkmmap.c (limited to 'src') diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c index 27931456..c29ddb5e 100644 --- a/src/libthread/Darwin-x86_64-swapcontext.c +++ b/src/libthread/Darwin-x86_64-swapcontext.c @@ -16,6 +16,14 @@ makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) va_end(arg); sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size); + /* + * Stack pointer at call instruction (before return address + * gets pushed) must be 16-byte aligned. + */ + if((uintptr)sp%4) + abort(); + while((uintptr)sp%16 != 0) + sp--; *--sp = 0; // fn's return address *--sp = (uintptr)fn; // return address of setcontext uc->mc.sp = (uintptr)sp; diff --git a/src/libthread/stkmalloc.c b/src/libthread/stkmalloc.c new file mode 100644 index 00000000..083aea1b --- /dev/null +++ b/src/libthread/stkmalloc.c @@ -0,0 +1,13 @@ +#include "threadimpl.h" + +void* +_threadstkalloc(int n) +{ + return malloc(n); +} + +void +_threadstkfree(void *v, int n) +{ + free(v); +} diff --git a/src/libthread/stkmmap.c b/src/libthread/stkmmap.c new file mode 100644 index 00000000..f4a24630 --- /dev/null +++ b/src/libthread/stkmmap.c @@ -0,0 +1,25 @@ +#include +#include +#include "threadimpl.h" + +#ifndef MAP_STACK +#define MAP_STACK 0 +#endif + +void* +_threadstkalloc(int n) +{ + void *p; + + p = mmap(nil, n, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_STACK, -1, 0); + if(p == (void*)-1) + return nil; + return p; +} + +void +_threadstkfree(void *v, int n) +{ + if(n > 0) + munmap(v, n); +} diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index 9eeea606..f76b975a 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -6,22 +6,22 @@ tag="$OBJTYPE-$SYSNAME-${SYSVERSION:-`uname -r`}-${CC9:-cc}" case "$tag" in *-Linux-2.[0-5]*) # will have to fix this for linux power pc - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-FreeBSD-[0-4].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-NetBSD-*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; *-Darwin-10.[5-6].* | *-Darwin-[89].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o stkmalloc.o ;; *-OpenBSD-*) - echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o + echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o ;; *) - echo pthread.o + echo pthread.o stkmalloc.o esac case "$OBJTYPE-$SYSNAME" in diff --git a/src/libthread/thread.c b/src/libthread/thread.c index d041efcc..2e654863 100644 --- a/src/libthread/thread.c +++ b/src/libthread/thread.c @@ -109,7 +109,7 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) ulong z; /* allocate the task and stack together */ - t = malloc(sizeof *t+stack); + t = malloc(sizeof *t); if(t == nil) sysfatal("threadalloc malloc: %r"); memset(t, 0, sizeof *t); @@ -122,7 +122,9 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) /* do a reasonable initialization */ if(stack == 0) return t; - t->stk = (uchar*)(t+1); + t->stk = _threadstkalloc(stack); + if(t->stk == nil) + sysfatal("threadalloc malloc stack: %r"); t->stksize = stack; memset(&t->context.uc, 0, sizeof t->context.uc); sigemptyset(&zero); @@ -353,6 +355,7 @@ Top: delthreadinproc(p, t); p->nthread--; /*print("nthread %d\n", p->nthread); */ + _threadstkfree(t->stk, t->stksize); free(t); } @@ -509,6 +512,8 @@ needstack(int n) _Thread *t; t = proc()->thread; + if(t->stk == nil) + return; if((char*)&t <= (char*)t->stk || (char*)&t - (char*)t->stk < 256+n){ diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 76ca57e5..6671f23c 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -209,3 +209,5 @@ extern void _threadsetupdaemonize(void); extern void _threaddodaemonize(char*); extern void _threadpexit(void); extern void _threaddaemonize(void); +extern void *_threadstkalloc(int); +extern void _threadstkfree(void*, int); -- cgit v1.2.3 From a0691bc460cbef889d017a640034f3321bd36b9d Mon Sep 17 00:00:00 2001 From: phonologus <59876118+phonologus@users.noreply.github.com> Date: Tue, 14 Jan 2020 19:52:18 +0000 Subject: tar: remove /bin/ when invoking compressors --- src/cmd/tar.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/cmd/tar.c b/src/cmd/tar.c index 61e9c4a6..6698675e 100644 --- a/src/cmd/tar.c +++ b/src/cmd/tar.c @@ -179,7 +179,6 @@ static int push(int fd, char *cmd, int input, Pushstate *ps) { int nfd, pifds[2]; - String *s; ps->open = 0; ps->fd = fd; @@ -197,11 +196,7 @@ push(int fd, char *cmd, int input, Pushstate *ps) dup(pifds[Rd], Stdin); close(pifds[input? Rd: Wr]); dup(fd, (input? Stdin: Stdout)); - s = s_new(); - if (cmd[0] != '/') - s_append(s, "/bin/"); - s_append(s, cmd); - execl(s_to_c(s), cmd, nil); + execl(cmd, cmd, nil); sysfatal("can't exec %s: %r", cmd); default: nfd = pifds[input? Rd: Wr]; -- cgit v1.2.3 From d28913a9e6609fef96f5baf6e9f4d5055ede744c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 16:38:34 -0500 Subject: acme: save/restore multiline tags in Dump/Load The dump substitutes each \n in a multiline tag with a 0xff byte. Since it is not valid UTF it cannot occur in an ordinary dump file. Old acmes will just read it in as an error rune. Fixes #135. Fixes #153. --- src/cmd/acme/rows.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c index 83c64594..7a64fabf 100644 --- a/src/cmd/acme/rows.c +++ b/src/cmd/acme/rows.c @@ -316,7 +316,7 @@ rowclean(Row *row) void rowdump(Row *row, char *file) { - int i, j, fd, m, n, dumped; + int i, j, fd, m, n, start, dumped; uint q0, q1; Biobuf *b; char *buf, *a, *fontname; @@ -434,9 +434,17 @@ rowdump(Row *row, char *file) m = min(RBUFSIZE, w->tag.file->b.nc); bufread(&w->tag.file->b, 0, r, m); n = 0; - while(nfile->b.nc; @@ -719,6 +727,10 @@ rowload(Row *row, char *file, int initing) if(l == nil) goto Rescue2; l[Blinelen(b)-1] = 0; + /* convert 0xff in multiline tag back to \n */ + for(i = 0; l[i] != 0; i++) + if((uchar)l[i] == 0xff) + l[i] = '\n'; r = bytetorune(l+5*12, &nr); ns = -1; for(n=0; n Date: Tue, 14 Jan 2020 18:03:05 -0500 Subject: lib9: make formatting lock-free again First use of . We will see if any supported systems don't have it yet. (C11 was so last decade.) Fixes #338. --- src/lib9/fmt/fmt.c | 165 ++++++++++++++++++++++--------------------------- src/lib9/fmt/fmtdef.h | 6 +- src/lib9/fmt/fmtlock.c | 14 +---- src/lib9/fmtlock2.c | 22 ++----- 4 files changed, 83 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/lib9/fmt/fmt.c b/src/lib9/fmt/fmt.c index 9c3f45d3..a86482c3 100644 --- a/src/lib9/fmt/fmt.c +++ b/src/lib9/fmt/fmt.c @@ -1,102 +1,107 @@ /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */ #include #include +#include #include "plan9.h" #include "fmt.h" #include "fmtdef.h" enum { - Maxfmt = 64 + Maxfmt = 128 }; typedef struct Convfmt Convfmt; struct Convfmt { int c; - volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */ + Fmts fmt; }; static struct { - /* lock by calling __fmtlock, __fmtunlock */ - int nfmt; + /* + * lock updates to fmt by calling __fmtlock, __fmtunlock. + * reads can start at nfmt and work backward without + * further locking. later fmtinstalls take priority over earlier + * ones because of the backwards loop. + * once installed, a format is never overwritten. + */ + _Atomic int nfmt; Convfmt fmt[Maxfmt]; -} fmtalloc; - -static Convfmt knownfmt[] = { - ' ', __flagfmt, - '#', __flagfmt, - '%', __percentfmt, - '\'', __flagfmt, - '+', __flagfmt, - ',', __flagfmt, - '-', __flagfmt, - 'C', __runefmt, /* Plan 9 addition */ - 'E', __efgfmt, -#ifndef PLAN9PORT - 'F', __efgfmt, /* ANSI only */ -#endif - 'G', __efgfmt, -#ifndef PLAN9PORT - 'L', __flagfmt, /* ANSI only */ -#endif - 'S', __runesfmt, /* Plan 9 addition */ - 'X', __ifmt, - 'b', __ifmt, /* Plan 9 addition */ - 'c', __charfmt, - 'd', __ifmt, - 'e', __efgfmt, - 'f', __efgfmt, - 'g', __efgfmt, - 'h', __flagfmt, -#ifndef PLAN9PORT - 'i', __ifmt, /* ANSI only */ -#endif - 'l', __flagfmt, - 'n', __countfmt, - 'o', __ifmt, - 'p', __ifmt, - 'r', __errfmt, - 's', __strfmt, -#ifdef PLAN9PORT - 'u', __flagfmt, -#else - 'u', __ifmt, -#endif - 'x', __ifmt, - 0, nil, +} fmtalloc = { + #ifdef PLAN9PORT + ATOMIC_VAR_INIT(27), + #else + ATOMIC_VAR_INIT(30), + #endif + { + {' ', __flagfmt}, + {'#', __flagfmt}, + {'%', __percentfmt}, + {'\'', __flagfmt}, + {'+', __flagfmt}, + {',', __flagfmt}, + {'-', __flagfmt}, + {'C', __runefmt}, /* Plan 9 addition */ + {'E', __efgfmt}, + #ifndef PLAN9PORT + {'F', __efgfmt}, /* ANSI only */ + #endif + {'G', __efgfmt}, + #ifndef PLAN9PORT + {'L', __flagfmt}, /* ANSI only */ + #endif + {'S', __runesfmt}, /* Plan 9 addition */ + {'X', __ifmt}, + {'b', __ifmt}, /* Plan 9 addition */ + {'c', __charfmt}, + {'d', __ifmt}, + {'e', __efgfmt}, + {'f', __efgfmt}, + {'g', __efgfmt}, + {'h', __flagfmt}, + #ifndef PLAN9PORT + {'i', __ifmt}, /* ANSI only */ + #endif + {'l', __flagfmt}, + {'n', __countfmt}, + {'o', __ifmt}, + {'p', __ifmt}, + {'r', __errfmt}, + {'s', __strfmt}, + #ifdef PLAN9PORT + {'u', __flagfmt}, + #else + {'u', __ifmt}, + #endif + {'x', __ifmt}, + } }; - int (*fmtdoquote)(int); /* - * __fmtwlock() must be set + * __fmtlock() must be set */ static int __fmtinstall(int c, Fmts f) { - Convfmt *p, *ep; + Convfmt *p; + int i; if(c<=0 || c>=65536) return -1; if(!f) f = __badfmt; - ep = &fmtalloc.fmt[fmtalloc.nfmt]; - for(p=fmtalloc.fmt; pc == c) - break; - - if(p == &fmtalloc.fmt[Maxfmt]) + i = atomic_load(&fmtalloc.nfmt); + if(i == Maxfmt) return -1; - + p = &fmtalloc.fmt[i]; + p->c = c; p->fmt = f; - if(p == ep){ /* installing a new format character */ - fmtalloc.nfmt++; - p->c = c; - } + atomic_store(&fmtalloc.nfmt, i+1); return 0; } @@ -106,43 +111,21 @@ fmtinstall(int c, int (*f)(Fmt*)) { int ret; - __fmtwlock(); + __fmtlock(); ret = __fmtinstall(c, f); - __fmtwunlock(); + __fmtunlock(); return ret; } static Fmts fmtfmt(int c) { - Convfmt *p, *ep, *kp; - - /* conflict-free check - common case */ - __fmtrlock(); - ep = &fmtalloc.fmt[fmtalloc.nfmt]; - for(p=fmtalloc.fmt; pc == c){ - __fmtrunlock(); + Convfmt *p, *ep; + + ep = &fmtalloc.fmt[atomic_load(&fmtalloc.nfmt)]; + for(p=ep; p-- > fmtalloc.fmt; ) + if(p->c == c) return p->fmt; - } - __fmtrunlock(); - - /* is this a predefined format char? */ - for(kp=knownfmt; kp->c; kp++){ - if(kp->c == c){ - __fmtwlock(); - /* double-check fmtinstall didn't happen */ - for(p=fmtalloc.fmt; pc == c){ - __fmtwunlock(); - return p->fmt; - } - } - __fmtinstall(kp->c, kp->fmt); - __fmtwunlock(); - return kp->fmt; - } - } return __badfmt; } diff --git a/src/lib9/fmt/fmtdef.h b/src/lib9/fmt/fmtdef.h index d547184d..2bafd36d 100644 --- a/src/lib9/fmt/fmtdef.h +++ b/src/lib9/fmt/fmtdef.h @@ -36,10 +36,8 @@ void * __fmtflush(Fmt *f, void *t, int len); int __fmtpad(Fmt *f, int n); double __fmtpow10(int n); int __fmtrcpy(Fmt *f, const void *vm, int n); -void __fmtrlock(void); -void __fmtrunlock(void); -void __fmtwlock(void); -void __fmtwunlock(void); +void __fmtlock(void); +void __fmtunlock(void); int __ifmt(Fmt *f); int __isInf(double d, int sign); int __isNaN(double d); diff --git a/src/lib9/fmt/fmtlock.c b/src/lib9/fmt/fmtlock.c index eb9cd845..cabe05f4 100644 --- a/src/lib9/fmt/fmtlock.c +++ b/src/lib9/fmt/fmtlock.c @@ -5,21 +5,11 @@ #include "fmtdef.h" void -__fmtrlock(void) +__fmtlock(void) { } void -__fmtrunlock(void) -{ -} - -void -__fmtwlock(void) -{ -} - -void -__fmtwunlock(void) +__fmtunlock(void) { } diff --git a/src/lib9/fmtlock2.c b/src/lib9/fmtlock2.c index b755daa3..d711e6d4 100644 --- a/src/lib9/fmtlock2.c +++ b/src/lib9/fmtlock2.c @@ -1,28 +1,16 @@ #include #include -static RWLock fmtlock; +static Lock fmtlock; void -__fmtrlock(void) +__fmtlock(void) { - rlock(&fmtlock); + lock(&fmtlock); } void -__fmtrunlock(void) +__fmtunlock(void) { - runlock(&fmtlock); -} - -void -__fmtwlock(void) -{ - wlock(&fmtlock); -} - -void -__fmtwunlock(void) -{ - wunlock(&fmtlock); + unlock(&fmtlock); } -- cgit v1.2.3 From 40d787ab1276f191bcf030748a954d6708d83228 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 18:05:51 -0500 Subject: libdraw: send hangup to process when window is lost This matches the Plan 9 behavior a bit better. Fixes #30. --- src/libdraw/mouse.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libdraw/mouse.c b/src/libdraw/mouse.c index 64a7f73d..382efae5 100644 --- a/src/libdraw/mouse.c +++ b/src/libdraw/mouse.c @@ -52,8 +52,12 @@ _ioproc(void *arg) one = 1; resized = 0; for(;;){ - if(_displayrdmouse(mc->display, &m, &resized) < 0) + if(_displayrdmouse(mc->display, &m, &resized) < 0) { + if(postnote(PNPROC, getpid(), "hangup") < 0) + fprint(2, "postnote: %r\n"); + sleep(10*1000); threadexitsall("mouse read error"); + } if(resized) send(mc->resizec, &one); send(mc->c, &m); -- cgit v1.2.3 From 1f799495e4aa89be5f32e3fcda8da342f3057f3c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 19:43:32 -0500 Subject: devdraw: notify window resize promptly on x11 Fixes #339. --- src/cmd/devdraw/devdraw.c | 5 +---- src/cmd/devdraw/devdraw.h | 1 + src/cmd/devdraw/mac-screen.m | 1 - src/cmd/devdraw/srv.c | 18 ++++++++++++++++++ src/cmd/devdraw/x11-screen.c | 16 ++++++++-------- 5 files changed, 28 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/cmd/devdraw/devdraw.c b/src/cmd/devdraw/devdraw.c index 086574ef..b4c373ad 100644 --- a/src/cmd/devdraw/devdraw.c +++ b/src/cmd/devdraw/devdraw.c @@ -55,10 +55,7 @@ gfx_replacescreenimage(Client *c, Memimage *m) _freememimage(om); } qunlock(&c->drawlk); - - qlock(&c->eventlk); - c->mouse.resized = 1; - qunlock(&c->eventlk); + gfx_mouseresized(c); } static void diff --git a/src/cmd/devdraw/devdraw.h b/src/cmd/devdraw/devdraw.h index 4980ed90..6829ab32 100644 --- a/src/cmd/devdraw/devdraw.h +++ b/src/cmd/devdraw/devdraw.h @@ -187,6 +187,7 @@ void gfx_keystroke(Client*, int); void gfx_main(void); void gfx_mousetrack(Client*, int, int, int, uint); void gfx_replacescreenimage(Client*, Memimage*); +void gfx_mouseresized(Client*); void gfx_started(void); // rpc_* routines are called on the RPC thread, diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m index 5e23c43a..4bc3f088 100644 --- a/src/cmd/devdraw/mac-screen.m +++ b/src/cmd/devdraw/mac-screen.m @@ -518,7 +518,6 @@ rpc_resizeimg(Client *c) - (void)resizeimg { [self initimg]; gfx_replacescreenimage(self.client, self.img); - [self sendmouse:0]; } - (void)windowDidResize:(NSNotification *)notification { diff --git a/src/cmd/devdraw/srv.c b/src/cmd/devdraw/srv.c index bfeb7c38..c98a865f 100644 --- a/src/cmd/devdraw/srv.c +++ b/src/cmd/devdraw/srv.c @@ -394,12 +394,30 @@ matchmouse(Client *c) } } +void +gfx_mouseresized(Client *c) +{ + gfx_mousetrack(c, -1, -1, -1, -1); +} + void gfx_mousetrack(Client *c, int x, int y, int b, uint ms) { Mouse *m; qlock(&c->eventlk); + if(x == -1 && y == -1 && b == -1 && ms == -1) { + Mouse *copy; + // repeat last mouse event for resize + if(c->mouse.ri == 0) + copy = &c->mouse.m[nelem(c->mouse.m)-1]; + else + copy = &c->mouse.m[c->mouse.ri-1]; + x = copy->xy.x; + y = copy->xy.y; + b = copy->buttons; + ms = copy->msec; + } if(x < c->mouserect.min.x) x = c->mouserect.min.x; if(x > c->mouserect.max.x) diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c index 8026e1e6..c3a6fa33 100644 --- a/src/cmd/devdraw/x11-screen.c +++ b/src/cmd/devdraw/x11-screen.c @@ -44,7 +44,7 @@ static Xwin* newxwin(Client *c) { Xwin *w; - + w = mallocz(sizeof *w, 1); if(w == nil) sysfatal("out of memory"); @@ -59,7 +59,7 @@ static Xwin* findxwin(XDrawable d) { Xwin *w, **l; - + for(l=&_x.windows; (w=*l) != nil; l=&w->next) { if(w->drawable == d) { /* move to front */ @@ -658,7 +658,7 @@ xattach(Client *client, char *label, char *winsize) _x.losefocus = XInternAtom(_x.display, "_9WM_LOSE_FOCUS", False); _x.wmprotos = XInternAtom(_x.display, "WM_PROTOCOLS", False); } - + atoms[0] = _x.takefocus; atoms[1] = _x.losefocus; XChangeProperty(_x.display, w->drawable, _x.wmprotos, XA_ATOM, 32, @@ -700,7 +700,7 @@ xattach(Client *client, char *label, char *winsize) _x.gcsimplesrc = xgc(w->screenpm, FillStippled, -1); _x.gczero = xgc(w->screenpm, -1, -1); _x.gcreplsrc = xgc(w->screenpm, FillTiled, -1); - + pmid = XCreatePixmap(_x.display, w->drawable, 1, 1, 1); _x.gcfill0 = xgc(pmid, FillSolid, 0); _x.gccopy0 = xgc(pmid, -1, -1); @@ -729,7 +729,7 @@ rpc_setlabel(Client *client, char *label) { Xwin *w = (Xwin*)client->view; XTextProperty name; - + /* * Label and other properties required by ICCCCM. */ @@ -1032,7 +1032,7 @@ _xreplacescreenimage(Client *client) XDrawable pixmap; Rectangle r; Xwin *w; - + w = (Xwin*)client->view; r = w->newscreenr; pixmap = XCreatePixmap(_x.display, w->drawable, Dx(r), Dy(r), _x.depth); @@ -1527,7 +1527,7 @@ __xputsnarf(char *data) { XButtonEvent e; Xwin *w; - + if(strlen(data) >= SnarfSize) return; qlock(&clip.lk); @@ -1730,7 +1730,7 @@ rpc_bouncemouse(Client *c, Mouse m) Xwin *w = (Xwin*)c->view; XButtonEvent e; XWindow dw; - + xlock(); e.type = ButtonPress; e.state = 0; -- cgit v1.2.3 From 5c06214952017d03f5e36bd1fbf25c1969922d80 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 14 Jan 2020 19:46:47 -0500 Subject: venti/buildindex: fix hang on large indexes Fixes #93. --- src/cmd/venti/srv/buildindex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/venti/srv/buildindex.c b/src/cmd/venti/srv/buildindex.c index faf4b414..540f0fdc 100644 --- a/src/cmd/venti/srv/buildindex.c +++ b/src/cmd/venti/srv/buildindex.c @@ -164,7 +164,7 @@ threadmain(int argc, char *argv[]) } /* wait for arena procs to finish */ - for(nfinish=0; nfinish Date: Wed, 15 Jan 2020 10:57:41 +0300 Subject: 9pfuse: update errortab --- src/cmd/9pfuse/errstr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cmd/9pfuse/errstr.c b/src/cmd/9pfuse/errstr.c index e3a122e4..ef5da00f 100644 --- a/src/cmd/9pfuse/errstr.c +++ b/src/cmd/9pfuse/errstr.c @@ -21,6 +21,7 @@ static Error errortab[] = { { "exist", ENOENT }, { "no such", ENOENT }, { "not found", ENOENT }, + { "not implemented", ENOSYS}, { "input/output", EIO }, { "timeout", ETIMEDOUT }, { "timed out", ETIMEDOUT }, @@ -42,6 +43,7 @@ static Error errortab[] = { { "invalid", EINVAL }, { "read-only", EROFS }, { "read only", EROFS }, + { "stale ", ESTALE}, #ifdef EPROTO { "proto", EPROTO }, #else -- cgit v1.2.3 From a9b462061c05f8cd4e1f85b05522770293c8a468 Mon Sep 17 00:00:00 2001 From: markvanatten Date: Wed, 15 Jan 2020 14:43:01 +0100 Subject: winwatch: port based Plan 9 winwatch Port of Plan 9's winwatch(1). --- src/cmd/rio/mkfile | 2 +- src/cmd/rio/winwatch.c | 538 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 src/cmd/rio/winwatch.c (limited to 'src') diff --git a/src/cmd/rio/mkfile b/src/cmd/rio/mkfile index 8b8ea46a..20202e22 100644 --- a/src/cmd/rio/mkfile +++ b/src/cmd/rio/mkfile @@ -16,7 +16,7 @@ RIOFILES=\ CFLAGS=$CFLAGS -DDEBUG HFILES=dat.h fns.h -TARG=rio xshove +TARG=rio winwatch xshove # need to add lib64 when it exists (on x86-64), but # Darwin complains about the nonexistant directory diff --git a/src/cmd/rio/winwatch.c b/src/cmd/rio/winwatch.c new file mode 100644 index 00000000..66ec8cbe --- /dev/null +++ b/src/cmd/rio/winwatch.c @@ -0,0 +1,538 @@ +/* slightly modified from +https://github.com/fhs/misc/blob/master/cmd/winwatch/winwatch.c +so as to deal with memory leaks and certain X errors */ + +#include +#include +#include +#include +#include +#include +#include "../devdraw/x11-inc.h" + +AUTOLIB(X11); + +typedef struct Win Win; +struct Win { + XWindow n; + int dirty; + char *label; + Rectangle r; +}; + +XDisplay *dpy; +XWindow root; +Atom net_active_window; +Reprog *exclude = nil; +Win *win; +int nwin; +int mwin; +int onwin; +int rows, cols; +int sortlabels; +int showwmnames; +Font *font; +Image *lightblue; + +XErrorHandler oldxerrorhandler; + +enum { + PAD = 3, + MARGIN = 5 +}; + +static jmp_buf savebuf; + +int +winwatchxerrorhandler(XDisplay *disp, XErrorEvent *xe) +{ + char buf[100]; + + XGetErrorText(disp, xe->error_code, buf, 100); + fprintf(stderr, "winwatch: X error %s, request code %d\n", buf, + xe->request_code); + XFlush(disp); + XSync(disp, False); + XSetErrorHandler(oldxerrorhandler); + longjmp(savebuf, 1); +} + +void* +erealloc(void *v, ulong n) +{ + v = realloc(v, n); + if (v == nil) + sysfatal("out of memory reallocating"); + return v; +} + +char* +estrdup(char *s) +{ + s = strdup(s); + if (s == nil) + sysfatal("out of memory allocating"); + return s; +} + +char* +getproperty(XWindow w, Atom a) +{ + uchar *p; + int fmt; + Atom type; + ulong n, dummy; + int s; + + n = 100; + p = nil; + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetWindowProperty(dpy, w, a, 0, 100L, 0, + AnyPropertyType, &type, &fmt, &n, &dummy, &p); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + + if (s == 0) + return (char *) p; + else { + free(p); + return nil; + } +} + +XWindow +findname(XWindow w) +{ + int i; + uint nxwin; + XWindow dw1, dw2, *xwin; + char *p; + int s; + Atom net_wm_name; + + p = getproperty(w, XA_WM_NAME); + if (p) { + free(p); + return w; + } + + net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); + p = getproperty(w, net_wm_name); + if (p) { + free(p); + return w; + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + if (s == 0) { + if (xwin != NULL) + XFree(xwin); + return 0; + } + + for (i = 0; i < nxwin; i++) { + w = findname(xwin[i]); + if (w != 0) { + XFree(xwin); + return w; + } + } + + XFree(xwin); + + return 0; +} + +int +wcmp(const void *w1, const void *w2) +{ + return *(XWindow *) w1 - *(XWindow *) w2; +} + +/* unicode-aware case-insensitive strcmp, taken from golang’s gc/subr.c */ + +int +_cistrcmp(char *p, char *q) +{ + Rune rp, rq; + + while(*p || *q) { + if(*p == 0) + return +1; + if(*q == 0) + return -1; + p += chartorune(&rp, p); + q += chartorune(&rq, q); + rp = tolowerrune(rp); + rq = tolowerrune(rq); + if(rp < rq) + return -1; + if(rp > rq) + return +1; + } + return 0; +} + +int +winlabelcmp(const void *w1, const void *w2) +{ + const Win *p1 = (Win *) w1; + const Win *p2 = (Win *) w2; + return _cistrcmp(p1->label, p2->label); +} + +void +refreshwin(void) +{ + XWindow dw1, dw2, *xwin; + XClassHint class; + XWindowAttributes attr; + char *label; + char *wmname; + int i, nw; + uint nxwin; + Status s; + Atom net_wm_name; + + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + if (s == 0) { + if (xwin != NULL) + XFree(xwin); + return; + } + qsort(xwin, nxwin, sizeof(xwin[0]), wcmp); + + nw = 0; + for (i = 0; i < nxwin; i++) { + memset(&attr, 0, sizeof attr); + xwin[i] = findname(xwin[i]); + if (xwin[i] == 0) + continue; + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetWindowAttributes(dpy, xwin[i], &attr); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + if (s == 0) + continue; + if (attr.width <= 0 || attr.override_redirect + || attr.map_state != IsViewable) + continue; + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetClassHint(dpy, xwin[i], &class); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + if (s == 0) + continue; + + if (exclude != nil && regexec(exclude, class.res_name, nil, 0)) { + free(class.res_name); + free(class.res_class); + continue; + } + + net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); + wmname = getproperty(xwin[i], net_wm_name); + + if (wmname == nil) { + wmname = getproperty(xwin[i], XA_WM_NAME); + if (wmname == nil) { + free(class.res_name); + free(class.res_class); + continue; + } + } + + if (showwmnames == 1) + label = wmname; + else + label = class.res_name; + + if (nw < nwin && win[nw].n == xwin[i] + && strcmp(win[nw].label, label) == 0) { + nw++; + free(wmname); + free(class.res_name); + free(class.res_class); + continue; + } + + if (nw < nwin) { + free(win[nw].label); + win[nw].label = nil; + } + + if (nw >= mwin) { + mwin += 8; + win = erealloc(win, mwin * sizeof(win[0])); + } + win[nw].n = xwin[i]; + win[nw].label = estrdup(label); + win[nw].dirty = 1; + win[nw].r = Rect(0, 0, 0, 0); + free(wmname); + free(class.res_name); + free(class.res_class); + nw++; + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + XFree(xwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + while (nwin > nw) + free(win[--nwin].label); + nwin = nw; + + if (sortlabels == 1) + qsort(win, nwin, sizeof(struct Win), winlabelcmp); + + return; +} + +void +drawnowin(int i) +{ + Rectangle r; + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, + font->height); + r = rectaddpt(rectaddpt + (r, + Pt(MARGIN + (PAD + Dx(r)) * (i / rows), + MARGIN + (PAD + Dy(r)) * (i % rows))), + screen->r.min); + draw(screen, insetrect(r, -1), lightblue, nil, ZP); +} + +void +drawwin(int i) +{ + draw(screen, win[i].r, lightblue, nil, ZP); + _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, + font, win[i].label, nil, strlen(win[i].label), + win[i].r, nil, ZP, SoverD); + border(screen, win[i].r, 1, display->black, ZP); + win[i].dirty = 0; +} + +int +geometry(void) +{ + int i, ncols, z; + Rectangle r; + + z = 0; + rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD); + if (rows * cols < nwin || rows * cols >= nwin * 2) { + ncols = nwin <= 0 ? 1 : (nwin + rows - 1) / rows; + if (ncols != cols) { + cols = ncols; + z = 1; + } + } + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, + font->height); + for (i = 0; i < nwin; i++) + win[i].r = + rectaddpt(rectaddpt + (r, + Pt(MARGIN + (PAD + Dx(r)) * (i / rows), + MARGIN + (PAD + Dy(r)) * (i % rows))), + screen->r.min); + + return z; +} + +void +redraw(Image *screen, int all) +{ + int i; + + all |= geometry(); + if (all) + draw(screen, screen->r, lightblue, nil, ZP); + for (i = 0; i < nwin; i++) + if (all || win[i].dirty) + drawwin(i); + if (!all) + for (; i < onwin; i++) + drawnowin(i); + + onwin = nwin; +} + +void +eresized(int new) +{ + if (new && getwindow(display, Refmesg) < 0) + fprint(2, "can't reattach to window"); + geometry(); + redraw(screen, 1); +} + + +void +selectwin(XWindow win) +{ + XEvent ev; + long mask; + + memset(&ev, 0, sizeof ev); + ev.xclient.type = ClientMessage; + ev.xclient.serial = 0; + ev.xclient.send_event = True; + ev.xclient.message_type = net_active_window; + ev.xclient.window = win; + ev.xclient.format = 32; + mask = SubstructureRedirectMask | SubstructureNotifyMask; + + XSendEvent(dpy, root, False, mask, &ev); + XMapRaised(dpy, win); + XSync(dpy, False); +} + + +void +click(Mouse m) +{ + int i, j; + + if (m.buttons == 0 || (m.buttons & ~4)) + return; + + for (i = 0; i < nwin; i++) + if (ptinrect(m.xy, win[i].r)) + break; + if (i == nwin) + return; + + do + m = emouse(); + while (m.buttons == 4); + + if (m.buttons != 0) { + do + m = emouse(); + while (m.buttons); + return; + } + + for (j = 0; j < nwin; j++) + if (ptinrect(m.xy, win[j].r)) + break; + if (j != i) + return; + + selectwin(win[i].n); +} + +void +usage(void) +{ + fprint(2, + "usage: winwatch [-e exclude] [-W winsize] [-f font] [-n] [-s]\n"); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + char *fontname; + int Etimer; + Event e; + + sortlabels = 0; + showwmnames = 0; + + fontname = "/lib/font/bit/lucsans/unicode.8.font"; + + ARGBEGIN { + case 'W': + winsize = EARGF(usage()); + break; + case 'f': + fontname = EARGF(usage()); + break; + case 'e': + exclude = regcomp(EARGF(usage())); + if (exclude == nil) + sysfatal("Bad regexp"); + break; + case 's': + sortlabels = 1; + break; + case 'n': + showwmnames = 1; + break; + default: + usage(); + } + ARGEND if (argc) + usage(); + + /* moved up from original winwatch.c for p9p because there can be only one but we want to restart when needed */ + einit(Emouse | Ekeyboard); + Etimer = etimer(0, 1000); + + dpy = XOpenDisplay(""); + + if (dpy == nil) + sysfatal("open display: %r"); + + root = DefaultRootWindow(dpy); + net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + + initdraw(0, 0, "winwatch"); + lightblue = allocimagemix(display, DPalebluegreen, DWhite); + if (lightblue == nil) + sysfatal("allocimagemix: %r"); + if ((font = openfont(display, fontname)) == nil) + sysfatal("font '%s' not found", fontname); + + + /* reentry point upon X server errors */ + setjmp(savebuf); + + refreshwin(); + redraw(screen, 1); + + for (;;) { + switch (eread(Emouse | Ekeyboard | Etimer, &e)) { + case Ekeyboard: + if (e.kbdc == 0x7F || e.kbdc == 'q') + exits(0); + break; + case Emouse: + if (e.mouse.buttons) + click(e.mouse); + /* fall through */ + default: /* Etimer */ + refreshwin(); + redraw(screen, 0); + break; + } + } +} -- cgit v1.2.3 From 0ac4bfee32fce9dc336751aa219ca4dbdf3e8ecd Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Wed, 15 Jan 2020 14:15:31 +0000 Subject: clock: Remove unused static variable in clock.c `struct Tm tms` was set but never referenced; noticed in a compiler warning. Remove it. Signed-off-by: Dan Cross --- src/cmd/draw/clock.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/cmd/draw/clock.c b/src/cmd/draw/clock.c index b804e1f4..b5d028b6 100644 --- a/src/cmd/draw/clock.c +++ b/src/cmd/draw/clock.c @@ -25,7 +25,6 @@ redraw(Image *screen) static int rad; int i; int anghr, angmin; - static Tm tms; static Tm ntms; ntm = time(0); @@ -36,7 +35,6 @@ redraw(Image *screen) anghr = 90-(ntms.hour*5 + ntms.min/12)*6; angmin = 90-ntms.min*6; tm = ntm; - tms = ntms; r = screen->r; c = divpt(addpt(r.min, r.max), 2); rad = Dx(r) < Dy(r) ? Dx(r) : Dy(r); -- cgit v1.2.3 From 6510a2d3530132753a6a1dfb2589e9ad82bc271c Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Wed, 15 Jan 2020 14:47:39 +0000 Subject: winwatch: Plan 9-ify. This is new code, and custom to plan9port. Make it conform more closely to plan9 style. Signed-off-by: Dan Cross --- src/cmd/rio/winwatch.c | 838 ++++++++++++++++++++++++------------------------- 1 file changed, 412 insertions(+), 426 deletions(-) (limited to 'src') diff --git a/src/cmd/rio/winwatch.c b/src/cmd/rio/winwatch.c index 66ec8cbe..1a93e78c 100644 --- a/src/cmd/rio/winwatch.c +++ b/src/cmd/rio/winwatch.c @@ -1,23 +1,25 @@ -/* slightly modified from -https://github.com/fhs/misc/blob/master/cmd/winwatch/winwatch.c -so as to deal with memory leaks and certain X errors */ +/* + * slightly modified from + * https://github.com/fhs/misc/blob/master/cmd/winwatch/winwatch.c + * so as to deal with memory leaks and certain X errors + */ #include #include #include #include #include -#include +#include #include "../devdraw/x11-inc.h" AUTOLIB(X11); typedef struct Win Win; struct Win { - XWindow n; - int dirty; - char *label; - Rectangle r; + XWindow n; + int dirty; + char *label; + Rectangle r; }; XDisplay *dpy; @@ -37,502 +39,486 @@ Image *lightblue; XErrorHandler oldxerrorhandler; enum { - PAD = 3, - MARGIN = 5 + PAD = 3, + MARGIN = 5 }; static jmp_buf savebuf; -int +int winwatchxerrorhandler(XDisplay *disp, XErrorEvent *xe) { - char buf[100]; - - XGetErrorText(disp, xe->error_code, buf, 100); - fprintf(stderr, "winwatch: X error %s, request code %d\n", buf, - xe->request_code); - XFlush(disp); - XSync(disp, False); - XSetErrorHandler(oldxerrorhandler); - longjmp(savebuf, 1); + char buf[100]; + + XGetErrorText(disp, xe->error_code, buf, 100); + fprint(2, "winwatch: X error %s, request code %d\n", + buf, xe->request_code); + XFlush(disp); + XSync(disp, False); + XSetErrorHandler(oldxerrorhandler); + longjmp(savebuf, 1); + return(0); /* Not reached */ } void* erealloc(void *v, ulong n) { - v = realloc(v, n); - if (v == nil) - sysfatal("out of memory reallocating"); - return v; + v = realloc(v, n); + if(v==nil) + sysfatal("out of memory reallocating"); + return v; } char* estrdup(char *s) { - s = strdup(s); - if (s == nil) - sysfatal("out of memory allocating"); - return s; + s = strdup(s); + if(s==nil) + sysfatal("out of memory allocating"); + return(s); } char* getproperty(XWindow w, Atom a) { - uchar *p; - int fmt; - Atom type; - ulong n, dummy; - int s; - - n = 100; - p = nil; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetWindowProperty(dpy, w, a, 0, 100L, 0, - AnyPropertyType, &type, &fmt, &n, &dummy, &p); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - - if (s == 0) - return (char *) p; - else { - free(p); - return nil; - } + uchar *p; + int fmt; + Atom type; + ulong n, dummy; + int s; + + n = 100; + p = nil; + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetWindowProperty(dpy, w, a, 0, 100L, 0, + AnyPropertyType, &type, &fmt, &n, &dummy, &p); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s!=0){ + XFree(p); + return(nil); + } + + return((char*)p); } -XWindow +XWindow findname(XWindow w) { - int i; - uint nxwin; - XWindow dw1, dw2, *xwin; - char *p; - int s; - Atom net_wm_name; - - p = getproperty(w, XA_WM_NAME); - if (p) { - free(p); - return w; - } - - net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); - p = getproperty(w, net_wm_name); - if (p) { - free(p); - return w; - } - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) { - if (xwin != NULL) - XFree(xwin); - return 0; - } - - for (i = 0; i < nxwin; i++) { - w = findname(xwin[i]); - if (w != 0) { - XFree(xwin); - return w; - } - } - - XFree(xwin); - - return 0; + int i; + uint nxwin; + XWindow dw1, dw2, *xwin; + char *p; + int s; + Atom net_wm_name; + + p = getproperty(w, XA_WM_NAME); + if(p){ + free(p); + return(w); + } + + net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE); + p = getproperty(w, net_wm_name); + if(p){ + free(p); + return(w); + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s == 0) { + if (xwin != NULL) + XFree(xwin); + return 0; + } + + for (i = 0; i < nxwin; i++) { + w = findname(xwin[i]); + if (w != 0) { + XFree(xwin); + return w; + } + } + XFree(xwin); + + return 0; } -int +int wcmp(const void *w1, const void *w2) { - return *(XWindow *) w1 - *(XWindow *) w2; + return *(XWindow *) w1 - *(XWindow *) w2; } /* unicode-aware case-insensitive strcmp, taken from golang’s gc/subr.c */ -int +int _cistrcmp(char *p, char *q) { - Rune rp, rq; - - while(*p || *q) { - if(*p == 0) - return +1; - if(*q == 0) - return -1; - p += chartorune(&rp, p); - q += chartorune(&rq, q); - rp = tolowerrune(rp); - rq = tolowerrune(rq); - if(rp < rq) - return -1; - if(rp > rq) - return +1; - } - return 0; + Rune rp, rq; + + while(*p || *q) { + if(*p == 0) + return +1; + if(*q == 0) + return -1; + p += chartorune(&rp, p); + q += chartorune(&rq, q); + rp = tolowerrune(rp); + rq = tolowerrune(rq); + if(rp < rq) + return -1; + if(rp > rq) + return +1; + } + return 0; } -int +int winlabelcmp(const void *w1, const void *w2) { - const Win *p1 = (Win *) w1; - const Win *p2 = (Win *) w2; - return _cistrcmp(p1->label, p2->label); + const Win *p1 = (Win *) w1; + const Win *p2 = (Win *) w2; + return _cistrcmp(p1->label, p2->label); } -void +void refreshwin(void) { - XWindow dw1, dw2, *xwin; - XClassHint class; - XWindowAttributes attr; - char *label; - char *wmname; - int i, nw; - uint nxwin; - Status s; - Atom net_wm_name; - - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) { - if (xwin != NULL) - XFree(xwin); - return; - } - qsort(xwin, nxwin, sizeof(xwin[0]), wcmp); - - nw = 0; - for (i = 0; i < nxwin; i++) { - memset(&attr, 0, sizeof attr); - xwin[i] = findname(xwin[i]); - if (xwin[i] == 0) - continue; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetWindowAttributes(dpy, xwin[i], &attr); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) - continue; - if (attr.width <= 0 || attr.override_redirect - || attr.map_state != IsViewable) - continue; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetClassHint(dpy, xwin[i], &class); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) - continue; - - if (exclude != nil && regexec(exclude, class.res_name, nil, 0)) { - free(class.res_name); - free(class.res_class); - continue; - } - - net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); - wmname = getproperty(xwin[i], net_wm_name); - - if (wmname == nil) { - wmname = getproperty(xwin[i], XA_WM_NAME); - if (wmname == nil) { - free(class.res_name); - free(class.res_class); - continue; - } - } - - if (showwmnames == 1) - label = wmname; - else - label = class.res_name; - - if (nw < nwin && win[nw].n == xwin[i] - && strcmp(win[nw].label, label) == 0) { - nw++; - free(wmname); - free(class.res_name); - free(class.res_class); - continue; - } - - if (nw < nwin) { - free(win[nw].label); - win[nw].label = nil; - } - - if (nw >= mwin) { - mwin += 8; - win = erealloc(win, mwin * sizeof(win[0])); - } - win[nw].n = xwin[i]; - win[nw].label = estrdup(label); - win[nw].dirty = 1; - win[nw].r = Rect(0, 0, 0, 0); - free(wmname); - free(class.res_name); - free(class.res_class); - nw++; - } - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - XFree(xwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - while (nwin > nw) - free(win[--nwin].label); - nwin = nw; - - if (sortlabels == 1) - qsort(win, nwin, sizeof(struct Win), winlabelcmp); - - return; + XWindow dw1, dw2, *xwin; + XClassHint class; + XWindowAttributes attr; + char *label; + char *wmname; + int i, nw; + uint nxwin; + Status s; + Atom net_wm_name; + + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s==0){ + if(xwin!=NULL) + XFree(xwin); + return; + } + qsort(xwin, nxwin, sizeof(xwin[0]), wcmp); + + nw = 0; + for(i=0; i=mwin){ + mwin += 8; + win = erealloc(win, mwin * sizeof(win[0])); + } + win[nw].n = xwin[i]; + win[nw].label = estrdup(label); + win[nw].dirty = 1; + win[nw].r = Rect(0, 0, 0, 0); + free(wmname); + free(class.res_name); + free(class.res_class); + nw++; + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + XFree(xwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + while(nwin>nw) + free(win[--nwin].label); + nwin = nw; + + if(sortlabels==1) + qsort(win, nwin, sizeof(struct Win), winlabelcmp); } -void +void drawnowin(int i) { - Rectangle r; - - r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, - font->height); - r = rectaddpt(rectaddpt - (r, - Pt(MARGIN + (PAD + Dx(r)) * (i / rows), - MARGIN + (PAD + Dy(r)) * (i % rows))), - screen->r.min); - draw(screen, insetrect(r, -1), lightblue, nil, ZP); + Rectangle r; + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height); + r = rectaddpt( + rectaddpt(r, + Pt(MARGIN + (PAD + Dx(r)) * (i / rows), + MARGIN + (PAD + Dy(r)) * (i % rows))), + screen->r.min); + draw(screen, insetrect(r, -1), lightblue, nil, ZP); } -void +void drawwin(int i) { - draw(screen, win[i].r, lightblue, nil, ZP); - _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, - font, win[i].label, nil, strlen(win[i].label), - win[i].r, nil, ZP, SoverD); - border(screen, win[i].r, 1, display->black, ZP); - win[i].dirty = 0; + draw(screen, win[i].r, lightblue, nil, ZP); + _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, + font, win[i].label, nil, strlen(win[i].label), + win[i].r, nil, ZP, SoverD); + border(screen, win[i].r, 1, display->black, ZP); + win[i].dirty = 0; } -int +int geometry(void) { - int i, ncols, z; - Rectangle r; - - z = 0; - rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD); - if (rows * cols < nwin || rows * cols >= nwin * 2) { - ncols = nwin <= 0 ? 1 : (nwin + rows - 1) / rows; - if (ncols != cols) { - cols = ncols; - z = 1; - } - } - - r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, - font->height); - for (i = 0; i < nwin; i++) - win[i].r = - rectaddpt(rectaddpt - (r, - Pt(MARGIN + (PAD + Dx(r)) * (i / rows), - MARGIN + (PAD + Dy(r)) * (i % rows))), - screen->r.min); - - return z; + int i, ncols, z; + Rectangle r; + + z = 0; + rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD); + if(rows*cols=nwin*2){ + ncols = 1; + if(nwin>0) + ncols = (nwin + rows - 1) / rows; + if(ncols!=cols){ + cols = ncols; + z = 1; + } + } + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height); + for(i=0; ir.min); + + return z; } -void +void redraw(Image *screen, int all) { - int i; - - all |= geometry(); - if (all) - draw(screen, screen->r, lightblue, nil, ZP); - for (i = 0; i < nwin; i++) - if (all || win[i].dirty) - drawwin(i); - if (!all) - for (; i < onwin; i++) - drawnowin(i); - - onwin = nwin; + int i; + + all |= geometry(); + if(all) + draw(screen, screen->r, lightblue, nil, ZP); + for(i=0; i Date: Wed, 15 Jan 2020 11:54:20 +0000 Subject: compress: import Plan9 compress Add #define USED(x)... boilerplate compress: import Plan9 manpage. --- src/cmd/compress/compress.c | 1274 +++++++++++++++++++++++++++++++++++++++++++ src/cmd/compress/mkfile | 15 + 2 files changed, 1289 insertions(+) create mode 100755 src/cmd/compress/compress.c create mode 100755 src/cmd/compress/mkfile (limited to 'src') diff --git a/src/cmd/compress/compress.c b/src/cmd/compress/compress.c new file mode 100755 index 00000000..808762ca --- /dev/null +++ b/src/cmd/compress/compress.c @@ -0,0 +1,1274 @@ +/* + * compress - File compression ala IEEE Computer, June 1984. + * + * Algorithm from "A Technique for High Performance Data Compression", + * Terry A. Welch, IEEE Computer Vol 17, No 6 (June 1984), pp 8-19. + * + * Usage: compress [-dfvc] [-b bits] [file ...] + * Inputs: + * -b: limit the max number of bits/code. + * -c: write output on stdout, don't remove original. + * -d: decompress instead. + * -f: Forces output file to be generated, even if one already + * exists, and even if no space is saved by compressing. + * If -f is not used, the user will be prompted if stdin is + * a tty, otherwise, the output file will not be overwritten. + * -v: Write compression statistics + * + * file ...: Files to be compressed. If none specified, stdin is used. + * Outputs: + * file.Z: Compressed form of file with same mode, owner, and utimes + * or stdout (if stdin used as input) + * + * Assumptions: + * When filenames are given, replaces with the compressed version + * (.Z suffix) only if the file decreases in size. + * Algorithm: + * Modified Lempel-Ziv method (LZW). Basically finds common + * substrings and replaces them with a variable size code. This is + * deterministic, and can be done on the fly. Thus, the decompression + * procedure needs no input table, but tracks the way the table was built. + + * Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas) + * Jim McKie (decvax!mcvax!jim) + * Steve Davies (decvax!vax135!petsd!peora!srd) + * Ken Turkowski (decvax!decwrl!turtlevax!ken) + * James A. Woods (decvax!ihnp4!ames!jaw) + * Joe Orost (decvax!vax135!petsd!joe) + */ + +#ifndef USED +# define USED(x) if(x);else +#endif + +#define _PLAN9_SOURCE +#define _BSD_EXTENSION +#define _POSIX_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define min(a,b) ((a>b) ? b : a) + +#define BITS 16 +#define HSIZE 69001 /* 95% occupancy */ + +/* + * a code_int must be able to hold 2**BITS values of type int, and also -1 + */ +typedef long code_int; +typedef long count_int; + +static char rcs_ident[] = "$Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $"; + +uchar magic_header[] = { 0x1F, 0x9D }; /* 1F 9D */ + +/* Defines for third byte of header */ +#define BIT_MASK 0x1f +#define BLOCK_MASK 0x80 +/* Masks 0x40 and 0x20 are free. I think 0x20 should mean that there is + a fourth header byte (for expansion). +*/ +#define INIT_BITS 9 /* initial number of bits/code */ + +#define ARGVAL() (*++(*argv) || (--argc && *++argv)) + +int n_bits; /* number of bits/code */ +int maxbits = BITS; /* user settable max # bits/code */ +code_int maxcode; /* maximum code, given n_bits */ +code_int maxmaxcode = 1 << BITS; /* should NEVER generate this code */ + +#define MAXCODE(n_bits) ((1 << (n_bits)) - 1) + +count_int htab[HSIZE]; +ushort codetab[HSIZE]; + +#define htabof(i) htab[i] +#define codetabof(i) codetab[i] + +code_int hsize = HSIZE; /* for dynamic table sizing */ +count_int fsize; + +/* + * To save much memory, we overlay the table used by compress() with those + * used by decompress(). The tab_prefix table is the same size and type + * as the codetab. The tab_suffix table needs 2**BITS characters. We + * get this from the beginning of htab. The output stack uses the rest + * of htab, and contains characters. There is plenty of room for any + * possible stack (stack used to be 8000 characters). + */ + +#define tab_prefixof(i) codetabof(i) +#define tab_suffixof(i) ((uchar *)(htab))[i] +#define de_stack ((uchar *)&tab_suffixof(1< 0; argc--, argv++) { + if (**argv == '-') { /* A flag argument */ + while (*++(*argv)) { /* Process all flags in this arg */ + switch (**argv) { + case 'C': + block_compress = 0; + break; +#ifdef DEBUG + case 'D': + debug = 1; + break; + case 'V': + verbose = 1; + version(); + break; +#else + case 'V': + version(); + break; +#endif + case 'b': + if (!ARGVAL()) { + fprintf(stderr, "Missing maxbits\n"); + Usage(); + exit(1); + } + maxbits = atoi(*argv); + goto nextarg; + case 'c': + zcat_flg = 1; + break; + case 'd': + do_decomp = 1; + break; + case 'f': + case 'F': + overwrite = 1; + force = 1; + break; + case 'n': + nomagic = 1; + break; + case 'q': + quiet = 1; + break; + case 'v': + quiet = 0; + break; + default: + fprintf(stderr, "Unknown flag: '%c'; ", **argv); + Usage(); + exit(1); + } + } + } else { /* Input file name */ + *fileptr++ = *argv; /* Build input file list */ + *fileptr = NULL; + /* process nextarg; */ + } +nextarg: + continue; + } + + if(maxbits < INIT_BITS) maxbits = INIT_BITS; + if (maxbits > BITS) maxbits = BITS; + maxmaxcode = 1 << maxbits; + + if (*filelist != NULL) { + for (fileptr = filelist; *fileptr; fileptr++) { + exit_stat = 0; + if (do_decomp != 0) { /* DECOMPRESSION */ + /* Check for .Z suffix */ + if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") != 0) { + /* No .Z: tack one on */ + strcpy(tempname, *fileptr); + strcat(tempname, ".Z"); + *fileptr = tempname; + } + /* Open input file */ + if ((freopen(*fileptr, "r", stdin)) == NULL) { + perror(*fileptr); + continue; + } + /* Check the magic number */ + if (nomagic == 0) { + if ((getchar() != (magic_header[0] & 0xFF)) + || (getchar() != (magic_header[1] & 0xFF))) { + fprintf(stderr, "%s: not in compressed format\n", + *fileptr); + continue; + } + maxbits = getchar(); /* set -b from file */ + block_compress = maxbits & BLOCK_MASK; + maxbits &= BIT_MASK; + maxmaxcode = 1 << maxbits; + if(maxbits > BITS) { + fprintf(stderr, + "%s: compressed with %d bits, can only handle %d bits\n", + *fileptr, maxbits, BITS); + continue; + } + } + /* Generate output filename */ + strcpy(ofname, *fileptr); + ofname[strlen(*fileptr) - 2] = '\0'; /* Strip off .Z */ + } else { /* COMPRESSION */ + if (strcmp(*fileptr + strlen(*fileptr) - 2, ".Z") == 0) { + fprintf(stderr, + "%s: already has .Z suffix -- no change\n", + *fileptr); + continue; + } + /* Open input file */ + if ((freopen(*fileptr, "r", stdin)) == NULL) { + perror(*fileptr); + continue; + } + (void) stat(*fileptr, &statbuf); + fsize = (long) statbuf.st_size; + /* + * tune hash table size for small files -- ad hoc, + * but the sizes match earlier #defines, which + * serve as upper bounds on the number of output codes. + */ + hsize = HSIZE; + if (fsize < (1 << 12)) + hsize = min(5003, HSIZE); + else if (fsize < (1 << 13)) + hsize = min(9001, HSIZE); + else if (fsize < (1 << 14)) + hsize = min (18013, HSIZE); + else if (fsize < (1 << 15)) + hsize = min (35023, HSIZE); + else if (fsize < 47000) + hsize = min (50021, HSIZE); + + /* Generate output filename */ + strcpy(ofname, *fileptr); +#ifndef BSD4_2 + if ((cp=strrchr(ofname,'/')) != NULL) + cp++; + else + cp = ofname; + /* + *** changed 12 to 25; should be NAMELEN-3, but I don't want + * to fight the headers. ehg 5 Nov 92 ** + */ + if (strlen(cp) > 25) { + fprintf(stderr, "%s: filename too long to tack on .Z\n", + cp); + continue; + } +#endif + strcat(ofname, ".Z"); + } + /* Check for overwrite of existing file */ + if (overwrite == 0 && zcat_flg == 0 && + stat(ofname, &statbuf) == 0) { + char response[2]; + + response[0] = 'n'; + fprintf(stderr, "%s already exists;", ofname); + if (foreground()) { + fprintf(stderr, + " do you wish to overwrite %s (y or n)? ", + ofname); + fflush(stderr); + (void) read(2, response, 2); + while (response[1] != '\n') + if (read(2, response+1, 1) < 0) { + /* Ack! */ + perror("stderr"); + break; + } + } + if (response[0] != 'y') { + fprintf(stderr, "\tnot overwritten\n"); + continue; + } + } + if(zcat_flg == 0) { /* Open output file */ + if (freopen(ofname, "w", stdout) == NULL) { + perror(ofname); + continue; + } + if(!quiet) + fprintf(stderr, "%s: ", *fileptr); + } + + /* Actually do the compression/decompression */ + if (do_decomp == 0) + compress(); +#ifndef DEBUG + else + decompress(); +#else + else if (debug == 0) + decompress(); + else + printcodes(); + if (verbose) + dump_tab(); +#endif /* DEBUG */ + if(zcat_flg == 0) { + copystat(*fileptr, ofname); /* Copy stats */ + if (exit_stat == 1 || !quiet) + putc('\n', stderr); + } + } + } else { /* Standard input */ + if (do_decomp == 0) { + compress(); +#ifdef DEBUG + if(verbose) + dump_tab(); +#endif + if(!quiet) + putc('\n', stderr); + } else { + /* Check the magic number */ + if (nomagic == 0) { + if ((getchar()!=(magic_header[0] & 0xFF)) + || (getchar()!=(magic_header[1] & 0xFF))) { + fprintf(stderr, "stdin: not in compressed format\n"); + exit(1); + } + maxbits = getchar(); /* set -b from file */ + block_compress = maxbits & BLOCK_MASK; + maxbits &= BIT_MASK; + maxmaxcode = 1 << maxbits; + fsize = 100000; /* assume stdin large for USERMEM */ + if(maxbits > BITS) { + fprintf(stderr, + "stdin: compressed with %d bits, can only handle %d bits\n", + maxbits, BITS); + exit(1); + } + } +#ifndef DEBUG + decompress(); +#else + if (debug == 0) + decompress(); + else + printcodes(); + if (verbose) + dump_tab(); +#endif /* DEBUG */ + } + } + exit(exit_stat); + return 0; +} + +static int offset; +long in_count = 1; /* length of input */ +long bytes_out; /* length of compressed output */ +long out_count = 0; /* # of codes output (for debugging) */ + +/* + * compress stdin to stdout + * + * Algorithm: use open addressing double hashing (no chaining) on the + * prefix code / next character combination. We do a variant of Knuth's + * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime + * secondary probe. Here, the modular division first probe is gives way + * to a faster exclusive-or manipulation. Also do block compression with + * an adaptive reset, whereby the code table is cleared when the compression + * ratio decreases, but after the table fills. The variable-length output + * codes are re-sized at this point, and a special CLEAR code is generated + * for the decompressor. Late addition: construct the table according to + * file size for noticeable speed improvement on small files. Please direct + * questions about this implementation to ames!jaw. + */ +void +compress(void) +{ + code_int ent, hsize_reg; + code_int i; + int c, disp, hshift; + long fcode; + + if (nomagic == 0) { + putchar(magic_header[0]); + putchar(magic_header[1]); + putchar((char)(maxbits | block_compress)); + if(ferror(stdout)) + writeerr(); + } + offset = 0; + bytes_out = 3; /* includes 3-byte header mojo */ + out_count = 0; + clear_flg = 0; + ratio = 0; + in_count = 1; + checkpoint = CHECK_GAP; + maxcode = MAXCODE(n_bits = INIT_BITS); + free_ent = (block_compress? FIRST: 256); + + ent = getchar (); + + hshift = 0; + for (fcode = (long)hsize; fcode < 65536L; fcode *= 2) + hshift++; + hshift = 8 - hshift; /* set hash code range bound */ + + hsize_reg = hsize; + cl_hash( (count_int) hsize_reg); /* clear hash table */ + + while ((c = getchar()) != EOF) { + in_count++; + fcode = (long) (((long) c << maxbits) + ent); + i = ((c << hshift) ^ ent); /* xor hashing */ + + if (htabof (i) == fcode) { + ent = codetabof(i); + continue; + } else if ((long)htabof(i) < 0 ) /* empty slot */ + goto nomatch; + disp = hsize_reg - i; /* secondary hash (after G. Knott) */ + if (i == 0) + disp = 1; +probe: + if ((i -= disp) < 0) + i += hsize_reg; + + if (htabof (i) == fcode) { + ent = codetabof(i); + continue; + } + if ((long)htabof(i) > 0) + goto probe; +nomatch: + output((code_int)ent); + out_count++; + ent = c; + if (free_ent < maxmaxcode) { + codetabof(i) = free_ent++; /* code -> hashtable */ + htabof(i) = fcode; + } else if ((count_int)in_count >= checkpoint && block_compress) + cl_block (); + } + /* + * Put out the final code. + */ + output( (code_int)ent ); + out_count++; + output( (code_int)-1 ); + + /* + * Print out stats on stderr + */ + if(zcat_flg == 0 && !quiet) { +#ifdef DEBUG + fprintf( stderr, + "%ld chars in, %ld codes (%ld bytes) out, compression factor: ", + in_count, out_count, bytes_out ); + prratio( stderr, in_count, bytes_out ); + fprintf( stderr, "\n"); + fprintf( stderr, "\tCompression as in compact: " ); + prratio( stderr, in_count-bytes_out, in_count ); + fprintf( stderr, "\n"); + fprintf( stderr, "\tLargest code (of last block) was %d (%d bits)\n", + free_ent - 1, n_bits ); +#else /* !DEBUG */ + fprintf( stderr, "Compression: " ); + prratio( stderr, in_count-bytes_out, in_count ); +#endif /* DEBUG */ + } + if(bytes_out > in_count) /* exit(2) if no savings */ + exit_stat = 2; +} + +/* + * TAG( output ) + * + * Output the given code. + * Inputs: + * code: A n_bits-bit integer. If == -1, then EOF. This assumes + * that n_bits =< (long)wordsize - 1. + * Outputs: + * Outputs code to the file. + * Assumptions: + * Chars are 8 bits long. + * Algorithm: + * Maintain a BITS character long buffer (so that 8 codes will + * fit in it exactly). When the buffer fills up empty it and start over. + */ + +static char buf[BITS]; + +uchar lmask[9] = {0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; +uchar rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; + +void +output( code ) +code_int code; +{ +#ifdef DEBUG + static int col = 0; +#endif + int r_off = offset, bits= n_bits; + char *bp = buf; + +#ifdef DEBUG + if (verbose) + fprintf(stderr, "%5d%c", code, + (col+=6) >= 74? (col = 0, '\n'): ' '); +#endif + if (code >= 0) { + /* + * byte/bit numbering on the VAX is simulated by the + * following code + */ + /* + * Get to the first byte. + */ + bp += (r_off >> 3); + r_off &= 7; + /* + * Since code is always >= 8 bits, only need to mask the first + * hunk on the left. + */ + *bp = (*bp & rmask[r_off]) | (code << r_off) & lmask[r_off]; + bp++; + bits -= 8 - r_off; + code >>= 8 - r_off; + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ + if ( bits >= 8 ) { + *bp++ = code; + code >>= 8; + bits -= 8; + } + /* Last bits. */ + if(bits) + *bp = code; + + offset += n_bits; + if ( offset == (n_bits << 3) ) { + bp = buf; + bits = n_bits; + bytes_out += bits; + do { + putchar(*bp++); + } while(--bits); + offset = 0; + } + + /* + * If the next entry is going to be too big for the code size, + * then increase it, if possible. + */ + if ( free_ent > maxcode || (clear_flg > 0)) { + /* + * Write the whole buffer, because the input side won't + * discover the size increase until after it has read it. + */ + if ( offset > 0 ) { + if( fwrite( buf, 1, n_bits, stdout ) != n_bits) + writeerr(); + bytes_out += n_bits; + } + offset = 0; + + if ( clear_flg ) { + maxcode = MAXCODE (n_bits = INIT_BITS); + clear_flg = 0; + } else { + n_bits++; + if ( n_bits == maxbits ) + maxcode = maxmaxcode; + else + maxcode = MAXCODE(n_bits); + } +#ifdef DEBUG + if ( debug ) { + fprintf(stderr, + "\nChange to %d bits\n", n_bits); + col = 0; + } +#endif + } + } else { + /* + * At EOF, write the rest of the buffer. + */ + if ( offset > 0 ) + fwrite( buf, 1, (offset + 7) / 8, stdout ); + bytes_out += (offset + 7) / 8; + offset = 0; + fflush( stdout ); +#ifdef DEBUG + if ( verbose ) + fprintf( stderr, "\n" ); +#endif + if( ferror( stdout ) ) + writeerr(); + } +} + +/* + * Decompress stdin to stdout. This routine adapts to the codes in the + * file building the "string" table on-the-fly; requiring no table to + * be stored in the compressed file. The tables used herein are shared + * with those of the compress() routine. See the definitions above. + */ +void +decompress(void) +{ + int finchar; + code_int code, oldcode, incode; + uchar *stackp; + + /* + * As above, initialize the first 256 entries in the table. + */ + maxcode = MAXCODE(n_bits = INIT_BITS); + for (code = 255; code >= 0; code--) { + tab_prefixof(code) = 0; + tab_suffixof(code) = (uchar)code; + } + free_ent = (block_compress? FIRST: 256); + + finchar = oldcode = getcode(); + if(oldcode == -1) /* EOF already? */ + return; /* Get out of here */ + putchar((char)finchar); /* first code must be 8 bits = char */ + if(ferror(stdout)) /* Crash if can't write */ + writeerr(); + stackp = de_stack; + + while ((code = getcode()) > -1) { + if ((code == CLEAR) && block_compress) { + for (code = 255; code >= 0; code--) + tab_prefixof(code) = 0; + clear_flg = 1; + free_ent = FIRST - 1; + if ((code = getcode()) == -1) /* O, untimely death! */ + break; + } + incode = code; + /* + * Special case for KwKwK string. + */ + if (code >= free_ent) { + *stackp++ = finchar; + code = oldcode; + } + + /* + * Generate output characters in reverse order + */ + while (code >= 256) { + *stackp++ = tab_suffixof(code); + code = tab_prefixof(code); + } + *stackp++ = finchar = tab_suffixof(code); + + /* + * And put them out in forward order + */ + do { + putchar(*--stackp); + } while (stackp > de_stack); + + /* + * Generate the new entry. + */ + if ( (code=free_ent) < maxmaxcode ) { + tab_prefixof(code) = (ushort)oldcode; + tab_suffixof(code) = finchar; + free_ent = code+1; + } + /* + * Remember previous code. + */ + oldcode = incode; + } + fflush(stdout); + if(ferror(stdout)) + writeerr(); +} + +/* + * TAG( getcode ) + * + * Read one code from the standard input. If EOF, return -1. + * Inputs: + * stdin + * Outputs: + * code or -1 is returned. + */ +code_int +getcode() +{ + int r_off, bits; + code_int code; + static int offset = 0, size = 0; + static uchar buf[BITS]; + uchar *bp = buf; + + if ( clear_flg > 0 || offset >= size || free_ent > maxcode ) { + /* + * If the next entry will be too big for the current code + * size, then we must increase the size. This implies reading + * a new buffer full, too. + */ + if ( free_ent > maxcode ) { + n_bits++; + if ( n_bits == maxbits ) + maxcode = maxmaxcode; /* won't get any bigger now */ + else + maxcode = MAXCODE(n_bits); + } + if ( clear_flg > 0) { + maxcode = MAXCODE(n_bits = INIT_BITS); + clear_flg = 0; + } + size = fread(buf, 1, n_bits, stdin); + if (size <= 0) + return -1; /* end of file */ + offset = 0; + /* Round size down to integral number of codes */ + size = (size << 3) - (n_bits - 1); + } + r_off = offset; + bits = n_bits; + /* + * Get to the first byte. + */ + bp += (r_off >> 3); + r_off &= 7; + /* Get first part (low order bits) */ + code = (*bp++ >> r_off); + bits -= (8 - r_off); + r_off = 8 - r_off; /* now, offset into code word */ + /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */ + if (bits >= 8) { + code |= *bp++ << r_off; + r_off += 8; + bits -= 8; + } + /* high order bits. */ + code |= (*bp & rmask[bits]) << r_off; + offset += n_bits; + return code; +} + +#ifdef DEBUG +printcodes() +{ + /* + * Just print out codes from input file. For debugging. + */ + code_int code; + int col = 0, bits; + + bits = n_bits = INIT_BITS; + maxcode = MAXCODE(n_bits); + free_ent = ((block_compress) ? FIRST : 256 ); + while ( ( code = getcode() ) >= 0 ) { + if ( (code == CLEAR) && block_compress ) { + free_ent = FIRST - 1; + clear_flg = 1; + } + else if ( free_ent < maxmaxcode ) + free_ent++; + if ( bits != n_bits ) { + fprintf(stderr, "\nChange to %d bits\n", n_bits ); + bits = n_bits; + col = 0; + } + fprintf(stderr, "%5d%c", code, (col+=6) >= 74 ? (col = 0, '\n') : ' ' ); + } + putc( '\n', stderr ); + exit( 0 ); +} + +code_int sorttab[1<= 0) { + sorttab[codetabof(i)] = i; + } + } + first = block_compress ? FIRST : 256; + for(i = first; i < free_ent; i++) { + fprintf(stderr, "%5d: \"", i); + de_stack[--stack_top] = '\n'; + de_stack[--stack_top] = '"'; + stack_top = in_stack((htabof(sorttab[i])>>maxbits)&0xff, + stack_top); + for(ent=htabof(sorttab[i]) & ((1< 256; + ent=htabof(sorttab[ent]) & ((1<> maxbits, + stack_top); + } + stack_top = in_stack(ent, stack_top); + fwrite( &de_stack[stack_top], 1, STACK_SIZE-stack_top, stderr); + stack_top = STACK_SIZE; + } + } else if(!debug) { /* decompressing */ + + for ( i = 0; i < free_ent; i++ ) { + ent = i; + c = tab_suffixof(ent); + if ( isascii(c) && isprint(c) ) + fprintf( stderr, "%5d: %5d/'%c' \"", + ent, tab_prefixof(ent), c ); + else + fprintf( stderr, "%5d: %5d/\\%03o \"", + ent, tab_prefixof(ent), c ); + de_stack[--stack_top] = '\n'; + de_stack[--stack_top] = '"'; + for ( ; ent != NULL; + ent = (ent >= FIRST ? tab_prefixof(ent) : NULL) ) { + stack_top = in_stack(tab_suffixof(ent), stack_top); + } + fwrite( &de_stack[stack_top], 1, STACK_SIZE - stack_top, stderr ); + stack_top = STACK_SIZE; + } + } +} + +int +in_stack(int c, int stack_top) +{ + if ( (isascii(c) && isprint(c) && c != '\\') || c == ' ' ) { + de_stack[--stack_top] = c; + } else { + switch( c ) { + case '\n': de_stack[--stack_top] = 'n'; break; + case '\t': de_stack[--stack_top] = 't'; break; + case '\b': de_stack[--stack_top] = 'b'; break; + case '\f': de_stack[--stack_top] = 'f'; break; + case '\r': de_stack[--stack_top] = 'r'; break; + case '\\': de_stack[--stack_top] = '\\'; break; + default: + de_stack[--stack_top] = '0' + c % 8; + de_stack[--stack_top] = '0' + (c / 8) % 8; + de_stack[--stack_top] = '0' + c / 64; + break; + } + de_stack[--stack_top] = '\\'; + } + return stack_top; +} +#endif /* DEBUG */ + +void +writeerr(void) +{ + perror(ofname); + unlink(ofname); + exit(1); +} + +void +copystat(ifname, ofname) +char *ifname, *ofname; +{ + int mode; + time_t timep[2]; /* should be struct utimbuf */ + struct stat statbuf; + + fclose(stdout); + if (stat(ifname, &statbuf)) { /* Get stat on input file */ + perror(ifname); + return; + } + if (!S_ISREG(statbuf.st_mode)) { + if (quiet) + fprintf(stderr, "%s: ", ifname); + fprintf(stderr, " -- not a regular file: unchanged"); + exit_stat = 1; + } else if (exit_stat == 2 && !force) { + /* No compression: remove file.Z */ + if (!quiet) + fprintf(stderr, " -- file unchanged"); + } else { /* Successful Compression */ + exit_stat = 0; + mode = statbuf.st_mode & 0777; + if (chmod(ofname, mode)) /* Copy modes */ + perror(ofname); + /* Copy ownership */ + chown(ofname, statbuf.st_uid, statbuf.st_gid); + timep[0] = statbuf.st_atime; + timep[1] = statbuf.st_mtime; + /* Update last accessed and modified times */ + utime(ofname, (struct utimbuf *)timep); +// if (unlink(ifname)) /* Remove input file */ +// perror(ifname); + return; /* success */ + } + + /* Unsuccessful return -- one of the tests failed */ + if (unlink(ofname)) + perror(ofname); +} + +/* + * This routine returns 1 if we are running in the foreground and stderr + * is a tty. + */ +int +foreground(void) +{ + if(bgnd_flag) /* background? */ + return 0; + else /* foreground */ + return isatty(2); /* and stderr is a tty */ +} + +void +onintr(int x) +{ + USED(x); + unlink(ofname); + exit(1); +} + +void +oops(int x) /* wild pointer -- assume bad input */ +{ + USED(x); + if (do_decomp == 1) + fprintf(stderr, "uncompress: corrupt input\n"); + unlink(ofname); + exit(1); +} + +void +cl_block(void) /* table clear for block compress */ +{ + long rat; + + checkpoint = in_count + CHECK_GAP; +#ifdef DEBUG + if ( debug ) { + fprintf ( stderr, "count: %ld, ratio: ", in_count ); + prratio ( stderr, in_count, bytes_out ); + fprintf ( stderr, "\n"); + } +#endif /* DEBUG */ + + if (in_count > 0x007fffff) { /* shift will overflow */ + rat = bytes_out >> 8; + if (rat == 0) /* Don't divide by zero */ + rat = 0x7fffffff; + else + rat = in_count / rat; + } else + rat = (in_count << 8) / bytes_out; /* 8 fractional bits */ + if (rat > ratio) + ratio = rat; + else { + ratio = 0; +#ifdef DEBUG + if (verbose) + dump_tab(); /* dump string table */ +#endif + cl_hash((count_int)hsize); + free_ent = FIRST; + clear_flg = 1; + output((code_int)CLEAR); +#ifdef DEBUG + if (debug) + fprintf(stderr, "clear\n"); +#endif /* DEBUG */ + } +} + +void +cl_hash(count_int hsize) /* reset code table */ +{ + count_int *htab_p = htab+hsize; + long i; + long m1 = -1; + + i = hsize - 16; + do { /* might use Sys V memset(3) here */ + *(htab_p-16) = m1; + *(htab_p-15) = m1; + *(htab_p-14) = m1; + *(htab_p-13) = m1; + *(htab_p-12) = m1; + *(htab_p-11) = m1; + *(htab_p-10) = m1; + *(htab_p-9) = m1; + *(htab_p-8) = m1; + *(htab_p-7) = m1; + *(htab_p-6) = m1; + *(htab_p-5) = m1; + *(htab_p-4) = m1; + *(htab_p-3) = m1; + *(htab_p-2) = m1; + *(htab_p-1) = m1; + htab_p -= 16; + } while ((i -= 16) >= 0); + for ( i += 16; i > 0; i-- ) + *--htab_p = m1; +} + +void +prratio(stream, num, den) +FILE *stream; +long num, den; +{ + int q; /* Doesn't need to be long */ + + if(num > 214748L) /* 2147483647/10000 */ + q = num / (den / 10000L); + else + q = 10000L * num / den; /* Long calculations, though */ + if (q < 0) { + putc('-', stream); + q = -q; + } + fprintf(stream, "%d.%02d%%", q / 100, q % 100); +} + +void +version(void) +{ + fprintf(stderr, "%s\n", rcs_ident); + fprintf(stderr, "Options: "); +#ifdef DEBUG + fprintf(stderr, "DEBUG, "); +#endif +#ifdef BSD4_2 + fprintf(stderr, "BSD4_2, "); +#endif + fprintf(stderr, "BITS = %d\n", BITS); +} + +/* + * The revision-history novel: + * + * $Header: compress.c,v 4.0 85/07/30 12:50:00 joe Release $ + * $Log: compress.c,v $ + * Revision 4.0 85/07/30 12:50:00 joe + * Removed ferror() calls in output routine on every output except first. + * Prepared for release to the world. + * + * Revision 3.6 85/07/04 01:22:21 joe + * Remove much wasted storage by overlaying hash table with the tables + * used by decompress: tab_suffix[1<putc] and + * added signal catcher [plus beef in writeerr()] to delete effluvia. + * + * Revision 2.0 84/08/28 22:00:00 petsd!joe + * Add check for foreground before prompting user. Insert maxbits into + * compressed file. Force file being uncompressed to end with ".Z". + * Added "-c" flag and "zcat". Prepared for release. + * + * Revision 1.10 84/08/24 18:28:00 turtlevax!ken + * Will only compress regular files (no directories), added a magic number + * header (plus an undocumented -n flag to handle old files without headers), + * added -f flag to force overwriting of possibly existing destination file, + * otherwise the user is prompted for a response. Will tack on a .Z to a + * filename if it doesn't have one when decompressing. Will only replace + * file if it was compressed. + * + * Revision 1.9 84/08/16 17:28:00 turtlevax!ken + * Removed scanargs(), getopt(), added .Z extension and unlimited number of + * filenames to compress. Flags may be clustered (-Ddvb12) or separated + * (-D -d -v -b 12), or combination thereof. Modes and other status is + * copied with copystat(). -O bug for 4.2 seems to have disappeared with + * 1.8. + * + * Revision 1.8 84/08/09 23:15:00 joe + * Made it compatible with vax version, installed jim's fixes/enhancements + * + * Revision 1.6 84/08/01 22:08:00 joe + * Sped up algorithm significantly by sorting the compress chain. + * + * Revision 1.5 84/07/13 13:11:00 srd + * Added C version of vax asm routines. Changed structure to arrays to + * save much memory. Do unsigned compares where possible (faster on + * Perkin-Elmer) + * + * Revision 1.4 84/07/05 03:11:11 thomas + * Clean up the code a little and lint it. (Lint complains about all + * the regs used in the asm, but I'm not going to "fix" this.) + * + * Revision 1.3 84/07/05 02:06:54 thomas + * Minor fixes. + * + * Revision 1.2 84/07/05 00:27:27 thomas + * Add variable bit length output. + */ diff --git a/src/cmd/compress/mkfile b/src/cmd/compress/mkfile new file mode 100755 index 00000000..5af1958d --- /dev/null +++ b/src/cmd/compress/mkfile @@ -0,0 +1,15 @@ +<$PLAN9/src/mkhdr + +TARG=\ + compress \ + zcat \ + uncompress + +$O.uncompress:Q: $O.compress + cp $prereq $target + +$O.zcat:Q: $O.compress + cp $prereq $target + +<$PLAN9/src/mkmany + -- cgit v1.2.3 From e75dbb6af8fbea53c62efb7176ed2d25a47557c9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 15 Jan 2020 10:48:20 -0500 Subject: factotum: update for new nbrecvul return value Unclear whether the old semantics were the right ones, but at least this preserves what they've been for the past however many years. --- src/cmd/auth/factotum/confirm.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/auth/factotum/confirm.c b/src/cmd/auth/factotum/confirm.c index 105a46db..8451e8ae 100644 --- a/src/cmd/auth/factotum/confirm.c +++ b/src/cmd/auth/factotum/confirm.c @@ -128,17 +128,33 @@ needkeywrite(char *s) int needkey(Conv *c, Attr *a) { + ulong u; + if(c == nil || *needkeyinuse == 0) return -1; lbappend(&needkeybuf, "needkey tag=%lud %A", c->tag, a); flog("needkey %A", a); - return nbrecvul(c->keywait); + + // Note: This code used to "return nbrecvul(c->keywait)." + // In Jan 2020 we changed nbrecvul to match Plan 9 and + // the man page and return 0 on "no data available" instead + // of -1. This new code with an explicit nbrecv preserves the + // code's old semantics, distinguishing a sent 0 from "no data". + // That said, this code seems to return -1 unconditionally: + // the c->keywait channel is unbuffered, and the only sending + // to it is done with an nbsendul, which won't block waiting for + // a receiver. So there is no sender for nbrecv to find here. + if(nbrecv(c->keywait, &u) < 0) + return -1; + return u; } int badkey(Conv *c, Key *k, char *msg, Attr *a) { + ulong u; + if(c == nil || *needkeyinuse == 0) return -1; @@ -146,5 +162,17 @@ badkey(Conv *c, Key *k, char *msg, Attr *a) c->tag, k->attr, k->privattr, msg, a); flog("badkey %A / %N / %s / %A", k->attr, k->privattr, msg, a); - return nbrecvul(c->keywait); + + // Note: This code used to "return nbrecvul(c->keywait)." + // In Jan 2020 we changed nbrecvul to match Plan 9 and + // the man page and return 0 on "no data available" instead + // of -1. This new code with an explicit nbrecv preserves the + // code's old semantics, distinguishing a sent 0 from "no data". + // That said, this code seems to return -1 unconditionally: + // the c->keywait channel is unbuffered, and the only sending + // to it is done with an nbsendul, which won't block waiting for + // a receiver. So there is no sender for nbrecv to find here. + if(nbrecv(c->keywait, &u) < 0) + return -1; + return u; } -- cgit v1.2.3 From ba60bab3cd247284977ff99573db0c1f3d056953 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 15 Jan 2020 11:09:16 -0500 Subject: devdraw: actually send resize event on resize Fixes #340. Fixes #343. --- src/cmd/devdraw/srv.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/cmd/devdraw/srv.c b/src/cmd/devdraw/srv.c index c98a865f..570091bc 100644 --- a/src/cmd/devdraw/srv.c +++ b/src/cmd/devdraw/srv.c @@ -37,6 +37,8 @@ usage(void) void threadmain(int argc, char **argv) { + char *p; + ARGBEGIN{ case 'D': /* for good ps -a listings */ break; @@ -52,6 +54,10 @@ threadmain(int argc, char **argv) usage(); }ARGEND + fmtinstall('H', encodefmt); + if((p = getenv("DEVDRAWTRACE")) != nil) + trace = atoi(p); + if(srvname == nil) { client0 = mallocz(sizeof(Client), 1); if(client0 == nil){ @@ -417,6 +423,7 @@ gfx_mousetrack(Client *c, int x, int y, int b, uint ms) y = copy->xy.y; b = copy->buttons; ms = copy->msec; + c->mouse.resized = 1; } if(x < c->mouserect.min.x) x = c->mouserect.min.x; -- cgit v1.2.3 From fe2b2de9844749c876df209bb8d9413e0074cbcf Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 15 Jan 2020 11:25:36 -0500 Subject: devdraw: set windowrect correctly on x11 if window gets unexpected size Fixes #54. --- src/cmd/devdraw/x11-screen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c index c3a6fa33..d01e8496 100644 --- a/src/cmd/devdraw/x11-screen.c +++ b/src/cmd/devdraw/x11-screen.c @@ -550,8 +550,6 @@ xattach(Client *client, char *label, char *winsize) havemin = 0; } w = newxwin(client); - w->screenrect = Rect(0, 0, WidthOfScreen(xscreen), HeightOfScreen(xscreen)); - w->windowrect = r; memset(&attr, 0, sizeof attr); attr.colormap = _x.cmap; @@ -679,6 +677,8 @@ xattach(Client *client, char *label, char *winsize) } }else fprint(2, "XGetWindowAttributes: bad attrs\n"); + w->screenrect = Rect(0, 0, WidthOfScreen(xscreen), HeightOfScreen(xscreen)); + w->windowrect = r; /* * Allocate our local backing store. -- cgit v1.2.3 From d46053106d746260ce0ab39458332bc31ce6948b Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Wed, 15 Jan 2020 16:51:14 +0000 Subject: libmach: Fix type errors in FreeBSD.c The ptrace handlers wanted to take u64int arguments, not ulong. Signed-off-by: Dan Cross --- src/libmach/FreeBSD.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libmach/FreeBSD.c b/src/libmach/FreeBSD.c index 80c8935a..de8647c6 100644 --- a/src/libmach/FreeBSD.c +++ b/src/libmach/FreeBSD.c @@ -30,8 +30,8 @@ struct PtraceRegs int pid; }; -static int ptracerw(Map*, Seg*, ulong, void*, uint, int); -static int ptraceregrw(Regs*, char*, ulong*, int); +static int ptracerw(Map*, Seg*, u64int, void*, uint, int); +static int ptraceregrw(Regs*, char*, u64int*, int); void unmapproc(Map *map) @@ -92,7 +92,7 @@ detachproc(int pid) } static int -ptracerw(Map *map, Seg *seg, ulong addr, void *v, uint n, int isr) +ptracerw(Map *map, Seg *seg, u64int addr, void *v, uint n, int isr) { int i; u32int u; @@ -167,7 +167,7 @@ reg2freebsd(char *reg) } static int -ptraceregrw(Regs *regs, char *name, ulong *val, int isr) +ptraceregrw(Regs *regs, char *name, u64int *val, int isr) { int pid; ulong addr; -- cgit v1.2.3 From 4241cae2a1ffe7a499ffd9d028e001fea7a678d6 Mon Sep 17 00:00:00 2001 From: Nicola Girardi Date: Sat, 22 Jun 2019 11:44:24 +0100 Subject: cmd/rio: xshove: set geometry by window id --- src/cmd/rio/xshove.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/rio/xshove.c b/src/cmd/rio/xshove.c index e235874e..7358987e 100644 --- a/src/cmd/rio/xshove.c +++ b/src/cmd/rio/xshove.c @@ -27,6 +27,7 @@ struct Win int y; int dx; int dy; + char *idstr; char *class; char *instance; char *name; @@ -143,6 +144,9 @@ getinfo(void) if(attr.width <= 0 || attr.override_redirect || attr.map_state != IsViewable) continue; ww->xw = xwin[i]; + char idstr[9]; + snprint(idstr, sizeof(idstr), "%08x", (uint)ww->xw); + ww->idstr = strdup(idstr); ww->x = attr.x; ww->y = attr.y; ww->dx = attr.width; @@ -196,7 +200,8 @@ shove(char *name, char *geom) for(i=0; iinstance && strstr(ww->instance, name) - || ww->class && strstr(ww->class, name)){ + || ww->class && strstr(ww->class, name) + || ww->idstr && strstr(ww->idstr, name)){ int value_mask; XWindowChanges e; -- cgit v1.2.3 From 0be57355f912dbedb76cea1a7a4f9a1deb5bde2b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 15 Jan 2020 11:59:45 -0500 Subject: devdraw: avoid deadlock in x11 resize Fixes #347. --- src/cmd/devdraw/x11-inc.h | 1 + src/cmd/devdraw/x11-screen.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/cmd/devdraw/x11-inc.h b/src/cmd/devdraw/x11-inc.h index dca3ebcd..ab4c2505 100644 --- a/src/cmd/devdraw/x11-inc.h +++ b/src/cmd/devdraw/x11-inc.h @@ -17,6 +17,7 @@ #include #include #ifdef SHOWEVENT +#include #include "../rio/showevent/ShowEvent.c" #endif diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c index d01e8496..62f49f2f 100644 --- a/src/cmd/devdraw/x11-screen.c +++ b/src/cmd/devdraw/x11-screen.c @@ -1042,7 +1042,9 @@ _xreplacescreenimage(Client *client) w->nextscreenpm = pixmap; w->screenr = r; client->mouserect = r; + xunlock(); gfx_replacescreenimage(client, m); + xlock(); return 1; } -- cgit v1.2.3 From 3ef80ba5f5c29a8367d32353a9620ec4cf9cb880 Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Thu, 16 Jan 2020 16:46:58 +0000 Subject: lib9: putenv wraps POSIX setenv, not legacy putenv POSIX setenv does everything that p9putenv's body, so just delegate to that. Signed-off-by: Dan Cross --- src/lib9/getenv.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/lib9/getenv.c b/src/lib9/getenv.c index 384196cf..5dfc8577 100644 --- a/src/lib9/getenv.c +++ b/src/lib9/getenv.c @@ -16,11 +16,5 @@ p9getenv(char *s) int p9putenv(char *s, char *v) { - char *t; - - t = smprint("%s=%s", s, v); - if(t == nil) - return -1; - putenv(t); - return 0; + return setenv(s, v, 1); } -- cgit v1.2.3 From 7bf2db4c2ae30c0f7b320e57060715bf6279e98a Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Thu, 16 Jan 2020 16:54:19 +0000 Subject: malloc: remove locking The issue manifests in fork: POSIX fork mandates that a fork'd process is created with a single thread. If a multithreaded program forks, and some thread was in malloc() when the fork() happened, then in the child the lock will be held but there will be no thread to release it. We assume the system malloc() must already know how to deal with this and is thread-safe, but it won't know about our custom spinlock. Judging that this is no longer necessary (the lock code was added 15 years ago) we remove it. Signed-off-by: Dan Cross --- src/cmd/9term/malloc.c | 10 ---------- src/lib9/debugmalloc.c | 9 --------- src/lib9/malloc.c | 25 +++---------------------- 3 files changed, 3 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/cmd/9term/malloc.c b/src/cmd/9term/malloc.c index 9132235b..7b590bc4 100644 --- a/src/cmd/9term/malloc.c +++ b/src/cmd/9term/malloc.c @@ -7,8 +7,6 @@ #define NOPLAN9DEFINES #include -static Lock malloclock; - void* p9malloc(ulong n) { @@ -16,9 +14,7 @@ p9malloc(ulong n) if(n == 0) n++; - lock(&malloclock); v = malloc(n); - unlock(&malloclock); print("p9malloc %lud => %p; pc %lux\n", n, v, getcallerpc(&n)); return v; } @@ -28,10 +24,8 @@ p9free(void *v) { if(v == nil) return; - lock(&malloclock); print("p9free %p; pc %lux\n", v, getcallerpc(&v)); free(v); - unlock(&malloclock); } void* @@ -42,9 +36,7 @@ p9calloc(ulong a, ulong b) if(a*b == 0) a = b = 1; - lock(&malloclock); v = calloc(a*b, 1); - unlock(&malloclock); print("p9calloc %lud %lud => %p; pc %lux\n", a, b, v, getcallerpc(&a)); return v; } @@ -54,9 +46,7 @@ p9realloc(void *v, ulong n) { void *vv; - lock(&malloclock); vv = realloc(v, n); - unlock(&malloclock); print("p9realloc %p %lud => %p; pc %lux\n", v, n, vv, getcallerpc(&v)); return vv; } diff --git a/src/lib9/debugmalloc.c b/src/lib9/debugmalloc.c index 51a2c61f..744af835 100644 --- a/src/lib9/debugmalloc.c +++ b/src/lib9/debugmalloc.c @@ -6,7 +6,6 @@ * The Unix libc routines cannot be trusted to do their own locking. * Sad but apparently true. */ -static Lock malloclock; static int mallocpid; /* @@ -112,11 +111,9 @@ p9malloc(ulong n) if(n == 0) n++; /*fprint(2, "%s %d malloc\n", argv0, getpid()); */ - lock(&malloclock); mallocpid = getpid(); v = malloc(n+Overhead); v = mark(v, getcallerpc(&n), n, MallocMagic); - unlock(&malloclock); /*fprint(2, "%s %d donemalloc\n", argv0, getpid()); */ return v; } @@ -128,11 +125,9 @@ p9free(void *v) return; /*fprint(2, "%s %d free\n", argv0, getpid()); */ - lock(&malloclock); mallocpid = getpid(); v = mark(v, getcallerpc(&v), 0, FreeMagic); free(v); - unlock(&malloclock); /*fprint(2, "%s %d donefree\n", argv0, getpid()); */ } @@ -142,11 +137,9 @@ p9calloc(ulong a, ulong b) void *v; /*fprint(2, "%s %d calloc\n", argv0, getpid()); */ - lock(&malloclock); mallocpid = getpid(); v = calloc(a*b+Overhead, 1); v = mark(v, getcallerpc(&a), a*b, CallocMagic); - unlock(&malloclock); /*fprint(2, "%s %d donecalloc\n", argv0, getpid()); */ return v; } @@ -155,12 +148,10 @@ void* p9realloc(void *v, ulong n) { /*fprint(2, "%s %d realloc\n", argv0, getpid()); */ - lock(&malloclock); mallocpid = getpid(); v = mark(v, getcallerpc(&v), 0, CheckMagic); v = realloc(v, n+Overhead); v = mark(v, getcallerpc(&v), n, ReallocMagic); - unlock(&malloclock); /*fprint(2, "%s %d donerealloc\n", argv0, getpid()); */ return v; } diff --git a/src/lib9/malloc.c b/src/lib9/malloc.c index 33593aa2..695ff8bc 100644 --- a/src/lib9/malloc.c +++ b/src/lib9/malloc.c @@ -7,50 +7,31 @@ #define NOPLAN9DEFINES #include -static Lock malloclock; void* p9malloc(ulong n) { - void *v; - if(n == 0) n++; - lock(&malloclock); - v = malloc(n); - unlock(&malloclock); - return v; + return malloc(n); } void p9free(void *v) { - if(v == nil) - return; - lock(&malloclock); free(v); - unlock(&malloclock); } void* p9calloc(ulong a, ulong b) { - void *v; - if(a*b == 0) a = b = 1; - - lock(&malloclock); - v = calloc(a*b, 1); - unlock(&malloclock); - return v; + return calloc(a, b); } void* p9realloc(void *v, ulong n) { - lock(&malloclock); - v = realloc(v, n); - unlock(&malloclock); - return v; + return realloc(v, n); } -- cgit v1.2.3 From 23a23689807560ee80806a339be0f7e7cef6340d Mon Sep 17 00:00:00 2001 From: Dan Cross Date: Thu, 16 Jan 2020 17:01:44 +0000 Subject: libthread: NetBSD supports pthreads, remove ancient systems in sysofiles.sh Signed-off-by: Dan Cross --- src/libthread/sysofiles.sh | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'src') diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index f76b975a..e1eb8f03 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -4,15 +4,8 @@ test -f $PLAN9/config && . $PLAN9/config tag="$OBJTYPE-$SYSNAME-${SYSVERSION:-`uname -r`}-${CC9:-cc}" case "$tag" in -*-Linux-2.[0-5]*) - # will have to fix this for linux power pc - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o - ;; -*-FreeBSD-[0-4].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o - ;; *-NetBSD-*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o pthread.o stkmalloc.o ;; *-Darwin-10.[5-6].* | *-Darwin-[89].*) echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o stkmalloc.o -- cgit v1.2.3 From 1d0d432ccb000b28de3309db5f8299357a46c903 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 16 Jan 2020 12:07:42 -0500 Subject: devdraw: abort alt sequence on window change on macOS Fixes #3. --- src/cmd/devdraw/mac-screen.m | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m index 4bc3f088..dedbfb84 100644 --- a/src/cmd/devdraw/mac-screen.m +++ b/src/cmd/devdraw/mac-screen.m @@ -560,6 +560,10 @@ rpc_resizewindow(Client *c, Rectangle r) [self sendmouse:0]; } +- (void)windowDidResignKey:(id)arg { + gfx_abortcompose(self.client); +} + - (void)mouseMoved:(NSEvent*)e{ [self getmouse:e];} - (void)mouseDown:(NSEvent*)e{ [self getmouse:e];} - (void)mouseDragged:(NSEvent*)e{ [self getmouse:e];} -- cgit v1.2.3 From 57157d856e4bf66326771e8036062eb6881280ca Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Mon, 20 Jan 2020 02:43:55 +0100 Subject: libthread: rm unused ARM (get|set)mcontext (#354) They were just a duplicate of my(get|set)mcontext from the other assembly file, and unused from threadimpl.h. Change-Id: Id8003e5177ed9d37a7f0210037acbe55bbf7f708 --- src/libthread/Linux-arm-asm.s | 43 ------------------------------------------- 1 file changed, 43 deletions(-) (limited to 'src') diff --git a/src/libthread/Linux-arm-asm.s b/src/libthread/Linux-arm-asm.s index 5a285bf2..721ea43b 100644 --- a/src/libthread/Linux-arm-asm.s +++ b/src/libthread/Linux-arm-asm.s @@ -8,46 +8,3 @@ _tas: swp r3, r3, [r0] mov r0, r3 mov pc, lr - -.globl getmcontext -getmcontext: - str r1, [r0,#4] - str r2, [r0,#8] - str r3, [r0,#12] - str r4, [r0,#16] - str r5, [r0,#20] - str r6, [r0,#24] - str r7, [r0,#28] - str r8, [r0,#32] - str r9, [r0,#36] - str r10, [r0,#40] - str r11, [r0,#44] - str r12, [r0,#48] - str r13, [r0,#52] - str r14, [r0,#56] - /* store 1 as r0-to-restore */ - mov r1, #1 - str r1, [r0] - /* return 0 */ - mov r0, #0 - mov pc, lr - -.globl setmcontext -setmcontext: - ldr r1, [r0,#4] - ldr r2, [r0,#8] - ldr r3, [r0,#12] - ldr r4, [r0,#16] - ldr r5, [r0,#20] - ldr r6, [r0,#24] - ldr r7, [r0,#28] - ldr r8, [r0,#32] - ldr r9, [r0,#36] - ldr r10, [r0,#40] - ldr r11, [r0,#44] - ldr r12, [r0,#48] - ldr r13, [r0,#52] - ldr r14, [r0,#56] - ldr r0, [r0] - mov pc, lr - -- cgit v1.2.3 From d15607b9ddd9872b48fe3ac8c68f9637044be310 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 20:51:28 -0500 Subject: libthread: rm OpenBSD.c This should have been deleted in 20f5692b (2012-07-14), which removed the mkfile and sysofiles.sh references to it. --- src/libthread/OpenBSD.c | 145 ------------------------------------------------ 1 file changed, 145 deletions(-) delete mode 100644 src/libthread/OpenBSD.c (limited to 'src') diff --git a/src/libthread/OpenBSD.c b/src/libthread/OpenBSD.c deleted file mode 100644 index 80a50977..00000000 --- a/src/libthread/OpenBSD.c +++ /dev/null @@ -1,145 +0,0 @@ -#include "threadimpl.h" -#include "BSD.c" - -#include - -struct thread_tag { - struct thread_tag *next; - spinlock_t l; - volatile int key; - void *data; -}; - -static spinlock_t mlock; -static spinlock_t dl_lock; -static spinlock_t tag_lock; -static struct thread_tag *thread_tag_store = nil; -static uint nextkey = 0; - -void -_thread_malloc_lock(void) -{ - _spinlock(&mlock); -} - -void -_thread_malloc_unlock(void) -{ - _spinunlock(&mlock); -} - -void -_thread_malloc_init(void) -{ -} - -/* - * for ld.so - */ -void -_thread_dl_lock(int t) -{ - if(t) - _spinunlock(&dl_lock); - else - _spinlock(&dl_lock); -} - -/* - * for libc - */ -static void -_thread_tag_init(void **tag) -{ - struct thread_tag *t; - - _spinlock(&tag_lock); - if(*tag == nil) { - t = malloc(sizeof (*t)); - if(t != nil) { - memset(&t->l, 0, sizeof(t->l)); - t->key = nextkey++; - *tag = t; - } - } - _spinunlock(&tag_lock); -} - -void -_thread_tag_lock(void **tag) -{ - struct thread_tag *t; - - if(*tag == nil) - _thread_tag_init(tag); - t = *tag; - _spinlock(&t->l); -} - -void -_thread_tag_unlock(void **tag) -{ - struct thread_tag *t; - - if(*tag == nil) - _thread_tag_init(tag); - t = *tag; - _spinunlock(&t->l); -} - -static void * -_thread_tag_insert(struct thread_tag *t, void *v) -{ - t->data = v; - t->next = thread_tag_store; - thread_tag_store = t; - return t; -} - -static void * -_thread_tag_lookup(struct thread_tag *tag, int size) -{ - struct thread_tag *t; - void *p; - - _spinlock(&tag->l); - for(t = thread_tag_store; t != nil; t = t->next) - if(t->key == tag->key) - break; - if(t == nil) { - p = malloc(size); - if(p == nil) { - _spinunlock(&tag->l); - return nil; - } - _thread_tag_insert(tag, p); - } - _spinunlock(&tag->l); - return tag->data; -} - -void * -_thread_tag_storage(void **tag, void *storage, size_t n, void *err) -{ - struct thread_tag *t; - void *r; - - if(*tag == nil) - _thread_tag_init(tag); - t = *tag; - - r = _thread_tag_lookup(t, n); - if(r == nil) - r = err; - else - memcpy(r, storage, n); - return r; -} - -void -_pthreadinit(void) -{ - __isthreaded = 1; - dlctl(nil, DL_SETTHREADLCK, _thread_dl_lock); - signal(SIGUSR2, sigusr2handler); -} -- cgit v1.2.3 From 8dcb18f71b1917713d4743ab10968c527acdc62e Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 21:25:33 -0500 Subject: libthread: rm FreeBSD 4 code Pretty sure FreeBSD 4 is gone now. :-) --- src/libthread/BSD.c | 403 ---------------------------------------- src/libthread/FreeBSD-386-asm.s | 52 ------ src/libthread/FreeBSD.c | 34 ---- src/libthread/OpenBSD-386-asm.s | 53 +++++- src/libthread/mkfile | 1 - src/libthread/threadimpl.h | 9 - 6 files changed, 52 insertions(+), 500 deletions(-) delete mode 100644 src/libthread/BSD.c delete mode 100644 src/libthread/FreeBSD-386-asm.s delete mode 100644 src/libthread/FreeBSD.c (limited to 'src') diff --git a/src/libthread/BSD.c b/src/libthread/BSD.c deleted file mode 100644 index 737c0a63..00000000 --- a/src/libthread/BSD.c +++ /dev/null @@ -1,403 +0,0 @@ -#undef exits -#undef _exits - -extern int __isthreaded; - -/* - * spin locks - */ -extern int _tas(int*); - -void -_threadunlock(Lock *l, ulong pc) -{ - USED(pc); - - l->held = 0; -} - -int -_threadlock(Lock *l, int block, ulong pc) -{ - int i; - - USED(pc); - - /* once fast */ - if(!_tas(&l->held)) - return 1; - if(!block) - return 0; - - /* a thousand times pretty fast */ - for(i=0; i<1000; i++){ - if(!_tas(&l->held)) - return 1; - sleep(0); - } - /* increasingly slow */ - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1000); - } - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10*1000); - } - /* now nice and slow */ - for(i=0; i<1000; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100*1000); - } - /* take your time */ - while(_tas(&l->held)) - usleep(1000*1000); - return 1; -} - -/* - * For libc. - */ - -typedef struct { - volatile long access_lock; - volatile long lock_owner; - volatile char *fname; - volatile int lineno; -} spinlock_t; - -void -_spinlock(spinlock_t *lk) -{ - lock((Lock*)&lk->access_lock); -} - -void -_spinunlock(spinlock_t *lk) -{ - unlock((Lock*)&lk->access_lock); -} - - - -/* - * sleep and wakeup - */ -static void -ign(int x) -{ - USED(x); -} - -static void /*__attribute__((constructor))*/ -ignusr1(int restart) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_handler = ign; - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGUSR1); - if(restart) - sa.sa_flags = SA_RESTART; - sigaction(SIGUSR1, &sa, nil); -} - -void -_procsleep(_Procrendez *r) -{ - sigset_t mask; - - /* - * Go to sleep. - * - * Block USR1, set the handler to interrupt system calls, - * unlock the vouslock so our waker can wake us, - * and then suspend. - */ -again: - 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. - */ - lock(r->l); - ignusr1(1); - if(r->asleep && r->pid == getpid()){ - /* Didn't really wake up - signal from something else */ - goto again; - } -} - -void -_procwakeup(_Procrendez *r) -{ - if(r->asleep){ - r->asleep = 0; - assert(r->pid >= 1); - kill(r->pid, SIGUSR1); - } -} - -void -_procwakeupandunlock(_Procrendez *r) -{ - _procwakeup(r); - unlock(r->l); -} - - -/* - * process creation and exit - */ -typedef struct Stackfree Stackfree; -struct Stackfree -{ - Stackfree *next; - int pid; -}; -static Lock stacklock; -static Stackfree *stackfree; - -static void -delayfreestack(uchar *stk) -{ - Stackfree *sf; - - sf = (Stackfree*)stk; - sf->pid = getpid(); - lock(&stacklock); - sf->next = stackfree; - stackfree = sf; - unlock(&stacklock); -} - -static void -dofreestacks(void) -{ - Stackfree *sf, *last, *next; - - if(stackfree==nil || !canlock(&stacklock)) - return; - - for(last=nil,sf=stackfree; sf; last=sf,sf=next){ - next = sf->next; - if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH){ - free(sf); - if(last) - last->next = next; - else - stackfree = next; - sf = last; - } - } - unlock(&stacklock); -} - -static int -startprocfn(void *v) -{ - void **a; - uchar *stk; - void (*fn)(void*); - Proc *p; - - a = (void**)v; - fn = a[0]; - p = a[1]; - stk = a[2]; - free(a); - p->osprocid = getpid(); - - (*fn)(p); - - delayfreestack(stk); - _exit(0); - return 0; -} - -void -_procstart(Proc *p, void (*fn)(Proc*)) -{ - void **a; - uchar *stk; - int pid; - - dofreestacks(); - a = malloc(3*sizeof a[0]); - if(a == nil) - sysfatal("_procstart malloc: %r"); - stk = malloc(65536); - if(stk == nil) - sysfatal("_procstart malloc stack: %r"); - - a[0] = fn; - a[1] = p; - a[2] = stk; - - pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, stk+65536-64, startprocfn, a); - if(pid < 0){ - fprint(2, "_procstart rfork_thread: %r\n"); - abort(); - } -} - -static char *threadexitsmsg; -void -sigusr2handler(int s) -{ -/* fprint(2, "%d usr2 %d\n", time(0), getpid()); */ - if(threadexitsmsg) - _exits(threadexitsmsg); -} - -void -threadexitsall(char *msg) -{ - static int pid[1024]; - int i, npid, mypid; - Proc *p; - - if(msg == nil) - msg = ""; - - /* - * Only one guy, ever, gets to run this. - * If two guys do it, inevitably they end up - * tripping over each other in the underlying - * C library exit() implementation, which is - * trying to run the atexit handlers and apparently - * not thread safe. This has been observed on - * both Linux and OpenBSD. Sigh. - */ - { - static Lock onelock; - if(!canlock(&onelock)) - _exits(threadexitsmsg); - threadexitsmsg = msg; - } - - if(msg == nil) - msg = ""; - mypid = getpid(); - lock(&_threadprocslock); - threadexitsmsg = msg; - npid = 0; - for(p=_threadprocs; p; p=p->next) - if(p->osprocid != mypid && p->osprocid >= 1) - pid[npid++] = p->osprocid; - for(i=0; ipid == pid) - return p; - if(p->pid == 0){ - print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h); - break; - } - } - fprint(2, "myperproc %d: cannot find self\n", pid); - abort(); - return nil; -} - -static Perproc* -newperproc(void) -{ - int i, pid, h; - Perproc *p; - - lock(&perlock); - pid = getpid(); - h = pid%nelem(perproc); - for(i=0; ipid == pid || p->pid == -1 || p->pid == 0){ - p->pid = pid; - unlock(&perlock); - return p; - } - } - fprint(2, "newperproc %d: out of procs\n", pid); - abort(); - return nil; -} - -Proc* -_threadproc(void) -{ - return myperproc()->proc; -} - -void -_threadsetproc(Proc *p) -{ - Perproc *pp; - - if(p) - p->osprocid = getpid(); - pp = newperproc(); - pp->proc = p; - if(p == nil) - pp->pid = -1; -} - -void -_threadpexit(void) -{ - _exit(0); -} diff --git a/src/libthread/FreeBSD-386-asm.s b/src/libthread/FreeBSD-386-asm.s deleted file mode 100644 index 42169853..00000000 --- a/src/libthread/FreeBSD-386-asm.s +++ /dev/null @@ -1,52 +0,0 @@ -.globl _tas -_tas: - movl $0xCAFEBABE, %eax - movl 4(%esp), %ecx - xchgl %eax, 0(%ecx) - ret - -.globl getmcontext -getmcontext: - movl 4(%esp), %eax - - movl %fs, 8(%eax) - movl %es, 12(%eax) - movl %ds, 16(%eax) - movl %ss, 76(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %ebp, 28(%eax) - movl %ebx, 36(%eax) - movl %edx, 40(%eax) - movl %ecx, 44(%eax) - - movl $1, 48(%eax) /* %eax */ - movl (%esp), %ecx /* %eip */ - movl %ecx, 60(%eax) - leal 4(%esp), %ecx /* %esp */ - movl %ecx, 72(%eax) - - movl 44(%eax), %ecx /* restore %ecx */ - movl $0, %eax - ret - -.globl setmcontext -setmcontext: - movl 4(%esp), %eax - - movl 8(%eax), %fs - movl 12(%eax), %es - movl 16(%eax), %ds - movl 76(%eax), %ss - movl 20(%eax), %edi - movl 24(%eax), %esi - movl 28(%eax), %ebp - movl 36(%eax), %ebx - movl 40(%eax), %edx - movl 44(%eax), %ecx - - movl 72(%eax), %esp - pushl 60(%eax) /* new %eip */ - movl 48(%eax), %eax - ret - diff --git a/src/libthread/FreeBSD.c b/src/libthread/FreeBSD.c deleted file mode 100644 index 5c282465..00000000 --- a/src/libthread/FreeBSD.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "threadimpl.h" - -#include "BSD.c" - -/* - * FreeBSD 4 and earlier needs the context functions. - */ -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - int *sp; - - sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4; - sp -= argc; - memmove(sp, &argc+1, argc*sizeof(int)); - *--sp = 0; /* return address */ - ucp->uc_mcontext.mc_eip = (long)func; - ucp->uc_mcontext.mc_esp = (int)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} - -void -_pthreadinit(void) -{ - __isthreaded = 1; - signal(SIGUSR2, sigusr2handler); -} diff --git a/src/libthread/OpenBSD-386-asm.s b/src/libthread/OpenBSD-386-asm.s index dad1b536..42169853 100644 --- a/src/libthread/OpenBSD-386-asm.s +++ b/src/libthread/OpenBSD-386-asm.s @@ -1 +1,52 @@ -#include "FreeBSD-386-asm.s" +.globl _tas +_tas: + movl $0xCAFEBABE, %eax + movl 4(%esp), %ecx + xchgl %eax, 0(%ecx) + ret + +.globl getmcontext +getmcontext: + movl 4(%esp), %eax + + movl %fs, 8(%eax) + movl %es, 12(%eax) + movl %ds, 16(%eax) + movl %ss, 76(%eax) + movl %edi, 20(%eax) + movl %esi, 24(%eax) + movl %ebp, 28(%eax) + movl %ebx, 36(%eax) + movl %edx, 40(%eax) + movl %ecx, 44(%eax) + + movl $1, 48(%eax) /* %eax */ + movl (%esp), %ecx /* %eip */ + movl %ecx, 60(%eax) + leal 4(%esp), %ecx /* %esp */ + movl %ecx, 72(%eax) + + movl 44(%eax), %ecx /* restore %ecx */ + movl $0, %eax + ret + +.globl setmcontext +setmcontext: + movl 4(%esp), %eax + + movl 8(%eax), %fs + movl 12(%eax), %es + movl 16(%eax), %ds + movl 76(%eax), %ss + movl 20(%eax), %edi + movl 24(%eax), %esi + movl 28(%eax), %ebp + movl 36(%eax), %ebx + movl 40(%eax), %edx + movl 44(%eax), %ecx + + movl 72(%eax), %esp + pushl 60(%eax) /* new %eip */ + movl 48(%eax), %eax + ret + diff --git a/src/libthread/mkfile b/src/libthread/mkfile index f621ac60..31c4c7e5 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -16,7 +16,6 @@ OFILES=\ <$PLAN9/src/mksyslib HFILES=thread.h threadimpl.h -FreeBSD.$O: BSD.c NetBSD.$O: Linux.c tprimes: test/tprimes.$O diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 6671f23c..e26ffe6b 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -15,15 +15,6 @@ #include "libc.h" #include "thread.h" -#if defined(__FreeBSD__) && __FreeBSD__ < 5 -extern int getmcontext(mcontext_t*); -extern void setmcontext(mcontext_t*); -#define setcontext(u) setmcontext(&(u)->uc_mcontext) -#define getcontext(u) getmcontext(&(u)->uc_mcontext) -extern int swapcontext(ucontext_t*, ucontext_t*); -extern void makecontext(ucontext_t*, void(*)(), int, ...); -#endif - #if defined(__APPLE__) /* * OS X before 10.5 (Leopard) does not provide -- cgit v1.2.3 From 52397aaf2b240015533fa46f1767c20f45296465 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 20:57:09 -0500 Subject: libthread: rm Darwin pre-11.0.0 support Darwin 11.0.0 was Mac OS X 10.7.0 aka Lion. The previous version was Snow Leopard, which has been unsupported by Apple since February 2014. --- src/libthread/Darwin-386-asm.s | 52 ------------------------- src/libthread/Darwin-386.c | 30 --------------- src/libthread/Darwin-power-asm.s | 83 ---------------------------------------- src/libthread/Darwin-power.c | 24 ------------ src/libthread/sysofiles.sh | 3 -- 5 files changed, 192 deletions(-) delete mode 100644 src/libthread/Darwin-386-asm.s delete mode 100644 src/libthread/Darwin-386.c delete mode 100644 src/libthread/Darwin-power-asm.s delete mode 100644 src/libthread/Darwin-power.c (limited to 'src') diff --git a/src/libthread/Darwin-386-asm.s b/src/libthread/Darwin-386-asm.s deleted file mode 100644 index 46c96e94..00000000 --- a/src/libthread/Darwin-386-asm.s +++ /dev/null @@ -1,52 +0,0 @@ -.globl _tas -_tas: - movl $0xCAFEBABE, %eax - movl 4(%esp), %ecx - xchgl %eax, 0(%ecx) - ret - -.globl _getmcontext -_getmcontext: - movl 4(%esp), %eax - - movl %fs, 8(%eax) - movl %es, 12(%eax) - movl %ds, 16(%eax) - movl %ss, 76(%eax) - movl %edi, 20(%eax) - movl %esi, 24(%eax) - movl %ebp, 28(%eax) - movl %ebx, 36(%eax) - movl %edx, 40(%eax) - movl %ecx, 44(%eax) - - movl $1, 48(%eax) /* %eax */ - movl (%esp), %ecx /* %eip */ - movl %ecx, 60(%eax) - leal 4(%esp), %ecx /* %esp */ - movl %ecx, 72(%eax) - - movl 44(%eax), %ecx /* restore %ecx */ - movl $0, %eax - ret - -.globl _setmcontext -_setmcontext: - movl 4(%esp), %eax - - movl 8(%eax), %fs - movl 12(%eax), %es - movl 16(%eax), %ds - movl 76(%eax), %ss - movl 20(%eax), %edi - movl 24(%eax), %esi - movl 28(%eax), %ebp - movl 36(%eax), %ebx - movl 40(%eax), %edx - movl 44(%eax), %ecx - - movl 72(%eax), %esp - pushl 60(%eax) /* new %eip */ - movl 48(%eax), %eax - ret - diff --git a/src/libthread/Darwin-386.c b/src/libthread/Darwin-386.c deleted file mode 100644 index b138e420..00000000 --- a/src/libthread/Darwin-386.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - int *sp; - - sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4; - sp -= argc; - /* - * Stack pointer at call instruction (before return address - * gets pushed) must be 16-byte aligned. - */ - if((uintptr)sp%4) - abort(); - while((uintptr)sp%16) - sp--; - memmove(sp, &argc+1, argc*sizeof(int)); - *--sp = 0; /* return address */ - ucp->uc_mcontext.mc_eip = (long)func; - ucp->uc_mcontext.mc_esp = (int)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/Darwin-power-asm.s b/src/libthread/Darwin-power-asm.s deleted file mode 100644 index a064b5ea..00000000 --- a/src/libthread/Darwin-power-asm.s +++ /dev/null @@ -1,83 +0,0 @@ -/* get FPR and VR use flags with sc 0x7FF3 */ -/* get vsave with mfspr reg, 256 */ - -.text -.align 2 - -.globl __getmcontext - -__getmcontext: /* xxx: instruction scheduling */ - mflr r0 - mfcr r5 - mfctr r6 - mfxer r7 - stw r0, 0*4(r3) - stw r5, 1*4(r3) - stw r6, 2*4(r3) - stw r7, 3*4(r3) - - stw r1, 4*4(r3) - stw r2, 5*4(r3) - li r5, 1 /* return value for setmcontext */ - stw r5, 6*4(r3) - - stw r13, (0+7)*4(r3) /* callee-save GPRs */ - stw r14, (1+7)*4(r3) /* xxx: block move */ - stw r15, (2+7)*4(r3) - stw r16, (3+7)*4(r3) - stw r17, (4+7)*4(r3) - stw r18, (5+7)*4(r3) - stw r19, (6+7)*4(r3) - stw r20, (7+7)*4(r3) - stw r21, (8+7)*4(r3) - stw r22, (9+7)*4(r3) - stw r23, (10+7)*4(r3) - stw r24, (11+7)*4(r3) - stw r25, (12+7)*4(r3) - stw r26, (13+7)*4(r3) - stw r27, (14+7)*4(r3) - stw r28, (15+7)*4(r3) - stw r29, (16+7)*4(r3) - stw r30, (17+7)*4(r3) - stw r31, (18+7)*4(r3) - - li r3, 0 /* return */ - blr - -.globl __setmcontext - -__setmcontext: - lwz r13, (0+7)*4(r3) /* callee-save GPRs */ - lwz r14, (1+7)*4(r3) /* xxx: block move */ - lwz r15, (2+7)*4(r3) - lwz r16, (3+7)*4(r3) - lwz r17, (4+7)*4(r3) - lwz r18, (5+7)*4(r3) - lwz r19, (6+7)*4(r3) - lwz r20, (7+7)*4(r3) - lwz r21, (8+7)*4(r3) - lwz r22, (9+7)*4(r3) - lwz r23, (10+7)*4(r3) - lwz r24, (11+7)*4(r3) - lwz r25, (12+7)*4(r3) - lwz r26, (13+7)*4(r3) - lwz r27, (14+7)*4(r3) - lwz r28, (15+7)*4(r3) - lwz r29, (16+7)*4(r3) - lwz r30, (17+7)*4(r3) - lwz r31, (18+7)*4(r3) - - lwz r1, 4*4(r3) - lwz r2, 5*4(r3) - - lwz r0, 0*4(r3) - mtlr r0 - lwz r0, 1*4(r3) - mtcr r0 /* mtcrf 0xFF, r0 */ - lwz r0, 2*4(r3) - mtctr r0 - lwz r0, 3*4(r3) - mtxer r0 - - lwz r3, 6*4(r3) - blr diff --git a/src/libthread/Darwin-power.c b/src/libthread/Darwin-power.c deleted file mode 100644 index 3f2bf566..00000000 --- a/src/libthread/Darwin-power.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - ulong *sp, *tos; - va_list arg; - - tos = (ulong*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(ulong); - sp = tos - 16; - ucp->mc.pc = (long)func; - ucp->mc.sp = (long)sp; - va_start(arg, argc); - ucp->mc.r3 = va_arg(arg, long); - va_end(arg); -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index e1eb8f03..30a4c338 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -7,9 +7,6 @@ case "$tag" in *-NetBSD-*) echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o pthread.o stkmalloc.o ;; -*-Darwin-10.[5-6].* | *-Darwin-[89].*) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME-${OBJTYPE}.o pthread.o stkmalloc.o - ;; *-OpenBSD-*) echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o ;; -- cgit v1.2.3 From c181e39eeab0eb8cad274b7b22ce5343bd55630d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 21:01:30 -0500 Subject: libthread: rm unused sparc-ucontext.h More dead code. --- src/libthread/sparc-ucontext.h | 23 ----------------------- src/libthread/threadimpl.h | 14 -------------- 2 files changed, 37 deletions(-) delete mode 100644 src/libthread/sparc-ucontext.h (limited to 'src') diff --git a/src/libthread/sparc-ucontext.h b/src/libthread/sparc-ucontext.h deleted file mode 100644 index 36b88171..00000000 --- a/src/libthread/sparc-ucontext.h +++ /dev/null @@ -1,23 +0,0 @@ -#define setcontext(u) _setmcontext(&(u)->mc) -#define getcontext(u) _getmcontext(&(u)->mc) -typedef struct mcontext mcontext_t; -typedef struct ucontext ucontext_t; -struct mcontext -{ - int r[16]; -}; - -struct ucontext -{ - struct { - void *ss_sp; - uint ss_size; - } uc_stack; - sigset_t uc_sigmask; - mcontext_t mc; -}; - -void makecontext(ucontext_t*, void(*)(void), int, ...); -int swapcontext(ucontext_t*, ucontext_t*); -int _getmcontext(mcontext_t*); -void _setmcontext(mcontext_t*); diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index e26ffe6b..5b6d74cc 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -55,20 +55,6 @@ extern pid_t rfork_thread(int, void*, int(*)(void*), void*); #endif -/* THIS DOES NOT WORK! Don't do this! -(At least, not on Solaris. Maybe this is right for Linux, -in which case it should say if defined(__linux__) && defined(__sun__), -but surely the latter would be defined(__sparc__). - -#if defined(__sun__) -# define mcontext libthread_mcontext -# define mcontext_t libthread_mcontext_t -# define ucontext libthread_ucontext -# define ucontext_t libthread_ucontext_t -# include "sparc-ucontext.h" -#endif -*/ - #if defined(__arm__) int mygetmcontext(ulong*); void mysetmcontext(const ulong*); -- cgit v1.2.3 From 8d82ccefd2b4b058e20ae0a7e3d9ef9b6b8cf8c3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 21:03:56 -0500 Subject: libthread: remove Linux 2.4 code Linux.c was for Linux 2.4 and is no longer used directly, only indirectly because NetBSD.c was a 1-line file #including Linux.c. So mv Linux.c NetBSD.c. Also rm Linux-*-asm.s which was for Linux 2.4 as well. --- src/libthread/Linux-386-asm.s | 7 - src/libthread/Linux-arm-asm.s | 10 - src/libthread/Linux-power-asm.s | 16 -- src/libthread/Linux-sparc64-asm.s | 16 -- src/libthread/Linux.c | 462 ------------------------------------- src/libthread/NetBSD.c | 463 +++++++++++++++++++++++++++++++++++++- src/libthread/mkfile | 1 - 7 files changed, 462 insertions(+), 513 deletions(-) delete mode 100644 src/libthread/Linux-386-asm.s delete mode 100644 src/libthread/Linux-arm-asm.s delete mode 100644 src/libthread/Linux-power-asm.s delete mode 100644 src/libthread/Linux-sparc64-asm.s delete mode 100644 src/libthread/Linux.c (limited to 'src') diff --git a/src/libthread/Linux-386-asm.s b/src/libthread/Linux-386-asm.s deleted file mode 100644 index 197f12b5..00000000 --- a/src/libthread/Linux-386-asm.s +++ /dev/null @@ -1,7 +0,0 @@ -.globl _tas -_tas: - movl $0xCAFEBABE, %eax - movl 4(%esp), %ecx - xchgl %eax, 0(%ecx) - ret - diff --git a/src/libthread/Linux-arm-asm.s b/src/libthread/Linux-arm-asm.s deleted file mode 100644 index 721ea43b..00000000 --- a/src/libthread/Linux-arm-asm.s +++ /dev/null @@ -1,10 +0,0 @@ - -.globl _tas -_tas: - mov r3, #0xCA000000 - add r3, r3, #0xFE0000 - add r3, r3, #0xBA00 - add r3, r3, #0xBE - swp r3, r3, [r0] - mov r0, r3 - mov pc, lr diff --git a/src/libthread/Linux-power-asm.s b/src/libthread/Linux-power-asm.s deleted file mode 100644 index d6e21c15..00000000 --- a/src/libthread/Linux-power-asm.s +++ /dev/null @@ -1,16 +0,0 @@ - .globl _tas -_tas: - li %r0, 0 - mr %r4, %r3 - lis %r5, 0xcafe - ori %r5, %r5, 0xbabe -1: - lwarx %r3, %r0, %r4 - cmpwi %r3, 0 - bne 2f - stwcx. %r5, %r0, %r4 - bne- 1b -2: - sync - blr - diff --git a/src/libthread/Linux-sparc64-asm.s b/src/libthread/Linux-sparc64-asm.s deleted file mode 100644 index 422a1b24..00000000 --- a/src/libthread/Linux-sparc64-asm.s +++ /dev/null @@ -1,16 +0,0 @@ -! Actually sparc32 assembly. -! Debian's sparc64 port is a 32-bit user space. - - .section ".text", #alloc, #execinstr - .align 8 - .skip 16 - .global _tas -! .type _tas,2 -_tas: - or %g0,1,%o1 - swap [%o0],%o1 ! o0 points to lock; key is first word - retl - mov %o1, %o0 - - .size _tas,(.-_tas) - diff --git a/src/libthread/Linux.c b/src/libthread/Linux.c deleted file mode 100644 index 31577e87..00000000 --- a/src/libthread/Linux.c +++ /dev/null @@ -1,462 +0,0 @@ -#include "threadimpl.h" - -#undef exits -#undef _exits - -static int -timefmt(Fmt *fmt) -{ - static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - vlong ns; - Tm tm; - ns = nsec(); - tm = *localtime(time(0)); - return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d", - mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec, - (int)(ns%1000000000)/1000000); -} - -/* - * spin locks - */ -extern int _tas(int*); - -void -_threadunlock(Lock *l, ulong pc) -{ - USED(pc); - - l->held = 0; -} - -int -_threadlock(Lock *l, int block, ulong pc) -{ - int i; -static int first=1; -if(first) {first=0; fmtinstall('\001', timefmt);} - - USED(pc); - - /* once fast */ - if(!_tas(&l->held)) - return 1; - if(!block) - return 0; - - /* a thousand times pretty fast */ - for(i=0; i<1000; i++){ - if(!_tas(&l->held)) - return 1; - sched_yield(); - } - /* now increasingly slow */ - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1); - } -fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc); - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10); - } -fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc); - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100); - } -fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc); - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(1000); - } -fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc); - for(i=0; i<10; i++){ - if(!_tas(&l->held)) - return 1; - usleep(10*1000); - } -fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc); - for(i=0; i<1000; i++){ - if(!_tas(&l->held)) - return 1; - usleep(100*1000); - } -fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc); - /* take your time */ - while(_tas(&l->held)) - usleep(1000*1000); - return 1; -} - -/* - * sleep and wakeup - */ -static void -ign(int x) -{ - USED(x); -} - -static void /*__attribute__((constructor))*/ -ignusr1(int restart) -{ - struct sigaction sa; - - memset(&sa, 0, sizeof sa); - sa.sa_handler = ign; - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGUSR1); - if(restart) - sa.sa_flags = SA_RESTART; - sigaction(SIGUSR1, &sa, nil); -} - -void -_procsleep(_Procrendez *r) -{ - sigset_t mask; - - /* - * Go to sleep. - * - * Block USR1, set the handler to interrupt system calls, - * unlock the vouslock so our waker can wake us, - * and then suspend. - */ -again: - 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. - */ - lock(r->l); - ignusr1(1); - if(r->asleep && r->pid == getpid()){ - /* Didn't really wake up - signal from something else */ - goto again; - } -} - -void -_procwakeupandunlock(_Procrendez *r) -{ - int pid; - - pid = 0; - if(r->asleep){ - r->asleep = 0; - assert(r->pid >= 1); - pid = r->pid; - } - assert(r->l); - unlock(r->l); - if(pid) - kill(pid, SIGUSR1); -} - -/* - * process creation and exit - */ -typedef struct Stackfree Stackfree; -struct Stackfree -{ - Stackfree *next; - int pid; - int pid1; -}; -static Lock stacklock; -static Stackfree *stackfree; - -static void -delayfreestack(uchar *stk, int pid, int pid1) -{ - Stackfree *sf; - - sf = (Stackfree*)stk; - sf->pid = pid; - sf->pid1 = pid1; - lock(&stacklock); - sf->next = stackfree; - stackfree = sf; - unlock(&stacklock); -} - -static void -dofreestacks(void) -{ - Stackfree *sf, *last, *next; - - if(stackfree==nil || !canlock(&stacklock)) - return; - - for(last=nil,sf=stackfree; sf; last=sf,sf=next){ - next = sf->next; - if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH) - if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){ - free(sf); - if(last) - last->next = next; - else - stackfree = next; - sf = last; - } - } - unlock(&stacklock); -} - -static int -startprocfn(void *v) -{ - void **a; - uchar *stk; - void (*fn)(void*); - Proc *p; - int pid0, pid1; - - a = (void**)v; - fn = a[0]; - p = a[1]; - stk = a[2]; - pid0 = (int)a[4]; - pid1 = getpid(); - free(a); - p->osprocid = pid1; - - (*fn)(p); - - delayfreestack(stk, pid0, pid1); - _exit(0); - return 0; -} - -/* - * indirect through here so that parent need not wait for child zombie - * - * slight race - if child exits and then another process starts before we - * manage to exit, we'll be running on a freed stack. - */ -static int -trampnowait(void *v) -{ - void **a; - int *kidpid; - - a = (void*)v; - kidpid = a[3]; - a[4] = (void*)getpid(); - *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a); - _exit(0); - return 0; -} - -void -_procstart(Proc *p, void (*fn)(Proc*)) -{ - void **a; - uchar *stk; - int pid, kidpid, status; - - dofreestacks(); - a = malloc(5*sizeof a[0]); - if(a == nil) - sysfatal("_procstart malloc: %r"); - stk = malloc(65536); - if(stk == nil) - sysfatal("_procstart malloc stack: %r"); - - a[0] = fn; - a[1] = p; - a[2] = stk; - a[3] = &kidpid; - kidpid = -1; - - pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a); - if(pid > 0) - if(wait4(pid, &status, __WALL, 0) < 0) - fprint(2, "ffork wait4: %r\n"); - if(pid < 0 || kidpid < 0){ - fprint(2, "_procstart clone: %r\n"); - abort(); - } -} - -static char *threadexitsmsg; -void -sigusr2handler(int s) -{ -/* fprint(2, "%d usr2 %d\n", time(0), getpid()); */ - if(threadexitsmsg) - _exits(threadexitsmsg); -} - -void -threadexitsall(char *msg) -{ - static int pid[1024]; - int i, npid, mypid; - Proc *p; - - if(msg == nil) - msg = ""; - - /* - * Only one guy, ever, gets to run this. - * If two guys do it, inevitably they end up - * tripping over each other in the underlying - * C library exit() implementation, which is - * trying to run the atexit handlers and apparently - * not thread safe. This has been observed on - * both Linux and OpenBSD. Sigh. - */ - { - static Lock onelock; - if(!canlock(&onelock)) - _exits(threadexitsmsg); - threadexitsmsg = msg; - } - - mypid = getpid(); - lock(&_threadprocslock); - npid = 0; - for(p=_threadprocs; p; p=p->next) - if(p->osprocid != mypid && p->osprocid >= 1) - pid[npid++] = p->osprocid; - for(i=0; ipid == pid) - return p; - if(p->pid == 0){ - print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h); - break; - } - } - fprint(2, "myperproc %d (%s): cannot find self\n", pid, argv0); - abort(); - return nil; -} - -static Perproc* -newperproc(void) -{ - int i, pid, h; - Perproc *p; - - lock(&perlock); - pid = getpid(); - h = pid%nelem(perproc); - for(i=0; ipid == pid || p->pid == -1 || p->pid == 0){ - p->pid = pid; - unlock(&perlock); - return p; - } - } - fprint(2, "newperproc %d: out of procs\n", pid); - abort(); - return nil; -} - -Proc* -_threadproc(void) -{ - return myperproc()->proc; -} - -void -_threadsetproc(Proc *p) -{ - Perproc *pp; - - if(p) - p->osprocid = getpid(); - pp = newperproc(); - pp->proc = p; - if(p == nil) - pp->pid = -1; -} - -void -_pthreadinit(void) -{ - signal(SIGUSR2, sigusr2handler); -} - -void -_threadpexit(void) -{ - _exit(0); -} - -#ifdef __arm__ -void -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) -{ - int i, *sp; - va_list arg; - - sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4; - va_start(arg, argc); - for(i=0; i<4 && iuc_mcontext.gregs[i] = va_arg(arg, uint); - va_end(arg); - uc->uc_mcontext.gregs[13] = (uint)sp; - uc->uc_mcontext.gregs[14] = (uint)fn; -} - -int -swapcontext(ucontext_t *oucp, const ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} -#endif diff --git a/src/libthread/NetBSD.c b/src/libthread/NetBSD.c index 37dabe9c..31577e87 100644 --- a/src/libthread/NetBSD.c +++ b/src/libthread/NetBSD.c @@ -1 +1,462 @@ -#include "Linux.c" +#include "threadimpl.h" + +#undef exits +#undef _exits + +static int +timefmt(Fmt *fmt) +{ + static char *mon[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + vlong ns; + Tm tm; + ns = nsec(); + tm = *localtime(time(0)); + return fmtprint(fmt, "%s %2d %02d:%02d:%02d.%03d", + mon[tm.mon], tm.mday, tm.hour, tm.min, tm.sec, + (int)(ns%1000000000)/1000000); +} + +/* + * spin locks + */ +extern int _tas(int*); + +void +_threadunlock(Lock *l, ulong pc) +{ + USED(pc); + + l->held = 0; +} + +int +_threadlock(Lock *l, int block, ulong pc) +{ + int i; +static int first=1; +if(first) {first=0; fmtinstall('\001', timefmt);} + + USED(pc); + + /* once fast */ + if(!_tas(&l->held)) + return 1; + if(!block) + return 0; + + /* a thousand times pretty fast */ + for(i=0; i<1000; i++){ + if(!_tas(&l->held)) + return 1; + sched_yield(); + } + /* now increasingly slow */ + for(i=0; i<10; i++){ + if(!_tas(&l->held)) + return 1; + usleep(1); + } +fprint(2, "%\001 %s: lock loop1 %p from %lux\n", argv0, l, pc); + for(i=0; i<10; i++){ + if(!_tas(&l->held)) + return 1; + usleep(10); + } +fprint(2, "%\001 %s: lock loop2 %p from %lux\n", argv0, l, pc); + for(i=0; i<10; i++){ + if(!_tas(&l->held)) + return 1; + usleep(100); + } +fprint(2, "%\001 %s: lock loop3 %p from %lux\n", argv0, l, pc); + for(i=0; i<10; i++){ + if(!_tas(&l->held)) + return 1; + usleep(1000); + } +fprint(2, "%\001 %s: lock loop4 %p from %lux\n", argv0, l, pc); + for(i=0; i<10; i++){ + if(!_tas(&l->held)) + return 1; + usleep(10*1000); + } +fprint(2, "%\001 %s: lock loop5 %p from %lux\n", argv0, l, pc); + for(i=0; i<1000; i++){ + if(!_tas(&l->held)) + return 1; + usleep(100*1000); + } +fprint(2, "%\001 %s: lock loop6 %p from %lux\n", argv0, l, pc); + /* take your time */ + while(_tas(&l->held)) + usleep(1000*1000); + return 1; +} + +/* + * sleep and wakeup + */ +static void +ign(int x) +{ + USED(x); +} + +static void /*__attribute__((constructor))*/ +ignusr1(int restart) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof sa); + sa.sa_handler = ign; + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGUSR1); + if(restart) + sa.sa_flags = SA_RESTART; + sigaction(SIGUSR1, &sa, nil); +} + +void +_procsleep(_Procrendez *r) +{ + sigset_t mask; + + /* + * Go to sleep. + * + * Block USR1, set the handler to interrupt system calls, + * unlock the vouslock so our waker can wake us, + * and then suspend. + */ +again: + 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. + */ + lock(r->l); + ignusr1(1); + if(r->asleep && r->pid == getpid()){ + /* Didn't really wake up - signal from something else */ + goto again; + } +} + +void +_procwakeupandunlock(_Procrendez *r) +{ + int pid; + + pid = 0; + if(r->asleep){ + r->asleep = 0; + assert(r->pid >= 1); + pid = r->pid; + } + assert(r->l); + unlock(r->l); + if(pid) + kill(pid, SIGUSR1); +} + +/* + * process creation and exit + */ +typedef struct Stackfree Stackfree; +struct Stackfree +{ + Stackfree *next; + int pid; + int pid1; +}; +static Lock stacklock; +static Stackfree *stackfree; + +static void +delayfreestack(uchar *stk, int pid, int pid1) +{ + Stackfree *sf; + + sf = (Stackfree*)stk; + sf->pid = pid; + sf->pid1 = pid1; + lock(&stacklock); + sf->next = stackfree; + stackfree = sf; + unlock(&stacklock); +} + +static void +dofreestacks(void) +{ + Stackfree *sf, *last, *next; + + if(stackfree==nil || !canlock(&stacklock)) + return; + + for(last=nil,sf=stackfree; sf; last=sf,sf=next){ + next = sf->next; + if(sf->pid >= 1 && kill(sf->pid, 0) < 0 && errno == ESRCH) + if(sf->pid1 >= 1 && kill(sf->pid1, 0) < 0 && errno == ESRCH){ + free(sf); + if(last) + last->next = next; + else + stackfree = next; + sf = last; + } + } + unlock(&stacklock); +} + +static int +startprocfn(void *v) +{ + void **a; + uchar *stk; + void (*fn)(void*); + Proc *p; + int pid0, pid1; + + a = (void**)v; + fn = a[0]; + p = a[1]; + stk = a[2]; + pid0 = (int)a[4]; + pid1 = getpid(); + free(a); + p->osprocid = pid1; + + (*fn)(p); + + delayfreestack(stk, pid0, pid1); + _exit(0); + return 0; +} + +/* + * indirect through here so that parent need not wait for child zombie + * + * slight race - if child exits and then another process starts before we + * manage to exit, we'll be running on a freed stack. + */ +static int +trampnowait(void *v) +{ + void **a; + int *kidpid; + + a = (void*)v; + kidpid = a[3]; + a[4] = (void*)getpid(); + *kidpid = clone(startprocfn, a[2]+65536-512, CLONE_VM|CLONE_FILES, a); + _exit(0); + return 0; +} + +void +_procstart(Proc *p, void (*fn)(Proc*)) +{ + void **a; + uchar *stk; + int pid, kidpid, status; + + dofreestacks(); + a = malloc(5*sizeof a[0]); + if(a == nil) + sysfatal("_procstart malloc: %r"); + stk = malloc(65536); + if(stk == nil) + sysfatal("_procstart malloc stack: %r"); + + a[0] = fn; + a[1] = p; + a[2] = stk; + a[3] = &kidpid; + kidpid = -1; + + pid = clone(trampnowait, stk+65536-16, CLONE_VM|CLONE_FILES, a); + if(pid > 0) + if(wait4(pid, &status, __WALL, 0) < 0) + fprint(2, "ffork wait4: %r\n"); + if(pid < 0 || kidpid < 0){ + fprint(2, "_procstart clone: %r\n"); + abort(); + } +} + +static char *threadexitsmsg; +void +sigusr2handler(int s) +{ +/* fprint(2, "%d usr2 %d\n", time(0), getpid()); */ + if(threadexitsmsg) + _exits(threadexitsmsg); +} + +void +threadexitsall(char *msg) +{ + static int pid[1024]; + int i, npid, mypid; + Proc *p; + + if(msg == nil) + msg = ""; + + /* + * Only one guy, ever, gets to run this. + * If two guys do it, inevitably they end up + * tripping over each other in the underlying + * C library exit() implementation, which is + * trying to run the atexit handlers and apparently + * not thread safe. This has been observed on + * both Linux and OpenBSD. Sigh. + */ + { + static Lock onelock; + if(!canlock(&onelock)) + _exits(threadexitsmsg); + threadexitsmsg = msg; + } + + mypid = getpid(); + lock(&_threadprocslock); + npid = 0; + for(p=_threadprocs; p; p=p->next) + if(p->osprocid != mypid && p->osprocid >= 1) + pid[npid++] = p->osprocid; + for(i=0; ipid == pid) + return p; + if(p->pid == 0){ + print("found 0 at %d (h=%d)\n", (i+h)%nelem(perproc), h); + break; + } + } + fprint(2, "myperproc %d (%s): cannot find self\n", pid, argv0); + abort(); + return nil; +} + +static Perproc* +newperproc(void) +{ + int i, pid, h; + Perproc *p; + + lock(&perlock); + pid = getpid(); + h = pid%nelem(perproc); + for(i=0; ipid == pid || p->pid == -1 || p->pid == 0){ + p->pid = pid; + unlock(&perlock); + return p; + } + } + fprint(2, "newperproc %d: out of procs\n", pid); + abort(); + return nil; +} + +Proc* +_threadproc(void) +{ + return myperproc()->proc; +} + +void +_threadsetproc(Proc *p) +{ + Perproc *pp; + + if(p) + p->osprocid = getpid(); + pp = newperproc(); + pp->proc = p; + if(p == nil) + pp->pid = -1; +} + +void +_pthreadinit(void) +{ + signal(SIGUSR2, sigusr2handler); +} + +void +_threadpexit(void) +{ + _exit(0); +} + +#ifdef __arm__ +void +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) +{ + int i, *sp; + va_list arg; + + sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4; + va_start(arg, argc); + for(i=0; i<4 && iuc_mcontext.gregs[i] = va_arg(arg, uint); + va_end(arg); + uc->uc_mcontext.gregs[13] = (uint)sp; + uc->uc_mcontext.gregs[14] = (uint)fn; +} + +int +swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +{ + if(getcontext(oucp) == 0) + setcontext(ucp); + return 0; +} +#endif diff --git a/src/libthread/mkfile b/src/libthread/mkfile index 31c4c7e5..a083fd01 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -16,7 +16,6 @@ OFILES=\ <$PLAN9/src/mksyslib HFILES=thread.h threadimpl.h -NetBSD.$O: Linux.c tprimes: test/tprimes.$O 9l -o $target test/$target.$O -- cgit v1.2.3 From cb8f7357867a2a5d0bd742ceeb77bce9ad5f435c Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 21:10:11 -0500 Subject: all: remove Linux 2.4 vs 2.6 detection Linux 2.4 is dead. (The libthread code hasn't worked for Linux 2.4 for a long time.) --- src/libthread/README.Linux | 40 ---------------------------------------- src/libthread/sysofiles.sh | 7 +++---- 2 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 src/libthread/README.Linux (limited to 'src') diff --git a/src/libthread/README.Linux b/src/libthread/README.Linux deleted file mode 100644 index 04c491a8..00000000 --- a/src/libthread/README.Linux +++ /dev/null @@ -1,40 +0,0 @@ -Thread support on Linux is confused by the recent thread local storage (TLS) -support that has been put into the ELF tool chain. The TLS libraries are -installed in /lib/tls on most Linux systems. - -We provide two different implementations of the os-dependent parts -of libthread for Linux. The first is intended for use on Linux 2.4 and earlier -kernels, which do not support TLS. It is in Linux.c and Linuxasm.c and -does not use the pthread interface. The second is intended for Linux 2.6 -and later kernels, which do support TLS. It is in pthread.c and uses the -standard pthread interface. It expects to be linked against the TLS-aware -thread library aka NPTL. - -If you use Linux.c and Linuxasm.c with TLS libraries, they do not -set up the TLS properly so you will get incorrect programs. -For example, there will only be one errno among all the procs -in your program instead of one per proc. The pthread NPTL -implementation is needed to use the TLS libraries properly. - -If you use pthread.c without TLS libraries (i.e., with the old Linux -pthread library known as LinuxThreads), then you will also get -incorrect programs, although more obviously so. The LinuxThreads -library assumes it can look at the stack pointer to distinguish between -threads, but libthread does its own stack management, breaking this -assumption. If you run a pthread-compiled program with the -LinuxThreads library, LinuxThreads itself will cause a segmentation -fault in __pthread_getspecific() the first time it is called from a -non-standard stack. - -So, it is important that you compile binaries that match your -system's choice of TLS vs. not-TLS libraries. The hard part is figuring -out which your system has chosen. Plan9port looks at the kernel -version you are running and assumes that on kernels that support -TLS (2.6+) you will be using TLS. - -Apparently Gentoo and maybe other distributions do not follow this rule. -They use non-TLS libraries even on kernels that can support TLS. -To accomodate them, you can add a line SYSVERSION=2.4 to $PLAN9/config -to force the build to think you are running an old kernel. -The INSTALL script sets up this file automatically on Linux systems. - diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index 30a4c338..fd60f131 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -2,12 +2,11 @@ test -f $PLAN9/config && . $PLAN9/config -tag="$OBJTYPE-$SYSNAME-${SYSVERSION:-`uname -r`}-${CC9:-cc}" -case "$tag" in -*-NetBSD-*) +case "$SYSNAME" in +NetBSD) echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o pthread.o stkmalloc.o ;; -*-OpenBSD-*) +OpenBSD) echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o ;; *) -- cgit v1.2.3 From ac8042dfa9819f76ccfedd4aa36c1239322808b8 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 21:14:20 -0500 Subject: libthread: rm NetBSD pthread reference in sysofiles.sh It may be that pthreads on NetBSD is now good enough, but the build as written (introduced in 23a2368 at my suggestion) is certainly broken, since both NetBSD.c and pthread.c define the same functions. If NetBSD does support pthreads now, then a few things should happen together: - libthread/sysofiles.sh should drop its top NetBSD case entirely - libthread/NetBSD.c should be deleted - libthread/NetBSD-*-asm.s should be deleted - include/u.h's NetBSD case should define PLAN9PORT_USING_PTHREADS and #include For now, restore to less clearly broken build. --- src/libthread/sysofiles.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index fd60f131..9a7301a8 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -4,7 +4,7 @@ test -f $PLAN9/config && . $PLAN9/config case "$SYSNAME" in NetBSD) - echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o pthread.o stkmalloc.o + echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; OpenBSD) echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o -- cgit v1.2.3 From 41b3e8b9893a8561af7e85ca98444bc284b4013d Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 22:39:22 -0500 Subject: libthread: use consistent stack calculation code in makecontext Also reduce duplication: makecontext is per-arch not per-os-arch. May fix #353. --- src/libthread/386-ucontext.c | 22 ++++++++++++++ src/libthread/COPYRIGHT | 6 ++-- src/libthread/Darwin-x86_64-swapcontext.c | 38 ------------------------ src/libthread/Linux-arm-swapcontext.c | 24 --------------- src/libthread/Linux-sparc64-swapcontext.c | 49 ------------------------------- src/libthread/NetBSD.c | 25 ---------------- src/libthread/OpenBSD-386.c | 22 -------------- src/libthread/OpenBSD-power.c | 24 --------------- src/libthread/OpenBSD-x86_64.c | 30 ------------------- src/libthread/arm-ucontext.c | 24 +++++++++++++++ src/libthread/mkfile | 4 +-- src/libthread/power-ucontext.c | 26 ++++++++++++++++ src/libthread/sparc64-ucontext.c | 49 +++++++++++++++++++++++++++++++ src/libthread/sysofiles.sh | 29 +++++++++++++----- src/libthread/threadimpl.h | 3 ++ src/libthread/x86_64-ucontext.c | 28 ++++++++++++++++++ 16 files changed, 178 insertions(+), 225 deletions(-) create mode 100644 src/libthread/386-ucontext.c delete mode 100644 src/libthread/Darwin-x86_64-swapcontext.c delete mode 100644 src/libthread/Linux-arm-swapcontext.c delete mode 100644 src/libthread/Linux-sparc64-swapcontext.c delete mode 100644 src/libthread/OpenBSD-386.c delete mode 100644 src/libthread/OpenBSD-power.c delete mode 100644 src/libthread/OpenBSD-x86_64.c create mode 100644 src/libthread/arm-ucontext.c create mode 100644 src/libthread/power-ucontext.c create mode 100644 src/libthread/sparc64-ucontext.c create mode 100644 src/libthread/x86_64-ucontext.c (limited to 'src') diff --git a/src/libthread/386-ucontext.c b/src/libthread/386-ucontext.c new file mode 100644 index 00000000..3afa9513 --- /dev/null +++ b/src/libthread/386-ucontext.c @@ -0,0 +1,22 @@ +#include "threadimpl.h" + +void +makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + int *sp; + + sp = USPALIGN(ucp, 4); + sp -= argc; + memmove(sp, &argc+1, argc*sizeof(int)); + *--sp = 0; /* return address */ + ucp->uc_mcontext.mc_eip = (long)func; + ucp->uc_mcontext.mc_esp = (int)sp; +} + +int +swapcontext(ucontext_t *oucp, ucontext_t *ucp) +{ + if(getcontext(oucp) == 0) + setcontext(ucp); + return 0; +} diff --git a/src/libthread/COPYRIGHT b/src/libthread/COPYRIGHT index f4ee354e..d0820965 100644 --- a/src/libthread/COPYRIGHT +++ b/src/libthread/COPYRIGHT @@ -45,9 +45,9 @@ Contains parts of an earlier library that has: === -The above notices do *NOT* apply to Linux-sparc64-context.S -or to Linux-sparc64-swapcontext.c. Those are functions from +The above notices do *NOT* apply to Linux-sparc64-context.S +or to sparc64-ucontext.c. Those are functions from the GNU C library and are provided for systems that use the GNU C -library but somehow are missing those functions. They are +library but somehow are missing those functions. They are distributed under the Lesser GPL; see COPYING.SPARC64-CONTEXT. diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c deleted file mode 100644 index c29ddb5e..00000000 --- a/src/libthread/Darwin-x86_64-swapcontext.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) -{ - uintptr *sp; - va_list arg; - -//fprint(2, "makecontext %d\n", argc); - if(argc != 2) - sysfatal("libthread: makecontext misused"); - va_start(arg, argc); - uc->mc.di = va_arg(arg, uint); - uc->mc.si = va_arg(arg, uint); -//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si); - va_end(arg); - - sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size); - /* - * Stack pointer at call instruction (before return address - * gets pushed) must be 16-byte aligned. - */ - if((uintptr)sp%4) - abort(); - while((uintptr)sp%16 != 0) - sp--; - *--sp = 0; // fn's return address - *--sp = (uintptr)fn; // return address of setcontext - uc->mc.sp = (uintptr)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/Linux-arm-swapcontext.c b/src/libthread/Linux-arm-swapcontext.c deleted file mode 100644 index fc0dfdda..00000000 --- a/src/libthread/Linux-arm-swapcontext.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) -{ - int i, *sp; - va_list arg; - - sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4; - va_start(arg, argc); - for(i=0; i<4 && iuc_mcontext.arm_r0)[i] = va_arg(arg, uint); - va_end(arg); - uc->uc_mcontext.arm_sp = (uint)sp; - uc->uc_mcontext.arm_lr = (uint)fn; -} - -int -swapcontext(ucontext_t *oucp, const ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/Linux-sparc64-swapcontext.c b/src/libthread/Linux-sparc64-swapcontext.c deleted file mode 100644 index e4800c19..00000000 --- a/src/libthread/Linux-sparc64-swapcontext.c +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2001 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek . - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include - -#define UC_M_PC 40 -#define UC_M_NPC 48 - -extern int __getcontext (ucontext_t *ucp); -extern int __setcontext (const ucontext_t *ucp, int restoremask); - -int -swapcontext (ucontext_t *oucp, const ucontext_t *ucp) -{ - extern void __swapcontext_ret (void); - /* Save the current machine context to oucp. */ - __getcontext (oucp); - /* Modify oucp to skip the __setcontext call on reactivation. */ - *(long*)((char*)oucp+UC_M_PC) = (long)__swapcontext_ret; - *(long*)((char*)oucp+UC_M_NPC) = (long)__swapcontext_ret + 4; - /* Restore the machine context in ucp. */ - __setcontext (ucp, 1); - return 0; -} - -asm (" \n\ - .text \n\ - .type __swapcontext_ret, #function \n\ -__swapcontext_ret: \n\ - return %i7 + 8 \n\ - clr %o0 \n\ - .size __swapcontext_ret, .-__swapcontext_ret \n\ - "); diff --git a/src/libthread/NetBSD.c b/src/libthread/NetBSD.c index 31577e87..2b14146b 100644 --- a/src/libthread/NetBSD.c +++ b/src/libthread/NetBSD.c @@ -435,28 +435,3 @@ _threadpexit(void) { _exit(0); } - -#ifdef __arm__ -void -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) -{ - int i, *sp; - va_list arg; - - sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4; - va_start(arg, argc); - for(i=0; i<4 && iuc_mcontext.gregs[i] = va_arg(arg, uint); - va_end(arg); - uc->uc_mcontext.gregs[13] = (uint)sp; - uc->uc_mcontext.gregs[14] = (uint)fn; -} - -int -swapcontext(ucontext_t *oucp, const ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} -#endif diff --git a/src/libthread/OpenBSD-386.c b/src/libthread/OpenBSD-386.c deleted file mode 100644 index 89bfedcd..00000000 --- a/src/libthread/OpenBSD-386.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - int *sp; - - sp = (int*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/4; - sp -= argc; - memmove(sp, &argc+1, argc*sizeof(int)); - *--sp = 0; /* return address */ - ucp->uc_mcontext.mc_eip = (long)func; - ucp->uc_mcontext.mc_esp = (int)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/OpenBSD-power.c b/src/libthread/OpenBSD-power.c deleted file mode 100644 index eab711f2..00000000 --- a/src/libthread/OpenBSD-power.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) -{ - ulong *sp, *tos; - va_list arg; - - tos = (ulong*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(ulong); - sp = (ulong*)((ulong)(tos-16) & ~15); - ucp->mc.pc = (long)func; - ucp->mc.sp = (long)sp; - va_start(arg, argc); - ucp->mc.r3 = va_arg(arg, long); - va_end(arg); -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/OpenBSD-x86_64.c b/src/libthread/OpenBSD-x86_64.c deleted file mode 100644 index 27931456..00000000 --- a/src/libthread/OpenBSD-x86_64.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "threadimpl.h" - -void -makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) -{ - uintptr *sp; - va_list arg; - -//fprint(2, "makecontext %d\n", argc); - if(argc != 2) - sysfatal("libthread: makecontext misused"); - va_start(arg, argc); - uc->mc.di = va_arg(arg, uint); - uc->mc.si = va_arg(arg, uint); -//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si); - va_end(arg); - - sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size); - *--sp = 0; // fn's return address - *--sp = (uintptr)fn; // return address of setcontext - uc->mc.sp = (uintptr)sp; -} - -int -swapcontext(ucontext_t *oucp, ucontext_t *ucp) -{ - if(getcontext(oucp) == 0) - setcontext(ucp); - return 0; -} diff --git a/src/libthread/arm-ucontext.c b/src/libthread/arm-ucontext.c new file mode 100644 index 00000000..512ca973 --- /dev/null +++ b/src/libthread/arm-ucontext.c @@ -0,0 +1,24 @@ +#include "threadimpl.h" + +void +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) +{ + int i, *sp; + va_list arg; + + sp = USPALIGN(uc, 4); + va_start(arg, argc); + for(i=0; i<4 && iuc_mcontext.arm_r0)[i] = va_arg(arg, uint); + va_end(arg); + uc->uc_mcontext.arm_sp = (uint)sp; + uc->uc_mcontext.arm_lr = (uint)fn; +} + +int +swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +{ + if(getcontext(oucp) == 0) + setcontext(ucp); + return 0; +} diff --git a/src/libthread/mkfile b/src/libthread/mkfile index a083fd01..45b78039 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -37,8 +37,8 @@ OpenBSD-%-asm.$O: OpenBSD-%-asm.S Linux-sparc64-context.$O: Linux-sparc64-context.S $CC -m64 -mcpu=v9 $CFLAGS Linux-sparc64-context.S -Linux-sparc64-swapcontext.$O: Linux-sparc64-swapcontext.c - $CC -m64 -mcpu=v9 $CFLAGS Linux-sparc64-swapcontext.c +sparc64-ucontext.$O: sparc64-ucontext.c + $CC -m64 -mcpu=v9 $CFLAGS sparc64-ucontext.c test:V: tprimes tspawn primes 1 10007 >p1.txt diff --git a/src/libthread/power-ucontext.c b/src/libthread/power-ucontext.c new file mode 100644 index 00000000..32a8e931 --- /dev/null +++ b/src/libthread/power-ucontext.c @@ -0,0 +1,26 @@ +#include "threadimpl.h" + +void +makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) +{ + ulong *sp, *tos; + va_list arg; + + if(argc != 2) + sysfatal("libthread: makecontext misused"); + sp = USPALIGN(ucp, 16); + ucp->mc.pc = (long)func; + ucp->mc.sp = (long)sp; + va_start(arg, argc); + ucp->mc.r3 = va_arg(arg, long); + ucp->mc.r4 = va_arg(arg, long); + va_end(arg); +} + +int +swapcontext(ucontext_t *oucp, ucontext_t *ucp) +{ + if(getcontext(oucp) == 0) + setcontext(ucp); + return 0; +} diff --git a/src/libthread/sparc64-ucontext.c b/src/libthread/sparc64-ucontext.c new file mode 100644 index 00000000..e4800c19 --- /dev/null +++ b/src/libthread/sparc64-ucontext.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define UC_M_PC 40 +#define UC_M_NPC 48 + +extern int __getcontext (ucontext_t *ucp); +extern int __setcontext (const ucontext_t *ucp, int restoremask); + +int +swapcontext (ucontext_t *oucp, const ucontext_t *ucp) +{ + extern void __swapcontext_ret (void); + /* Save the current machine context to oucp. */ + __getcontext (oucp); + /* Modify oucp to skip the __setcontext call on reactivation. */ + *(long*)((char*)oucp+UC_M_PC) = (long)__swapcontext_ret; + *(long*)((char*)oucp+UC_M_NPC) = (long)__swapcontext_ret + 4; + /* Restore the machine context in ucp. */ + __setcontext (ucp, 1); + return 0; +} + +asm (" \n\ + .text \n\ + .type __swapcontext_ret, #function \n\ +__swapcontext_ret: \n\ + return %i7 + 8 \n\ + clr %o0 \n\ + .size __swapcontext_ret, .-__swapcontext_ret \n\ + "); diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index 9a7301a8..8a65d0f6 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -7,24 +7,37 @@ NetBSD) echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; OpenBSD) - echo ${SYSNAME}-${OBJTYPE}-asm.o ${SYSNAME}-${OBJTYPE}.o pthread.o stkmmap.o + echo ${SYSNAME}-${OBJTYPE}-asm.o pthread.o stkmmap.o ;; *) echo pthread.o stkmalloc.o esac +# Various libc don't supply swapcontext, makecontext, so we do. case "$OBJTYPE-$SYSNAME" in -sparc64-Linux) - # Debian glibc doesn't supply swapcontext, makecontext - # so we supply our own copy from the latest glibc. - echo Linux-sparc64-context.o Linux-sparc64-swapcontext.o +386-OpenBSD) + echo 386-ucontext.o ;; arm-Linux) - # ARM doesn't supply them either. - echo Linux-arm-context.o Linux-arm-swapcontext.o + echo arm-ucontext.o + echo Linux-arm-context.o # setcontext, getcontext + ;; +arm-NetBSD) + echo arm-ucontext.o + ;; +power-OpenBSD) + echo power-ucontext.o + ;; +sparc64-Linux) + echo sparc64-ucontext.o + echo Linux-sparc64-swapcontext.o # setcontext, getcontext ;; x86_64-Darwin) - echo Darwin-x86_64-asm.o Darwin-x86_64-swapcontext.o + echo x86_64-ucontext.o + echo Darwin-x86_64-asm.o # setcontext, getcontext + ;; +x86_64-OpenBSD) + echo x86_64-ucontext.o ;; esac diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h index 5b6d74cc..cceb1b8e 100644 --- a/src/libthread/threadimpl.h +++ b/src/libthread/threadimpl.h @@ -188,3 +188,6 @@ extern void _threadpexit(void); extern void _threaddaemonize(void); extern void *_threadstkalloc(int); extern void _threadstkfree(void*, int); + +#define USPALIGN(ucp, align) \ + (void*)((((uintptr)(ucp)->uc_stack.ss_sp+(ucp)->uc_stack.ss_size)-(align))&~((align)-1)) diff --git a/src/libthread/x86_64-ucontext.c b/src/libthread/x86_64-ucontext.c new file mode 100644 index 00000000..5d1aaefc --- /dev/null +++ b/src/libthread/x86_64-ucontext.c @@ -0,0 +1,28 @@ +#include "threadimpl.h" + +void +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) +{ + uintptr *sp; + va_list arg; + + if(argc != 2) + sysfatal("libthread: makecontext misused"); + va_start(arg, argc); + uc->mc.di = va_arg(arg, uint); + uc->mc.si = va_arg(arg, uint); + va_end(arg); + + sp = USPALIGN(uc, 16); + *--sp = 0; // fn's return address + *--sp = (uintptr)fn; // return address of setcontext + uc->mc.sp = (uintptr)sp; +} + +int +swapcontext(ucontext_t *oucp, ucontext_t *ucp) +{ + if(getcontext(oucp) == 0) + setcontext(ucp); + return 0; +} -- cgit v1.2.3 From 37e7d24c0cb9fd2d18ab332980c31cf470454d93 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 22:52:04 -0500 Subject: libthread: rm OpenBSD tas implementations OpenBSD is using pthreads now, so no need for tas. --- src/libthread/OpenBSD-386-asm.s | 9 +-------- src/libthread/OpenBSD-power-asm.S | 15 --------------- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'src') diff --git a/src/libthread/OpenBSD-386-asm.s b/src/libthread/OpenBSD-386-asm.s index 42169853..ed18d2f0 100644 --- a/src/libthread/OpenBSD-386-asm.s +++ b/src/libthread/OpenBSD-386-asm.s @@ -1,10 +1,3 @@ -.globl _tas -_tas: - movl $0xCAFEBABE, %eax - movl 4(%esp), %ecx - xchgl %eax, 0(%ecx) - ret - .globl getmcontext getmcontext: movl 4(%esp), %eax @@ -17,7 +10,7 @@ getmcontext: movl %esi, 24(%eax) movl %ebp, 28(%eax) movl %ebx, 36(%eax) - movl %edx, 40(%eax) + movl %edx, 40(%eax) movl %ecx, 44(%eax) movl $1, 48(%eax) /* %eax */ diff --git a/src/libthread/OpenBSD-power-asm.S b/src/libthread/OpenBSD-power-asm.S index 03b46e7b..36035eb5 100644 --- a/src/libthread/OpenBSD-power-asm.S +++ b/src/libthread/OpenBSD-power-asm.S @@ -1,18 +1,3 @@ -ENTRY(_tas) - li %r0, 0 - mr %r4, %r3 - lis %r5, 0xcafe - ori %r5, %r5, 0xbabe -1: - lwarx %r3, %r0, %r4 - cmpwi %r3, 0 - bne 2f - stwcx. %r5, %r0, %r4 - bne- 1b -2: - sync - blr - ENTRY(_getmcontext) /* xxx: instruction scheduling */ mflr %r0 mfcr %r5 -- cgit v1.2.3 From 4698bde2367f971fed3924f2dee736e0dfe37bb9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 23:00:26 -0500 Subject: libthread: clean up sysofiles.sh a bit more --- src/libthread/sysofiles.sh | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh index 8a65d0f6..20811cdf 100644 --- a/src/libthread/sysofiles.sh +++ b/src/libthread/sysofiles.sh @@ -7,37 +7,22 @@ NetBSD) echo ${SYSNAME}-${OBJTYPE}-asm.o $SYSNAME.o stkmalloc.o ;; OpenBSD) - echo ${SYSNAME}-${OBJTYPE}-asm.o pthread.o stkmmap.o + echo pthread.o stkmmap.o ;; *) echo pthread.o stkmalloc.o esac # Various libc don't supply swapcontext, makecontext, so we do. -case "$OBJTYPE-$SYSNAME" in -386-OpenBSD) - echo 386-ucontext.o - ;; -arm-Linux) - echo arm-ucontext.o - echo Linux-arm-context.o # setcontext, getcontext - ;; -arm-NetBSD) - echo arm-ucontext.o - ;; -power-OpenBSD) - echo power-ucontext.o - ;; -sparc64-Linux) - echo sparc64-ucontext.o - echo Linux-sparc64-swapcontext.o # setcontext, getcontext - ;; -x86_64-Darwin) - echo x86_64-ucontext.o - echo Darwin-x86_64-asm.o # setcontext, getcontext - ;; -x86_64-OpenBSD) - echo x86_64-ucontext.o +case "$SYSNAME-$OBJTYPE" in +Darwin-x86_64 | Linux-arm | Linux-sparc64 | NetBSD-arm | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64) + echo $OBJTYPE-ucontext.o ;; esac +# A few libc don't supply setcontext, getcontext, so we do. +case "$SYSNAME-$OBJTYPE" in +Darwin-x86_64 | Linux-arm | Linux-sparc64 | OpenBSD-386 | OpenBSD-power | OpenBSD-x86_64) + echo $SYSNAME-$OBJTYPE-asm.o + ;; +esac -- cgit v1.2.3 From f6c9f7b14c9dce53fff6020200b28c4e25621e87 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 19 Jan 2020 23:04:03 -0500 Subject: libthread: fix test deps, cleanup in mkfile --- src/libthread/mkfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libthread/mkfile b/src/libthread/mkfile index 45b78039..8a77a316 100644 --- a/src/libthread/mkfile +++ b/src/libthread/mkfile @@ -24,6 +24,8 @@ tspawn: test/tspawn.$O tspawnloop: test/tspawnloop.$O 9l -o $target test/$target.$O +tprimes tspawn tspawnloop: $PLAN9/lib/$LIB + %.$O: %.c $CC -o $target $CFLAGS -I. $stem.c @@ -50,4 +52,5 @@ test:V: tprimes tspawn echo tspawn should take 3 seconds, not 6 $PLAN9/bin/time ./tspawn sleep 3 >/dev/null -CLEANFILES=p1.txt p2.txt tp1.txt tp2.txt test/*.$O +CLEANFILES=p1.txt p2.txt tp1.txt tp2.txt test/*.$O tprimes tspawn + -- cgit v1.2.3 From 93e2e820a5551ba3d0a1e0f0fbd4c5eb65e18ce6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 24 Jan 2020 13:08:36 -0500 Subject: acme: report close failure in Put, this time for sure Missed in 0b349f6f that Bterm is not closing fd. --- src/cmd/acme/exec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c index 1d50f92f..be7936ae 100644 --- a/src/cmd/acme/exec.c +++ b/src/cmd/acme/exec.c @@ -699,7 +699,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) Rune *r; Biobuf *b; char *s, *name; - int i, fd, q, ret; + int i, fd, q, ret, retc; Dir *d, *d1; Window *w; int isapp; @@ -763,9 +763,10 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) goto Rescue2; } ret = Bterm(b); + retc = close(fd); free(b); b = nil; - if(ret < 0) { + if(ret < 0 || retc < 0) { warning(nil, "can't write file %s: %r\n", name); goto Rescue2; // flush or close failed } @@ -785,10 +786,9 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) // in case we don't have read permission. // (The create above worked, so we probably // still have write permission.) - close(fd); fd = open(name, OWRITE); - d1 = dirfstat(fd); + close(fd); if(d1 != nil){ free(d); d = d1; @@ -821,11 +821,11 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname) if(b != nil) { Bterm(b); free(b); + close(fd); } free(h); fbuffree(s); fbuffree(r); - close(fd); /* fall through */ Rescue1: -- cgit v1.2.3 From 4197af4122bc06cf4062ca2d1d5bc8f973e37cf1 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 24 Jan 2020 13:09:55 -0500 Subject: libthread: comment stack border a bit more --- src/libthread/thread.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libthread/thread.c b/src/libthread/thread.c index 2e654863..f657b5b2 100644 --- a/src/libthread/thread.c +++ b/src/libthread/thread.c @@ -136,10 +136,16 @@ threadalloc(void (*fn)(void*), void *arg, uint stack) sysfatal("threadalloc getcontext: %r"); //print("makecontext sp=%p t=%p startfn=%p\n", (char*)t->stk+t->stksize, t, t->startfn); - /* call makecontext to do the real work. */ - /* leave a few words open on both ends */ - t->context.uc.uc_stack.ss_sp = (void*)(t->stk+8); - t->context.uc.uc_stack.ss_size = t->stksize-64; + /* + * Call makecontext to do the real work. + * To avoid various mistakes on other system software, + * debuggers, and so on, don't get too close to both + * ends of the stack. Just staying away is much easier + * than debugging everything (outside our control) + * that has off-by-one errors. + */ + t->context.uc.uc_stack.ss_sp = (void*)(t->stk+64); + t->context.uc.uc_stack.ss_size = t->stksize-2*64; #if defined(__sun__) && !defined(__MAKECONTEXT_V2_SOURCE) /* sigh */ /* can avoid this with __MAKECONTEXT_V2_SOURCE but only on SunOS 5.9 */ t->context.uc.uc_stack.ss_sp = -- cgit v1.2.3 From f66f0a587b48337388296c8f1820f9b3dbfd0085 Mon Sep 17 00:00:00 2001 From: Martin Palma Date: Mon, 3 Feb 2020 20:59:58 +0100 Subject: devdraw: fix `cmd-r` to toggle retina vs. non-retina mode on macOS (#361) and not unexpectedly quitting an application. Fixes #360 --- src/cmd/devdraw/mac-screen.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cmd/devdraw/mac-screen.m b/src/cmd/devdraw/mac-screen.m index dedbfb84..c6e58341 100644 --- a/src/cmd/devdraw/mac-screen.m +++ b/src/cmd/devdraw/mac-screen.m @@ -510,7 +510,7 @@ void rpc_resizeimg(Client *c) { DrawView *view = (__bridge DrawView*)c->view; - dispatch_sync(dispatch_get_main_queue(), ^(void){ + dispatch_async(dispatch_get_main_queue(), ^(void){ [view resizeimg]; }); } -- cgit v1.2.3 From 0237dec768a4ee36ae9e18ce8566d2c999d78410 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Tue, 11 Feb 2020 09:18:57 +0000 Subject: libthread: fix ARM build by renaming file Fixes #363 Change-Id: Ic8ad5ccce3935fdf00732d78d3024b535db90447 --- src/libthread/Linux-arm-asm.s | 41 +++++++++++++++++++++++++++++++++++++++ src/libthread/Linux-arm-context.s | 41 --------------------------------------- 2 files changed, 41 insertions(+), 41 deletions(-) create mode 100644 src/libthread/Linux-arm-asm.s delete mode 100644 src/libthread/Linux-arm-context.s (limited to 'src') diff --git a/src/libthread/Linux-arm-asm.s b/src/libthread/Linux-arm-asm.s new file mode 100644 index 00000000..9bd54f8a --- /dev/null +++ b/src/libthread/Linux-arm-asm.s @@ -0,0 +1,41 @@ +.globl mygetmcontext +mygetmcontext: + str r1, [r0,#4] + str r2, [r0,#8] + str r3, [r0,#12] + str r4, [r0,#16] + str r5, [r0,#20] + str r6, [r0,#24] + str r7, [r0,#28] + str r8, [r0,#32] + str r9, [r0,#36] + str r10, [r0,#40] + str r11, [r0,#44] + str r12, [r0,#48] + str r13, [r0,#52] + str r14, [r0,#56] + /* store 1 as r0-to-restore */ + mov r1, #1 + str r1, [r0] + /* return 0 */ + mov r0, #0 + mov pc, lr + +.globl mysetmcontext +mysetmcontext: + ldr r1, [r0,#4] + ldr r2, [r0,#8] + ldr r3, [r0,#12] + ldr r4, [r0,#16] + ldr r5, [r0,#20] + ldr r6, [r0,#24] + ldr r7, [r0,#28] + ldr r8, [r0,#32] + ldr r9, [r0,#36] + ldr r10, [r0,#40] + ldr r11, [r0,#44] + ldr r12, [r0,#48] + ldr r13, [r0,#52] + ldr r14, [r0,#56] + ldr r0, [r0] + mov pc, lr diff --git a/src/libthread/Linux-arm-context.s b/src/libthread/Linux-arm-context.s deleted file mode 100644 index 9bd54f8a..00000000 --- a/src/libthread/Linux-arm-context.s +++ /dev/null @@ -1,41 +0,0 @@ -.globl mygetmcontext -mygetmcontext: - str r1, [r0,#4] - str r2, [r0,#8] - str r3, [r0,#12] - str r4, [r0,#16] - str r5, [r0,#20] - str r6, [r0,#24] - str r7, [r0,#28] - str r8, [r0,#32] - str r9, [r0,#36] - str r10, [r0,#40] - str r11, [r0,#44] - str r12, [r0,#48] - str r13, [r0,#52] - str r14, [r0,#56] - /* store 1 as r0-to-restore */ - mov r1, #1 - str r1, [r0] - /* return 0 */ - mov r0, #0 - mov pc, lr - -.globl mysetmcontext -mysetmcontext: - ldr r1, [r0,#4] - ldr r2, [r0,#8] - ldr r3, [r0,#12] - ldr r4, [r0,#16] - ldr r5, [r0,#20] - ldr r6, [r0,#24] - ldr r7, [r0,#28] - ldr r8, [r0,#32] - ldr r9, [r0,#36] - ldr r10, [r0,#40] - ldr r11, [r0,#44] - ldr r12, [r0,#48] - ldr r13, [r0,#52] - ldr r14, [r0,#56] - ldr r0, [r0] - mov pc, lr -- cgit v1.2.3