diff options
Diffstat (limited to 'src/libthread/create.c')
-rw-r--r-- | src/libthread/create.c | 227 |
1 files changed, 121 insertions, 106 deletions
diff --git a/src/libthread/create.c b/src/libthread/create.c index 5dee4c48..290c52a8 100644 --- a/src/libthread/create.c +++ b/src/libthread/create.c @@ -1,45 +1,46 @@ #include "threadimpl.h" -Pqueue _threadpq; -int _threadprocs; -int __pthread_nonstandard_stacks; +Pqueue _threadpq; /* list of all procs */ +int _threadnprocs; /* count of procs */ -static int nextID(void); +static int newthreadid(void); +static int newprocid(void); /* * Create and initialize a new Thread structure attached to a given proc. */ -void -_stackfree(void *v) -{ - free(v); -} - -static int -newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp) +int +_newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, + char *name, int grp) { int id; Thread *t; - char *s; - __pthread_nonstandard_stacks = 1; - if(stacksize < 32) - sysfatal("bad stacksize %d", stacksize); t = _threadmalloc(sizeof(Thread), 1); - t->lastfd = -1; - s = _threadmalloc(stacksize, 0); - t->stk = (uchar*)s; - t->stksize = stacksize; - _threaddebugmemset(s, 0xFE, stacksize); - _threadinitstack(t, f, arg); t->proc = p; t->grp = grp; + t->id = id = newthreadid(); if(name) - t->cmdname = strdup(name); - t->id = nextID(); - id = t->id; - t->next = (Thread*)~0; - _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->pid, t->id, name); + t->name = strdup(name); + _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->id, id, name); + + /* + * Allocate and clear stack. + */ + if(stacksize < 1024) + sysfatal("bad stacksize %d", stacksize); + t->stk = _threadmalloc(stacksize, 0); + t->stksize = stacksize; + _threaddebugmemset(t->stk, 0xFE, stacksize); + + /* + * Set up t->context to call f(arg). + */ + _threadinitstack(t, f, arg); + + /* + * Add thread to proc. + */ lock(&p->lock); p->nthreads++; if(p->threads.head == nil) @@ -49,120 +50,134 @@ newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, t->prevt->nextt = t; } p->threads.tail = t; + t->next = (Thread*)~0; + + /* + * Mark thread as ready to run. + */ t->state = Ready; _threadready(t); unlock(&p->lock); + return id; } -static int -nextID(void) -{ - static Lock l; - static int id; - int i; - - lock(&l); - i = ++id; - unlock(&l); - return i; -} - -int -procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag) +/* + * Free a Thread structure. + */ +void +_threadfree(Thread *t) { - Proc *p; - int id; - - p = _threadgetproc(); - assert(p->newproc == nil); - p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag); - id = p->newproc->threads.head->id; - _sched(); - return id; + free(t->stk); + free(t->name); + free(t); } -int -proccreate(void (*f)(void*), void *arg, uint stacksize) +/* + * Create and initialize a new Proc structure with a single Thread + * running inside it. Add the Proc to the global process list. + */ +Proc* +_newproc(void) { Proc *p; - p = _threadgetproc(); - if(p->idle){ - fprint(2, "cannot create procs once there is an idle thread\n"); - werrstr("cannot create procs once there is an idle thread"); - return -1; - } - return procrfork(f, arg, stacksize, 0); + /* + * Allocate. + */ + p = _threadmalloc(sizeof *p, 1); + p->id = newprocid(); + + /* + * Add to list. Record if we're now multiprocess. + */ + lock(&_threadpq.lock); + if(_threadpq.head == nil) + _threadpq.head = p; + else + *_threadpq.tail = p; + _threadpq.tail = &p->next; + if(_threadnprocs == 1) + _threadmultiproc(); + _threadnprocs++; + unlock(&_threadpq.lock); + + return p; } -void -_freeproc(Proc *p) +/* + * Allocate a new thread running f(arg) on a stack of size stacksize. + * Return the thread id. The thread group inherits from the current thread. + */ +int +threadcreate(void (*f)(void*), void *arg, uint stacksize) { - Thread *t, *nextt; - - for(t = p->threads.head; t; t = nextt){ - if(t->cmdname) - free(t->cmdname); - assert(t->stk != nil); - _stackfree(t->stk); - nextt = t->nextt; - free(t); - } - free(p); + return _newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); } /* - * Create a new thread and schedule it to run. - * The thread grp is inherited from the currently running thread. + * Allocate a new idle thread. Only allowed in a single-proc program. */ int -threadcreate(void (*f)(void *arg), void *arg, uint stacksize) +threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize) { - return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); + int id; + + assert(_threadnprocs == 1); + + id = threadcreate(f, arg, stacksize); + _threaddebug(DBGSCHED, "idle is %d", id); + _threadsetidle(id); + return id; } +/* + * Threadcreate, but do it inside a fresh proc. + */ int -threadcreateidle(void (*f)(void *arg), void *arg, uint stacksize) +proccreate(void (*f)(void*), void *arg, uint stacksize) { int id; + Proc *p, *np; - if(_threadprocs!=1){ - fprint(2, "cannot have idle thread in multi-proc program\n"); - werrstr("cannot have idle thread in multi-proc program"); - return -1; - } - id = newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); - _threaddebug(DBGSCHED, "idle is %d", id); - _threadidle(); + p = _threadgetproc(); + np = _newproc(); + p->newproc = np; + p->schedfn = _threadstartproc; + id = _newthread(np, f, arg, stacksize, nil, p->thread->grp); + _sched(); /* call into scheduler to create proc XXX */ return id; } /* - * Create and initialize a new Proc structure with a single Thread - * running inside it. Add the Proc to the global process list. + * Allocate a new thread id. */ -Proc* -_newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, int rforkflag) +static int +newthreadid(void) { - Proc *p; + static Lock l; + static int id; + int i; - p = _threadmalloc(sizeof *p, 1); - p->pid = -1; - p->rforkflag = rforkflag; - newthread(p, f, arg, stacksize, name, grp); + lock(&l); + i = ++id; + unlock(&l); + return i; +} - lock(&_threadpq.lock); - if(_threadpq.head == nil) - _threadpq.head = p; - else - *_threadpq.tail = p; - _threadpq.tail = &p->next; +/* + * Allocate a new proc id. + */ +static int +newprocid(void) +{ + static Lock l; + static int id; + int i; - if(_threadprocs == 1) - _threadmultiproc(); - _threadprocs++; - unlock(&_threadpq.lock); - return p; + lock(&l); + i = ++id; + unlock(&l); + return i; } |