commit - e0c4896ed41faa71445d9e0b1751aba5157343c9
commit + 0158bceec78c7891a7ef672770bf42e65fd064dd
blob - 0ebbddd0a421a959ff09aa141da9bf9195d19154
blob + 9088ae2e7ea99c973cee2e613e389e9b77d24434
--- man/man3/thread.3
+++ man/man3/thread.3
.B mainstacksize
.B =
.BR 1024 ).
+When using the
+.I pthread
+library,
+.B mainstacksize
+is ignored, as is the stack size argument to
+.BR proccreate :
+the first thread in each proc
+runs on the native system stack.
.PP
.I Threadcreate
creates a new thread in the calling proc, returning a unique integer
blob - 05636dc910fc2b1359ab144421a06531fc1d8313
blob + 204328b8b64255eabf88b36b6a0fe195c0656055
--- src/libthread/test/tspawnloop.c
+++ src/libthread/test/tspawnloop.c
int i, fd[3];
char buf[100], *args[3];
- i = (int)v;
+ i = (int)(uintptr)v;
sprint(buf, "%d", i);
fd[0] = dup(0, -1);
fd[1] = dup(1, -1);
c = threadwaitchan();
for(i=0;; i++){
- proccreate(execproc, (void*)i, 16384);
+ proccreate(execproc, (void*)(uintptr)i, 16384);
w = recvp(c);
if(w == nil)
sysfatal("exec/recvp failed: %r");
blob - cbad185c4a7fa7ad4dd85caf341894514ff56b6a
blob + c84af855ccc2feb77cd9ee0aac87f8d4bfd53af0
--- src/libthread/thread.c
+++ src/libthread/thread.c
static void addthreadinproc(Proc*, _Thread*);
static void delthreadinproc(Proc*, _Thread*);
static void contextswitch(Context *from, Context *to);
+static void procmain(Proc*);
static void procscheduler(Proc*);
static int threadinfo(void*, char*);
if(t == nil)
sysfatal("threadalloc malloc: %r");
memset(t, 0, sizeof *t);
- t->stk = (uchar*)(t+1);
- t->stksize = stack;
t->id = incref(&threadidref);
//print("fn=%p arg=%p\n", fn, arg);
t->startfn = fn;
//print("makecontext sp=%p t=%p startfn=%p\n", (char*)t->stk+t->stksize, t, t->startfn);
/* do a reasonable initialization */
+ if(stack == 0)
+ return t;
+ t->stk = (uchar*)(t+1);
+ t->stksize = stack;
memset(&t->context.uc, 0, sizeof t->context.uc);
sigemptyset(&zero);
sigprocmask(SIG_BLOCK, &zero, &t->context.uc.uc_sigmask);
if(stack < (256<<10))
stack = 256<<10;
+ if(p->nthread == 0)
+ stack = 0; // not using it
t = threadalloc(fn, arg, stack);
t->proc = p;
addthreadinproc(p, t);
p = procalloc();
t = _threadcreate(p, fn, arg, stack);
id = t->id; /* t might be freed after _procstart */
- _procstart(p, procscheduler);
+ _procstart(p, procmain);
return id;
}
needstack(0);
p = proc();
/*print("threadswtch %p\n", p); */
- contextswitch(&p->thread->context, &p->schedcontext);
+ if(p->thread->stk == nil)
+ procscheduler(p);
+ else
+ contextswitch(&p->thread->context, &p->schedcontext);
}
void
}
static void
+procmain(Proc *p)
+{
+ _Thread *t;
+
+ _threadsetproc(p);
+
+ /* take out first thread to run on system stack */
+ t = p->runqueue.head;
+ delthread(&p->runqueue, t);
+ memset(&t->context.uc, 0, sizeof t->context.uc);
+
+ /* run it */
+ p->thread = t;
+ t->startfn(t->startarg);
+ if(p->nthread != 0)
+ threadexits(nil);
+}
+
+static void
procscheduler(Proc *p)
{
_Thread *t;
- setproc(p);
_threaddebug("scheduler enter");
//print("s %p\n", p);
+Top:
lock(&p->lock);
+ t = p->thread;
+ p->thread = nil;
+ if(t->exiting){
+ delthreadinproc(p, t);
+ p->nthread--;
+/*print("nthread %d\n", p->nthread); */
+ free(t);
+ }
+
for(;;){
if((t = p->pinthread) != nil){
while(!onlist(&p->runqueue, t)){
p->nswitch++;
_threaddebug("run %d (%s)", t->id, t->name);
//print("run %p %p %p %p\n", t, *(uintptr*)(t->context.uc.mc.sp), t->context.uc.mc.di, t->context.uc.mc.si);
+ if(t->stk == nil)
+ return;
contextswitch(&p->schedcontext, &t->context);
/*print("back in scheduler\n"); */
- p->thread = nil;
- lock(&p->lock);
- if(t->exiting){
- delthreadinproc(p, t);
- p->nthread--;
-/*print("nthread %d\n", p->nthread); */
- free(t);
- }
+ goto Top;
}
Out:
mainstacksize = 256*1024;
atnotify(threadinfo, 1);
_threadcreate(p, threadmainstart, nil, mainstacksize);
- procscheduler(p);
+ procmain(p);
sysfatal("procscheduler returned in threadmain!");
/* does not return */
return 0;
blob - a8d52704db96a276c602c0fb2e5da3239115cd7c
blob + 437503c68a7751c51aa9045c9b8fceef7003945d
--- src/libthread/threadimpl.h
+++ src/libthread/threadimpl.h
};
#define proc() _threadproc()
-#define setproc(p) _threadsetproc(p)
extern Proc *_threadprocs;
extern Lock _threadprocslock;