xref: /plan9/sys/src/libthread/create.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "threadimpl.h"
5 
6 Pqueue _threadpq;
7 
8 static int
nextID(void)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
newthread(Proc * p,void (* f)(void * arg),void * arg,uint stacksize,char * name,int grp)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
threadcreate(void (* f)(void * arg),void * arg,uint stacksize)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*
_newproc(void (* f)(void * arg),void * arg,uint stacksize,char * name,int grp,int rforkflag)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
procrfork(void (* f)(void *),void * arg,uint stacksize,int rforkflag)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
proccreate(void (* f)(void *),void * arg,uint stacksize)108 proccreate(void (*f)(void*), void *arg, uint stacksize)
109 {
110 	return procrfork(f, arg, stacksize, 0);
111 }
112 
113 void
_freeproc(Proc * p)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
_freethread(Thread * t)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