diff --git a/src/lib/lwp/arch.c b/src/lib/lwp/arch.c index 18810b36..8be384d3 100644 --- a/src/lib/lwp/arch.c +++ b/src/lib/lwp/arch.c @@ -32,40 +32,81 @@ * Steve McClure, 1994-2000 */ +#include #include "lwp.h" #include "lwpint.h" #if defined(_EMPTH_LWP) /* - * Implement machine-dependent functions lwpInitContext(), lwpSave(), - * lwpRestore(). - * + * Implement machine-dependent functions lwpNewContext(), + * lwpSwitchContext(). + */ + + +#if defined UCONTEXT + +/* + * Alternate aproach using setcontext and getcontext instead of setjmp + * and longjump. This should work on any SVr4 machine independant of + * architecture. + */ + +int +lwpNewContext(struct lwpProc *newp, int stacksz) +{ + char *s; + int size, redsize; + + /* Make size a multiple of sizeof(long) to keep things aligned */ + stacksz = (stacksz + sizeof(long) - 1) & -sizeof(long); + /* Add a red zone on each side of the stack for LWP_STACKCHECK */ + redsize = newp->flags & LWP_STACKCHECK ? LWP_REDZONE : 0; + size = stacksz + 2 * redsize; + + s = malloc(size); + if (!s) + return -1; + + newp->sbtm = s; + newp->size = size; + newp->ustack = s + redsize; + newp->usize = stacksz; + + if (getcontext(&newp->context) < 0) + return -1; + newp->context.uc_stack.ss_sp = newp->ustack; + newp->context.uc_stack.ss_size = newp->usize; + newp->context.uc_stack.ss_flags = 0; + newp->context.uc_link = NULL; + makecontext(&newp->context, lwpEntryPoint, 0); + return 0; +} + +void +lwpSwitchContext(struct lwpProc *oldp, struct lwpProc *nextp) +{ + if (!oldp) { + setcontext(&nextp->context); + abort(); + } else { + if (swapcontext(&oldp->context, &nextp->context) < 0) + abort(); + } +} + +#else /* !UCONTEXT */ + +/* * If lwpSave() and lwpRestore() are #def'd to setjmp() and longjmp(), * then lwpInitContext() needs to set up the jmp_buf for a longjmp(), * similar to setjmp(). To figure that out for another machine, check * their source or reverse engineer. */ +#if defined(hpc) -#if defined UCONTEXT -/* - * Alternate aproach using setcontext and getcontext instead of setjmp and - * longjump. This should work on any SVr4 machine independant of - * architecture. Unfortunately some changes are still nessesary in lwp.c. - * Tested on IRIX 5.3 - */ - -void -lwpInitContext(struct lwpProc *newp, stack_t *spp) -{ - getcontext(&newp->context); - newp->context.uc_stack = *spp; - newp->context.uc_link = NULL; - makecontext(&newp->context, lwpEntryPoint, 0); -} - -#elif defined(hpc) +#define STKALIGN 64 static struct lwpProc *tempcontext; static struct lwpProc *initcontext = NULL; @@ -87,7 +128,7 @@ startcontext(void) lwpEntryPoint(); } -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { struct lwpProc holder; @@ -115,7 +156,7 @@ lwpInitContext(struct lwpProc *newp, void *sp) } } -int +static int lwpSave(jmp_buf jb) { int endpoint; @@ -136,13 +177,15 @@ lwpSave(jmp_buf jb) #elif defined(hpux) -void +#define STKALIGN 64 + +static void lwpInitContext(volatile struct lwpProc *volatile newp, void *sp) { static jmp_buf *cpp; if (!lwpSave(LwpCurrent->context)) { - cpp = (jmp_buf *) & newp->context; + cpp = (jmp_buf *)&newp->context; asm volatile ("ldw %0, %%sp"::"o" (sp)); if (!lwpSave(*cpp)) lwpRestore(LwpCurrent->context); @@ -150,7 +193,7 @@ lwpInitContext(volatile struct lwpProc *volatile newp, void *sp) } } -int +static int lwpSave(jmp_buf jb) { /* save stack pointer and return program counter */ @@ -185,7 +228,7 @@ lwpSave(jmp_buf jb) asm(".LABEL _comefrom_"); } -void +static void lwpRestore(jmp_buf jb) { /* restore stack pointer and program counter */ @@ -221,7 +264,7 @@ lwpRestore(jmp_buf jb) #elif defined(FBSD) -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { setjmp(newp->context); @@ -232,7 +275,7 @@ lwpInitContext(struct lwpProc *newp, void *sp) #elif defined(__linux__) -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { #if defined(__GLIBC__) && (__GLIBC__ >= 2) @@ -253,7 +296,7 @@ lwpInitContext(struct lwpProc *newp, void *sp) #elif defined(SUN3) -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { newp->context[2] = (int)sp; @@ -262,7 +305,7 @@ lwpInitContext(struct lwpProc *newp, void *sp) #elif defined(SUN4) -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { static jmp_buf *cpp; @@ -287,11 +330,14 @@ lwpInitContext(struct lwpProc *newp, void *sp) } } +#define lwpSave(x) _setjmp(x) +#define lwpRestore(x) _longjmp(x, 1) + #elif defined(ALPHA) #include -void +static void lwpInitContext(struct lwpProc *newp, void *sp) { extern long *_gp; @@ -304,13 +350,13 @@ lwpInitContext(struct lwpProc *newp, void *sp) newp->context[34] = (long)sp; /* stack pointer */ } -int +static int lwpSave(jmp_buf jb) { return _setjmp(jb); } -void +static void lwpRestore(jmp_buf jb) { /* resume, but get the pv from the jmp_buf */ @@ -321,7 +367,94 @@ lwpRestore(jmp_buf jb) } #elif defined(AIX32) + +#define LWP_EXTRASTACK 12 + /* Code is in .s files, as compiler doesn't grok asm */ -#endif +extern int lwpSave(jmp_buf); +extern void lwpRestore(jmp_buf); +extern void lwpInitContext(struct lwpProc *); + +#endif + +#ifndef LWP_EXTRASTACK +#define LWP_EXTRASTACK 0 +#endif +#ifndef STKALIGN +#define STKALIGN sizeof(double) +#endif +#ifndef lwpSave +#define lwpSave(x) setjmp(x) +#endif +#ifndef lwpRestore +#define lwpRestore(x) longjmp(x, 1) +#endif + +int +lwpNewContext(struct lwpProc *newp, int stacksz) +{ + char *s, *sp; + int size, redsize; + + if (CANT_HAPPEN(STKALIGN == 0|| (STKALIGN & (STKALIGN - 1)))) + return -1; /* STKALIGN not power of 2 */ + + /* Make size a multiple of sizeof(long) to keep things aligned */ + stacksz = (stacksz + sizeof(long) - 1) & -sizeof(long); + /* Add a red zone on each side of the stack for LWP_STACKCHECK */ + redsize = newp->flags & LWP_STACKCHECK ? LWP_REDZONE : 0; + size = stacksz + 2 * redsize + LWP_EXTRASTACK + STKALIGN - 1; + + s = malloc(size); + if (!s) + return -1; + + if (LwpStackGrowsDown) { + /* + * Stack layout for stack growing downward: + * ptr block size + * -------------------------------------- + * red zone LWP_REDZONE + * sp -> extra LWP_EXTRASTACK + * ustack -> stack stacksz + * red zone LWP_REDZONE + * waste STKALIGN - 1 - x + * sp is aligned to a multiple of STKALIGN. + */ + sp = s + redsize + stacksz; + sp = (char *)0 + (((sp + STKALIGN - 1) - (char *)0) & -STKALIGN); + newp->ustack = sp - stacksz; + } else { + /* + * Stack layout for stack growing upward: + * ptr block size + * -------------------------------------- + * waste x + * red zone LWP_REDZONE + * sp -> stack stacksz + * ustack -> extra LWP_EXTRASTACK + * red zone LWP_REDZONE + * waste STKALIGN - 1 - x + * sp is aligned to a multiple of STKALIGN. + */ + sp = s + redsize + LWP_EXTRASTACK; + sp = (char *)0 + (((sp + STKALIGN - 1) - (char *)0) & -STKALIGN); + newp->ustack = sp - LWP_EXTRASTACK; + } + newp->sbtm = s; + newp->size = size; + newp->usize = stacksz + LWP_EXTRASTACK; + lwpInitContext(newp, sp); + return 0; +} + +void +lwpSwitchContext(struct lwpProc *oldp, struct lwpProc *nextp) +{ + if (!(oldp && lwpSave(oldp->context))) + lwpRestore(nextp->context); +} + +#endif /* !UCONTEXT */ #endif diff --git a/src/lib/lwp/lwp.c b/src/lib/lwp/lwp.c index 0a802e69..1288a285 100644 --- a/src/lib/lwp/lwp.c +++ b/src/lib/lwp/lwp.c @@ -36,6 +36,7 @@ struct lwpQueue LwpSchedQ[LWP_MAX_PRIO], LwpDeadQ; struct lwpProc *LwpCurrent = NULL; char **LwpContextPtr; int LwpMaxpri = 0; /* maximum priority so far */ +int LwpStackGrowsDown; static sigset_t oldmask; @@ -107,16 +108,14 @@ lwpReschedule(void) fprintf(stderr, "No processes to run!\n"); exit(1); } - if (LwpCurrent) - lwpStatus(LwpCurrent, "switch out"); - /* do context switch */ - i = LwpCurrent && lwpSave(LwpCurrent->context); - if (LwpCurrent != nextp && !i) { - /* restore previous context */ - lwpStatus(nextp, "switch in %d", nextp->pri); + if (LwpCurrent != nextp) { + struct lwpProc *oldp = LwpCurrent; + if (oldp) + lwpStatus(oldp, "switch out"); LwpCurrent = nextp; - *LwpContextPtr = LwpCurrent->ud; - lwpRestore(LwpCurrent->context); + *LwpContextPtr = nextp->ud; + lwpSwitchContext(oldp, nextp); + lwpStatus(nextp, "switch in %d", nextp->pri); } } @@ -145,23 +144,9 @@ struct lwpProc * lwpCreate(int priority, void (*entry)(void *), int stacksz, int flags, char *name, char *desc, int argc, char **argv, void *ud) { struct lwpProc *newp; - char *s, *sp; - int size, redsize, x; -#ifdef UCONTEXT - stack_t usp; -#endif /* UCONTEXT */ - if (CANT_HAPPEN(STKALIGN == 0|| (STKALIGN & (STKALIGN - 1)))) - return NULL; /* STKALIGN not power of 2 */ if (!(newp = malloc(sizeof(struct lwpProc)))) return 0; - /* Make size a multiple of sizeof(long) to keep things aligned */ - stacksz = (stacksz + sizeof(long) - 1) & -sizeof(long); - /* Add a red zone on each side of the stack for LWP_STACKCHECK */ - redsize = flags & LWP_STACKCHECK ? LWP_REDZONE : 0; - size = stacksz + 2 * redsize + LWP_EXTRASTACK + STKALIGN - 1; - if (!(s = malloc(size))) - return 0; newp->flags = flags; newp->name = strdup(name); newp->desc = strdup(desc); @@ -169,61 +154,18 @@ lwpCreate(int priority, void (*entry)(void *), int stacksz, int flags, char *nam newp->argc = argc; newp->argv = argv; newp->ud = ud; - if (growsdown(&x)) { - /* - * Stack layout for stack growing downward: - * ptr block size - * -------------------------------------- - * waste x - * red zone LWP_REDZONE - * sp -> extra LWP_EXTRASTACK - * ustack -> stack stacksz - * red zone LWP_REDZONE - * waste STKALIGN - 1 - x - * sp is aligned to a multiple of STKALIGN. - */ - sp = s + redsize + stacksz; - sp = (char *)0 + (((sp + STKALIGN - 1) - (char *)0) & -STKALIGN); - newp->ustack = sp - stacksz; - } else { - /* - * Stack layout for stack growing upward: - * ptr block size - * -------------------------------------- - * waste x - * red zone LWP_REDZONE - * sp -> stack stacksz - * ustack -> extra LWP_EXTRASTACK - * red zone LWP_REDZONE - * waste STKALIGN - 1 - x - * sp is aligned to a multiple of STKALIGN. - */ - sp = s + redsize + LWP_EXTRASTACK; - sp = (char *)0 + (((sp + STKALIGN - 1) - (char *)0) & -STKALIGN); - newp->ustack = sp - LWP_EXTRASTACK; - } - newp->usize = stacksz + LWP_EXTRASTACK; + newp->dead = 0; if (LWP_MAX_PRIO <= priority) priority = LWP_MAX_PRIO - 1; if (LwpMaxpri < (newp->pri = priority)) LwpMaxpri = priority; - newp->sbtm = s; - newp->size = size; - newp->dead = 0; - if (flags & LWP_STACKCHECK) - lwpStackCheckInit(newp); + lwpNewContext(newp, stacksz); lwpStatus(newp, "creating process structure %p (sbtm %p)", newp, newp->sbtm); + if (flags & LWP_STACKCHECK) + lwpStackCheckInit(newp); lwpReady(newp); lwpReady(LwpCurrent); -#ifdef UCONTEXT - usp.ss_sp = s + redsize; - usp.ss_size = stacksz; - usp.ss_flags = 0; - lwpInitContext(newp, &usp); /* architecture-dependent: from arch.c */ -#else /* UCONTEXT */ - lwpInitContext(newp, sp); /* architecture-dependent: from arch.c */ -#endif /* UCONTEXT */ lwpReschedule(); return newp; } @@ -352,13 +294,14 @@ struct lwpProc * lwpInitSystem(int pri, char **ctxptr, int flags) { struct lwpQueue *q; - int i, *stack; + int i, *stack, marker; struct lwpProc *sel; LwpContextPtr = ctxptr; if (pri < 1) pri = 1; /* *LwpContextPtr = 0; */ + LwpStackGrowsDown = growsdown(&marker); if (!(LwpCurrent = calloc(1, sizeof(struct lwpProc)))) return 0; if (!(stack = malloc(64))) @@ -410,7 +353,7 @@ lwpStackCheck(struct lwpProc *newp) int *btm = (int *)(newp->ustack - LWP_REDZONE); int *top = (int *)(newp->ustack + newp->usize + LWP_REDZONE); int n = LWP_REDZONE / sizeof(int); - int i, lo_clean, hi_clean, marker, overflow, underflow; + int i, lo_clean, hi_clean, overflow, underflow; for (i = 0; i < n && btm[i] == LWP_CHECKMARK; i++) ; lo_clean = i; @@ -418,7 +361,7 @@ lwpStackCheck(struct lwpProc *newp) for (i = 1; i <= n && top[-i] == LWP_CHECKMARK; i++) ; hi_clean = i - 1; - if (growsdown(&marker)) { + if (LwpStackGrowsDown) { overflow = n - lo_clean; underflow = n - hi_clean; } else { @@ -445,9 +388,9 @@ lwpStackCheckUsed(struct lwpProc *newp) int *base = (int *)newp->ustack; int *lim = (int *)(newp->ustack + newp->usize); int total = (lim + 1 - base) * sizeof(int); - int marker, used, *p; + int used, *p; - if (growsdown(&marker)) { + if (LwpStackGrowsDown) { for (p = base; p < lim && *p == LWP_CHECKMARK; ++p) ; used = (lim - p) * sizeof(int); } else { diff --git a/src/lib/lwp/lwpint.h b/src/lib/lwp/lwpint.h index 3786699f..5991f211 100644 --- a/src/lib/lwp/lwpint.h +++ b/src/lib/lwp/lwpint.h @@ -73,50 +73,15 @@ struct lwpSem { char *name; }; -#ifdef UCONTEXT -void lwpInitContext(struct lwpProc *, stack_t *); -#define lwpSave(x) getcontext(&(x)) -#define lwpRestore(x) setcontext(&(x)) -#else /* !UCONTEXT */ -#if defined(hpux) && !defined(hpc) -void lwpInitContext(volatile struct lwpProc * volatile, void *); -#else -void lwpInitContext(struct lwpProc *, void *); -#endif -#if defined(hpc) -int lwpSave(jmp_buf); -#define lwpRestore(x) longjmp(x, 1) -#elif defined(hpux) || defined(AIX32) || defined(ALPHA) -int lwpSave(jmp_buf); -void lwpRestore(jmp_buf); -#elif defined(SUN4) -#define lwpSave(x) _setjmp(x) -#define lwpRestore(x) _longjmp(x, 1) -#else -#define lwpSave(x) setjmp(x) -#define lwpRestore(x) longjmp(x, 1) -#endif -#endif /* !UCONTEXT */ - -#ifdef AIX32 -/* AIX needs 12 extra bytes above the stack; we add it here */ -#define LWP_EXTRASTACK 3*sizeof(long) -#else -#define LWP_EXTRASTACK 0 -#endif - #define LWP_REDZONE 1024 /* make this a multiple of 1024 */ /* XXX Note that this assumes sizeof(long) == 4 */ #define LWP_CHECKMARK 0x5a5a5a5aL -#ifdef hpux -#define STKALIGN 64 -#else -#define STKALIGN sizeof(double) -#endif +extern int LwpStackGrowsDown; -/* internal routines */ +int lwpNewContext(struct lwpProc *, int); +void lwpSwitchContext(struct lwpProc *, struct lwpProc *); void lwpAddTail(struct lwpQueue *, struct lwpProc *); struct lwpProc *lwpGetFirst(struct lwpQueue *); void lwpReady(struct lwpProc *);