Blob


1 #include "threadimpl.h"
3 Pqueue _threadpq;
5 static int nextID(void);
7 /*
8 * Create and initialize a new Thread structure attached to a given proc.
9 */
11 typedef struct Stack Stack;
12 struct Stack {
13 ulong magic;
14 Thread *thr;
15 Stack *next;
16 uchar buf[STKSIZE-12];
17 };
19 static Stack *stkfree;
20 static Lock stklock;
22 void
23 _stackfree(void *v)
24 {
25 Stack *s;
27 s = v;
28 lock(&stklock);
29 s->thr = nil;
30 s->magic = 0;
31 s->next = stkfree;
32 stkfree = s;
33 unlock(&stklock);
34 }
36 static Stack*
37 stackalloc(void)
38 {
39 char *buf;
40 Stack *s;
41 int i;
43 lock(&stklock);
44 while(stkfree == nil){
45 unlock(&stklock);
46 assert(STKSIZE == sizeof(Stack));
47 buf = malloc(STKSIZE+128*STKSIZE);
48 s = (Stack*)(((ulong)buf+STKSIZE)&~(STKSIZE-1));
49 for(i=0; i<128; i++)
50 _stackfree(&s[i]);
51 lock(&stklock);
52 }
53 s = stkfree;
54 stkfree = stkfree->next;
55 unlock(&stklock);
56 s->magic = STKMAGIC;
57 return s;
58 }
60 static int
61 newthread(Proc *p, void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp)
62 {
63 int id;
64 Thread *t;
65 Stack *s;
67 if(stacksize < 32)
68 sysfatal("bad stacksize %d", stacksize);
69 t = _threadmalloc(sizeof(Thread), 1);
70 s = stackalloc();
71 s->thr = t;
72 t->stk = (char*)s;
73 t->stksize = STKSIZE;
74 _threaddebugmemset(s->buf, 0xFE, sizeof s->buf);
75 _threadinitstack(t, f, arg);
76 t->proc = p;
77 t->grp = grp;
78 if(name)
79 t->cmdname = strdup(name);
80 t->id = nextID();
81 id = t->id;
82 t->next = (Thread*)~0;
83 _threaddebug(DBGSCHED, "create thread %d.%d name %s", p->pid, t->id, name);
84 lock(&p->lock);
85 p->nthreads++;
86 if(p->threads.head == nil)
87 p->threads.head = t;
88 else{
89 t->prevt = p->threads.tail;
90 t->prevt->nextt = t;
91 }
92 p->threads.tail = t;
93 t->state = Ready;
94 _threadready(t);
95 unlock(&p->lock);
96 return id;
97 }
99 static int
100 nextID(void)
102 static Lock l;
103 static int id;
104 int i;
106 lock(&l);
107 i = ++id;
108 unlock(&l);
109 return i;
112 int
113 procrfork(void (*f)(void *), void *arg, uint stacksize, int rforkflag)
115 Proc *p;
116 int id;
118 p = _threadgetproc();
119 assert(p->newproc == nil);
120 p->newproc = _newproc(f, arg, stacksize, nil, p->thread->grp, rforkflag);
121 id = p->newproc->threads.head->id;
122 _sched();
123 return id;
126 int
127 proccreate(void (*f)(void*), void *arg, uint stacksize)
129 return procrfork(f, arg, stacksize, 0);
132 void
133 _freeproc(Proc *p)
135 Thread *t, *nextt;
137 for(t = p->threads.head; t; t = nextt){
138 if(t->cmdname)
139 free(t->cmdname);
140 assert(t->stk != nil);
141 _stackfree((Stack*)t->stk);
142 nextt = t->nextt;
143 free(t);
145 free(p);
148 /*
149 * Create a new thread and schedule it to run.
150 * The thread grp is inherited from the currently running thread.
151 */
152 int
153 threadcreate(void (*f)(void *arg), void *arg, uint stacksize)
155 return newthread(_threadgetproc(), f, arg, stacksize, nil, threadgetgrp());
158 /*
159 * Create and initialize a new Proc structure with a single Thread
160 * running inside it. Add the Proc to the global process list.
161 */
162 Proc*
163 _newproc(void (*f)(void *arg), void *arg, uint stacksize, char *name, int grp, int rforkflag)
165 Proc *p;
167 p = _threadmalloc(sizeof *p, 1);
168 p->pid = -1;
169 p->rforkflag = rforkflag;
170 newthread(p, f, arg, stacksize, name, grp);
172 lock(&_threadpq.lock);
173 if(_threadpq.head == nil)
174 _threadpq.head = p;
175 else
176 *_threadpq.tail = p;
177 _threadpq.tail = &p->next;
178 unlock(&_threadpq.lock);
179 return p;