1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include "threadimpl.h" 5 6 Pqueue _threadpq; 7 8 static int 9 nextID(void) 10 { 11 static Lock l; 12 static int id; 13 int i; 14 15 lock(&l); 16 i = ++id; 17 unlock(&l); 18 return i; 19 } 20 21 /* 22 * Create and initialize a new Thread structure attached to a given proc. 23 */ 24 static int 25 newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp) 26 { 27 int id; 28 Thread *t; 29 30 if(stacksize < 32) 31 sysfatal("bad stacksize %d", stacksize); 32 t = _threadmalloc(sizeof(Thread), 1); 33 t->stksize = stacksize; 34 t->stk = _threadmalloc(stacksize, 0); 35 memset(t->stk, 0xFE, stacksize); 36 _threadinitstack(t, f, arg); 37 t->grp = grp; 38 if(name) 39 t->cmdname = strdup(name); 40 t->id = nextID(); 41 id = t->id; 42 t->next = (Thread*)~0; 43 t->proc = p; 44 _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->pid, t->id, name); 45 lock(&p->lock); 46 p->nthreads++; 47 if(p->threads.head == nil) 48 p->threads.head = t; 49 else 50 *p->threads.tail = t; 51 p->threads.tail = &t->nextt; 52 t->nextt = nil; 53 t->state = Ready; 54 _threadready(t); 55 unlock(&p->lock); 56 return id; 57 } 58 59 /* 60 * Create a new thread and schedule it to run. 61 * The thread grp is inherited from the currently running thread. 62 */ 63 int 64 threadcreate(void (*f)(void *arg), void *arg, uint stacksize) 65 { 66 return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp()); 67 } 68 69 /* 70 * Create and initialize a new Proc structure with a single Thread 71 * running inside it. Add the Proc to the global process list. 72 */ 73 Proc* 74 _newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, int rforkflag) 75 { 76 Proc *p; 77 78 p = _threadmalloc(sizeof *p, 1); 79 p->pid = -1; 80 p->rforkflag = rforkflag; 81 newthread(p, f, arg, stacksize, name, grp); 82 83 lock(&_threadpq.lock); 84 if(_threadpq.head == nil) 85 _threadpq.head = p; 86 else 87 *_threadpq.tail = p; 88 _threadpq.tail = &p->next; 89 unlock(&_threadpq.lock); 90 return p; 91 } 92 93 int 94 procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag) 95 { 96 Proc *p; 97 int id; 98 99 p = _threadgetproc(); 100 assert(p->newproc == nil); 101 p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag); 102 id = p->newproc->threads.head->id; 103 _sched(); 104 return id; 105 } 106 107 int 108 proccreate(void (*f)(void*), void *arg, uint stacksize) 109 { 110 return procrfork(f, arg, stacksize, 0); 111 } 112 113 void 114 _freeproc(Proc *p) 115 { 116 Thread *t, *nextt; 117 118 for(t = p->threads.head; t; t = nextt){ 119 if(t->cmdname) 120 free(t->cmdname); 121 assert(t->stk != nil); 122 free(t->stk); 123 nextt = t->nextt; 124 free(t); 125 } 126 free(p); 127 } 128 129 void 130 _freethread(Thread *t) 131 { 132 Proc *p; 133 Thread **l; 134 135 p = t->proc; 136 lock(&p->lock); 137 for(l=&p->threads.head; *l; l=&(*l)->nextt){ 138 if(*l == t){ 139 *l = t->nextt; 140 if(*l == nil) 141 p->threads.tail = l; 142 break; 143 } 144 } 145 unlock(&p->lock); 146 if (t->cmdname) 147 free(t->cmdname); 148 assert(t->stk != nil); 149 free(t->stk); 150 free(t); 151 } 152 153