From 5c2f7646e1deabf4b4a95d2b5e60fc24a3cfda20 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 14 Feb 2008 23:47:27 +0100 Subject: [PATCH] Fix LWP's stack initialization for -s With -s, LWP initializes thread stacks to track stack use. It did that after makecontext(), with disastrous results on systems where makecontext() writes something to the stack that swapcontext() expects to find there. Makes FreeBSD 6.2 crash in swapcontext(). Factor stack allocation out of lwpNewContext() into lwpNewStack(). Move call of lwpStackCheckInit() into lwpNewStack(). --- src/lib/lwp/arch.c | 26 +++----------------------- src/lib/lwp/lwp.c | 32 +++++++++++++++++++++++++++++--- src/lib/lwp/lwpint.h | 2 +- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/lib/lwp/arch.c b/src/lib/lwp/arch.c index 7022eb29..f4107b43 100644 --- a/src/lib/lwp/arch.c +++ b/src/lib/lwp/arch.c @@ -47,36 +47,16 @@ */ int -lwpNewContext(struct lwpProc *newp, int stacksz) +lwpNewContext(struct lwpProc *newp) { - 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) + if (getcontext(&newp->context) < 0) return -1; - - newp->sbtm = s; - newp->size = size; - newp->ustack = s + redsize; - newp->usize = stacksz; - - if (getcontext(&newp->context) < 0) { - free(s); - return -1; - } #ifdef MAKECONTEXT_SP_HIGH /* * Known systems that are broken that way: Solaris prior to 10, * IRIX. */ - newp->context.uc_stack.ss_sp = newp->ustack + stacksz - 8; + newp->context.uc_stack.ss_sp = newp->ustack + newp->usize - 8; #else newp->context.uc_stack.ss_sp = newp->ustack; #endif diff --git a/src/lib/lwp/lwp.c b/src/lib/lwp/lwp.c index 01c3384c..85a2636d 100644 --- a/src/lib/lwp/lwp.c +++ b/src/lib/lwp/lwp.c @@ -127,6 +127,32 @@ lwpEntryPoint(void) lwpExit(); } +static int +lwpNewStack(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 (newp->flags & LWP_STACKCHECK) + lwpStackCheckInit(newp); + return 0; +} + /* * lwpCreate -- create a process. */ @@ -147,19 +173,19 @@ lwpCreate(int priority, void (*entry)(void *), int stacksz, newp->dead = 0; newp->runtime = (time_t)-1; newp->fd = -1; + newp->sbtm = NULL; if (LWP_MAX_PRIO <= priority) priority = LWP_MAX_PRIO - 1; if (LwpMaxpri < (newp->pri = priority)) LwpMaxpri = priority; - if (lwpNewContext(newp, stacksz) < 0) { + if (lwpNewStack(newp, stacksz) < 0 || lwpNewContext(newp) < 0) { + free(newp->sbtm); free(newp->name); free(newp); return NULL; } lwpStatus(newp, "creating process structure %p (sbtm %p)", newp, newp->sbtm); - if (flags & LWP_STACKCHECK) - lwpStackCheckInit(newp); lwpReady(newp); lwpReady(LwpCurrent); lwpReschedule(); diff --git a/src/lib/lwp/lwpint.h b/src/lib/lwp/lwpint.h index c887f5e6..23dde314 100644 --- a/src/lib/lwp/lwpint.h +++ b/src/lib/lwp/lwpint.h @@ -73,7 +73,7 @@ struct lwpQueue { extern int LwpStackGrowsDown; -int lwpNewContext(struct lwpProc *, int); +int lwpNewContext(struct lwpProc *); void lwpSwitchContext(struct lwpProc *, struct lwpProc *); void lwpAddTail(struct lwpQueue *, struct lwpProc *); struct lwpProc *lwpGetFirst(struct lwpQueue *);