Redesign interface to machine-dependent code to cleanse lwp.c of

machine-dependencies:
(lwpNewContext): New, factored out of lwpCreate().
(lwpSwitchContext): New, factored out of lwpReschedule().
(LWP_EXTRASTACK, STKALIGN, lwpInitContext, lwpSave, lwpRestore): Move
to arch.c.  Remove for UCONTEXT, else static linkage unless macro or
AIX32.

(lwpReschedule): Skip lwpStatus() when not actually switching.

(LwpStackGrowsDown): New.
(lwpInitSystem): Initialize it.
(lwpStackCheck, lwpStackCheckUsed): Use it.
This commit is contained in:
Markus Armbruster 2005-12-10 19:28:24 +00:00
parent 2218a7a9a1
commit 9e3db08fda
3 changed files with 189 additions and 148 deletions

View file

@ -32,40 +32,81 @@
* Steve McClure, 1994-2000 * Steve McClure, 1994-2000
*/ */
#include <stdlib.h>
#include "lwp.h" #include "lwp.h"
#include "lwpint.h" #include "lwpint.h"
#if defined(_EMPTH_LWP) #if defined(_EMPTH_LWP)
/* /*
* Implement machine-dependent functions lwpInitContext(), lwpSave(), * Implement machine-dependent functions lwpNewContext(),
* lwpRestore(). * 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(), * If lwpSave() and lwpRestore() are #def'd to setjmp() and longjmp(),
* then lwpInitContext() needs to set up the jmp_buf for a longjmp(), * then lwpInitContext() needs to set up the jmp_buf for a longjmp(),
* similar to setjmp(). To figure that out for another machine, check * similar to setjmp(). To figure that out for another machine, check
* their source or reverse engineer. * their source or reverse engineer.
*/ */
#if defined(hpc)
#if defined UCONTEXT #define STKALIGN 64
/*
* 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)
static struct lwpProc *tempcontext; static struct lwpProc *tempcontext;
static struct lwpProc *initcontext = NULL; static struct lwpProc *initcontext = NULL;
@ -87,7 +128,7 @@ startcontext(void)
lwpEntryPoint(); lwpEntryPoint();
} }
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
struct lwpProc holder; struct lwpProc holder;
@ -115,7 +156,7 @@ lwpInitContext(struct lwpProc *newp, void *sp)
} }
} }
int static int
lwpSave(jmp_buf jb) lwpSave(jmp_buf jb)
{ {
int endpoint; int endpoint;
@ -136,13 +177,15 @@ lwpSave(jmp_buf jb)
#elif defined(hpux) #elif defined(hpux)
void #define STKALIGN 64
static void
lwpInitContext(volatile struct lwpProc *volatile newp, void *sp) lwpInitContext(volatile struct lwpProc *volatile newp, void *sp)
{ {
static jmp_buf *cpp; static jmp_buf *cpp;
if (!lwpSave(LwpCurrent->context)) { if (!lwpSave(LwpCurrent->context)) {
cpp = (jmp_buf *) & newp->context; cpp = (jmp_buf *)&newp->context;
asm volatile ("ldw %0, %%sp"::"o" (sp)); asm volatile ("ldw %0, %%sp"::"o" (sp));
if (!lwpSave(*cpp)) if (!lwpSave(*cpp))
lwpRestore(LwpCurrent->context); lwpRestore(LwpCurrent->context);
@ -150,7 +193,7 @@ lwpInitContext(volatile struct lwpProc *volatile newp, void *sp)
} }
} }
int static int
lwpSave(jmp_buf jb) lwpSave(jmp_buf jb)
{ {
/* save stack pointer and return program counter */ /* save stack pointer and return program counter */
@ -185,7 +228,7 @@ lwpSave(jmp_buf jb)
asm(".LABEL _comefrom_"); asm(".LABEL _comefrom_");
} }
void static void
lwpRestore(jmp_buf jb) lwpRestore(jmp_buf jb)
{ {
/* restore stack pointer and program counter */ /* restore stack pointer and program counter */
@ -221,7 +264,7 @@ lwpRestore(jmp_buf jb)
#elif defined(FBSD) #elif defined(FBSD)
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
setjmp(newp->context); setjmp(newp->context);
@ -232,7 +275,7 @@ lwpInitContext(struct lwpProc *newp, void *sp)
#elif defined(__linux__) #elif defined(__linux__)
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
#if defined(__GLIBC__) && (__GLIBC__ >= 2) #if defined(__GLIBC__) && (__GLIBC__ >= 2)
@ -253,7 +296,7 @@ lwpInitContext(struct lwpProc *newp, void *sp)
#elif defined(SUN3) #elif defined(SUN3)
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
newp->context[2] = (int)sp; newp->context[2] = (int)sp;
@ -262,7 +305,7 @@ lwpInitContext(struct lwpProc *newp, void *sp)
#elif defined(SUN4) #elif defined(SUN4)
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
static jmp_buf *cpp; 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) #elif defined(ALPHA)
#include <c_asm.h> #include <c_asm.h>
void static void
lwpInitContext(struct lwpProc *newp, void *sp) lwpInitContext(struct lwpProc *newp, void *sp)
{ {
extern long *_gp; extern long *_gp;
@ -304,13 +350,13 @@ lwpInitContext(struct lwpProc *newp, void *sp)
newp->context[34] = (long)sp; /* stack pointer */ newp->context[34] = (long)sp; /* stack pointer */
} }
int static int
lwpSave(jmp_buf jb) lwpSave(jmp_buf jb)
{ {
return _setjmp(jb); return _setjmp(jb);
} }
void static void
lwpRestore(jmp_buf jb) lwpRestore(jmp_buf jb)
{ {
/* resume, but get the pv from the jmp_buf */ /* resume, but get the pv from the jmp_buf */
@ -321,7 +367,94 @@ lwpRestore(jmp_buf jb)
} }
#elif defined(AIX32) #elif defined(AIX32)
#define LWP_EXTRASTACK 12
/* Code is in .s files, as compiler doesn't grok asm */ /* 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 #endif

View file

@ -36,6 +36,7 @@ struct lwpQueue LwpSchedQ[LWP_MAX_PRIO], LwpDeadQ;
struct lwpProc *LwpCurrent = NULL; struct lwpProc *LwpCurrent = NULL;
char **LwpContextPtr; char **LwpContextPtr;
int LwpMaxpri = 0; /* maximum priority so far */ int LwpMaxpri = 0; /* maximum priority so far */
int LwpStackGrowsDown;
static sigset_t oldmask; static sigset_t oldmask;
@ -107,16 +108,14 @@ lwpReschedule(void)
fprintf(stderr, "No processes to run!\n"); fprintf(stderr, "No processes to run!\n");
exit(1); exit(1);
} }
if (LwpCurrent) if (LwpCurrent != nextp) {
lwpStatus(LwpCurrent, "switch out"); struct lwpProc *oldp = LwpCurrent;
/* do context switch */ if (oldp)
i = LwpCurrent && lwpSave(LwpCurrent->context); lwpStatus(oldp, "switch out");
if (LwpCurrent != nextp && !i) {
/* restore previous context */
lwpStatus(nextp, "switch in %d", nextp->pri);
LwpCurrent = nextp; LwpCurrent = nextp;
*LwpContextPtr = LwpCurrent->ud; *LwpContextPtr = nextp->ud;
lwpRestore(LwpCurrent->context); 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) lwpCreate(int priority, void (*entry)(void *), int stacksz, int flags, char *name, char *desc, int argc, char **argv, void *ud)
{ {
struct lwpProc *newp; 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)))) if (!(newp = malloc(sizeof(struct lwpProc))))
return 0; 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->flags = flags;
newp->name = strdup(name); newp->name = strdup(name);
newp->desc = strdup(desc); newp->desc = strdup(desc);
@ -169,61 +154,18 @@ lwpCreate(int priority, void (*entry)(void *), int stacksz, int flags, char *nam
newp->argc = argc; newp->argc = argc;
newp->argv = argv; newp->argv = argv;
newp->ud = ud; newp->ud = ud;
if (growsdown(&x)) { newp->dead = 0;
/*
* 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;
if (LWP_MAX_PRIO <= priority) if (LWP_MAX_PRIO <= priority)
priority = LWP_MAX_PRIO - 1; priority = LWP_MAX_PRIO - 1;
if (LwpMaxpri < (newp->pri = priority)) if (LwpMaxpri < (newp->pri = priority))
LwpMaxpri = priority; LwpMaxpri = priority;
newp->sbtm = s; lwpNewContext(newp, stacksz);
newp->size = size;
newp->dead = 0;
if (flags & LWP_STACKCHECK)
lwpStackCheckInit(newp);
lwpStatus(newp, "creating process structure %p (sbtm %p)", lwpStatus(newp, "creating process structure %p (sbtm %p)",
newp, newp->sbtm); newp, newp->sbtm);
if (flags & LWP_STACKCHECK)
lwpStackCheckInit(newp);
lwpReady(newp); lwpReady(newp);
lwpReady(LwpCurrent); 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(); lwpReschedule();
return newp; return newp;
} }
@ -352,13 +294,14 @@ struct lwpProc *
lwpInitSystem(int pri, char **ctxptr, int flags) lwpInitSystem(int pri, char **ctxptr, int flags)
{ {
struct lwpQueue *q; struct lwpQueue *q;
int i, *stack; int i, *stack, marker;
struct lwpProc *sel; struct lwpProc *sel;
LwpContextPtr = ctxptr; LwpContextPtr = ctxptr;
if (pri < 1) if (pri < 1)
pri = 1; pri = 1;
/* *LwpContextPtr = 0; */ /* *LwpContextPtr = 0; */
LwpStackGrowsDown = growsdown(&marker);
if (!(LwpCurrent = calloc(1, sizeof(struct lwpProc)))) if (!(LwpCurrent = calloc(1, sizeof(struct lwpProc))))
return 0; return 0;
if (!(stack = malloc(64))) if (!(stack = malloc(64)))
@ -410,7 +353,7 @@ lwpStackCheck(struct lwpProc *newp)
int *btm = (int *)(newp->ustack - LWP_REDZONE); int *btm = (int *)(newp->ustack - LWP_REDZONE);
int *top = (int *)(newp->ustack + newp->usize + LWP_REDZONE); int *top = (int *)(newp->ustack + newp->usize + LWP_REDZONE);
int n = LWP_REDZONE / sizeof(int); 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++) ; for (i = 0; i < n && btm[i] == LWP_CHECKMARK; i++) ;
lo_clean = i; lo_clean = i;
@ -418,7 +361,7 @@ lwpStackCheck(struct lwpProc *newp)
for (i = 1; i <= n && top[-i] == LWP_CHECKMARK; i++) ; for (i = 1; i <= n && top[-i] == LWP_CHECKMARK; i++) ;
hi_clean = i - 1; hi_clean = i - 1;
if (growsdown(&marker)) { if (LwpStackGrowsDown) {
overflow = n - lo_clean; overflow = n - lo_clean;
underflow = n - hi_clean; underflow = n - hi_clean;
} else { } else {
@ -445,9 +388,9 @@ lwpStackCheckUsed(struct lwpProc *newp)
int *base = (int *)newp->ustack; int *base = (int *)newp->ustack;
int *lim = (int *)(newp->ustack + newp->usize); int *lim = (int *)(newp->ustack + newp->usize);
int total = (lim + 1 - base) * sizeof(int); 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) ; for (p = base; p < lim && *p == LWP_CHECKMARK; ++p) ;
used = (lim - p) * sizeof(int); used = (lim - p) * sizeof(int);
} else { } else {

View file

@ -73,50 +73,15 @@ struct lwpSem {
char *name; 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 */ #define LWP_REDZONE 1024 /* make this a multiple of 1024 */
/* XXX Note that this assumes sizeof(long) == 4 */ /* XXX Note that this assumes sizeof(long) == 4 */
#define LWP_CHECKMARK 0x5a5a5a5aL #define LWP_CHECKMARK 0x5a5a5a5aL
#ifdef hpux extern int LwpStackGrowsDown;
#define STKALIGN 64
#else
#define STKALIGN sizeof(double)
#endif
/* internal routines */ int lwpNewContext(struct lwpProc *, int);
void lwpSwitchContext(struct lwpProc *, struct lwpProc *);
void lwpAddTail(struct lwpQueue *, struct lwpProc *); void lwpAddTail(struct lwpQueue *, struct lwpProc *);
struct lwpProc *lwpGetFirst(struct lwpQueue *); struct lwpProc *lwpGetFirst(struct lwpQueue *);
void lwpReady(struct lwpProc *); void lwpReady(struct lwpProc *);