182 lines · 3.2 KB · C
RawDownload
#include "threadimpl.h" #define freePqueue _threadpq; static int nextID(void); /* * Create and initialize a new Thread structure attached to a given proc. */ typedef struct Stack Stack;struct Stack {	ulong magic;	Thread *thr;	Stack *next;	uchar buf[STKSIZE-12];}; static Stack *stkfree;static Lock stklock; void_stackfree(void *v){	Stack *s; 	s = v;	lock(&stklock);	s->thr = nil;	s->magic = 0;	s->next = stkfree;	stkfree = s;	unlock(&stklock);} static Stack*stackalloc(void){	char *buf;	Stack *s;	int i; 	lock(&stklock);	while(stkfree == nil){		unlock(&stklock);		assert(STKSIZE == sizeof(Stack));		buf = malloc(STKSIZE+128*STKSIZE);		s = (Stack*)(((ulong)buf+STKSIZE)&~(STKSIZE-1));		for(i=0; i<128; i++)			_stackfree(&s[i]);		lock(&stklock);	}	s = stkfree;	stkfree = stkfree->next;	unlock(&stklock);	s->magic = STKMAGIC;	return s;} static intnewthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp){	int id;	Thread *t;	Stack *s; 	if(stacksize < 32)		sysfatal("bad stacksize %d", stacksize);	t = _threadmalloc(sizeof(Thread), 1);	s = stackalloc();	s->thr = t;	t->stk = (char*)s;	t->stksize = STKSIZE;	_threaddebugmemset(s->buf, 0xFE, sizeof s->buf);	_threadinitstack(t, f, arg);	t->proc = p;	t->grp = grp;	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);	lock(&p->lock);	p->nthreads++;	if(p->threads.head == nil)		p->threads.head = t;	else{		t->prevt = p->threads.tail;		t->prevt->nextt = t;	}	p->threads.tail = t;	t->state = Ready;	_threadready(t);	unlock(&p->lock);	return id;} static intnextID(void){	static Lock l;	static int id;	int i; 	lock(&l);	i = ++id;	unlock(&l);	return i;}	intprocrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag){	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;} intproccreate(void (*f)(void*), void *arg, uint stacksize){	return procrfork(f, arg, stacksize, 0);} void_freeproc(Proc *p){	Thread *t, *nextt; 	for(t = p->threads.head; t; t = nextt){		if(t->cmdname)			free(t->cmdname);		assert(t->stk != nil);		_stackfree((Stack*)t->stk);		nextt = t->nextt;		free(t);	}	free(p);} /*  * Create a new thread and schedule it to run. * The thread grp is inherited from the currently running thread. */intthreadcreate(void (*f)(void *arg), void *arg, uint stacksize){	return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());} /* * 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 (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, int rforkflag){	Proc *p; 	p = _threadmalloc(sizeof *p, 1);	p->pid = -1;	p->rforkflag = rforkflag;	newthread(p, f, arg, stacksize, name, grp); 	lock(&_threadpq.lock);	if(_threadpq.head == nil)		_threadpq.head = p;	else		*_threadpq.tail = p;	_threadpq.tail = &p->next;	unlock(&_threadpq.lock);	return p;}