]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libthread/create.c
add games/blit
[plan9front.git] / sys / src / libthread / create.c
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 }