aboutsummaryrefslogtreecommitdiff
path: root/src/libthread/create.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libthread/create.c')
-rw-r--r--src/libthread/create.c227
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;
}