1*433d6423SLionel Sambuc #include <minix/mthread.h>
2*433d6423SLionel Sambuc #include "global.h"
3*433d6423SLionel Sambuc #include "proto.h"
4*433d6423SLionel Sambuc
5*433d6423SLionel Sambuc static struct __mthread_attr *va_front, *va_rear;
6*433d6423SLionel Sambuc static void mthread_attr_add(mthread_attr_t *a);
7*433d6423SLionel Sambuc static void mthread_attr_remove(mthread_attr_t *a);
8*433d6423SLionel Sambuc static int mthread_attr_valid(mthread_attr_t *a);
9*433d6423SLionel Sambuc
10*433d6423SLionel Sambuc /*===========================================================================*
11*433d6423SLionel Sambuc * mthread_init_valid_attributes *
12*433d6423SLionel Sambuc *===========================================================================*/
mthread_init_valid_attributes(void)13*433d6423SLionel Sambuc void mthread_init_valid_attributes(void)
14*433d6423SLionel Sambuc {
15*433d6423SLionel Sambuc /* Initialize list of valid attributs */
16*433d6423SLionel Sambuc va_front = va_rear = NULL;
17*433d6423SLionel Sambuc }
18*433d6423SLionel Sambuc
19*433d6423SLionel Sambuc
20*433d6423SLionel Sambuc /*===========================================================================*
21*433d6423SLionel Sambuc * mthread_attr_add *
22*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_add(a)23*433d6423SLionel Sambuc static void mthread_attr_add(a)
24*433d6423SLionel Sambuc mthread_attr_t *a;
25*433d6423SLionel Sambuc {
26*433d6423SLionel Sambuc /* Add attribute to list of valid, initialized attributes */
27*433d6423SLionel Sambuc
28*433d6423SLionel Sambuc if (va_front == NULL) { /* Empty list */
29*433d6423SLionel Sambuc va_front = *a;
30*433d6423SLionel Sambuc (*a)->ma_prev = NULL;
31*433d6423SLionel Sambuc } else {
32*433d6423SLionel Sambuc va_rear->ma_next = *a;
33*433d6423SLionel Sambuc (*a)->ma_prev = va_rear;
34*433d6423SLionel Sambuc }
35*433d6423SLionel Sambuc
36*433d6423SLionel Sambuc (*a)->ma_next = NULL;
37*433d6423SLionel Sambuc va_rear = *a;
38*433d6423SLionel Sambuc }
39*433d6423SLionel Sambuc
40*433d6423SLionel Sambuc
41*433d6423SLionel Sambuc /*===========================================================================*
42*433d6423SLionel Sambuc * mthread_attr_destroy *
43*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_destroy(attr)44*433d6423SLionel Sambuc int mthread_attr_destroy(attr)
45*433d6423SLionel Sambuc mthread_attr_t *attr;
46*433d6423SLionel Sambuc {
47*433d6423SLionel Sambuc /* Invalidate attribute and deallocate resources. */
48*433d6423SLionel Sambuc
49*433d6423SLionel Sambuc if (attr == NULL)
50*433d6423SLionel Sambuc return(EINVAL);
51*433d6423SLionel Sambuc
52*433d6423SLionel Sambuc if (!mthread_attr_valid(attr))
53*433d6423SLionel Sambuc return(EINVAL);
54*433d6423SLionel Sambuc
55*433d6423SLionel Sambuc /* Valide attribute; invalidate it */
56*433d6423SLionel Sambuc mthread_attr_remove(attr);
57*433d6423SLionel Sambuc free(*attr);
58*433d6423SLionel Sambuc *attr = NULL;
59*433d6423SLionel Sambuc
60*433d6423SLionel Sambuc return(0);
61*433d6423SLionel Sambuc }
62*433d6423SLionel Sambuc
63*433d6423SLionel Sambuc
64*433d6423SLionel Sambuc /*===========================================================================*
65*433d6423SLionel Sambuc * mthread_attr_init *
66*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_init(attr)67*433d6423SLionel Sambuc int mthread_attr_init(attr)
68*433d6423SLionel Sambuc mthread_attr_t *attr; /* Attribute */
69*433d6423SLionel Sambuc {
70*433d6423SLionel Sambuc /* Initialize the attribute to a known state. */
71*433d6423SLionel Sambuc struct __mthread_attr *a;
72*433d6423SLionel Sambuc
73*433d6423SLionel Sambuc if (attr == NULL)
74*433d6423SLionel Sambuc return(EAGAIN);
75*433d6423SLionel Sambuc else if (mthread_attr_valid(attr))
76*433d6423SLionel Sambuc return(EBUSY);
77*433d6423SLionel Sambuc
78*433d6423SLionel Sambuc if ((a = malloc(sizeof(struct __mthread_attr))) == NULL)
79*433d6423SLionel Sambuc return(-1);
80*433d6423SLionel Sambuc
81*433d6423SLionel Sambuc a->ma_detachstate = MTHREAD_CREATE_JOINABLE;
82*433d6423SLionel Sambuc a->ma_stackaddr = NULL;
83*433d6423SLionel Sambuc a->ma_stacksize = (size_t) 0;
84*433d6423SLionel Sambuc
85*433d6423SLionel Sambuc *attr = (mthread_attr_t) a;
86*433d6423SLionel Sambuc mthread_attr_add(attr); /* Validate attribute: attribute now in use */
87*433d6423SLionel Sambuc
88*433d6423SLionel Sambuc return(0);
89*433d6423SLionel Sambuc }
90*433d6423SLionel Sambuc
91*433d6423SLionel Sambuc /*===========================================================================*
92*433d6423SLionel Sambuc * mthread_attr_getdetachstate *
93*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_getdetachstate(attr,detachstate)94*433d6423SLionel Sambuc int mthread_attr_getdetachstate(attr, detachstate)
95*433d6423SLionel Sambuc mthread_attr_t *attr;
96*433d6423SLionel Sambuc int *detachstate;
97*433d6423SLionel Sambuc {
98*433d6423SLionel Sambuc /* Get detachstate of a thread attribute */
99*433d6423SLionel Sambuc struct __mthread_attr *a;
100*433d6423SLionel Sambuc
101*433d6423SLionel Sambuc if (attr == NULL)
102*433d6423SLionel Sambuc return(EINVAL);
103*433d6423SLionel Sambuc
104*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
105*433d6423SLionel Sambuc if (!mthread_attr_valid(attr))
106*433d6423SLionel Sambuc return(EINVAL);
107*433d6423SLionel Sambuc
108*433d6423SLionel Sambuc *detachstate = a->ma_detachstate;
109*433d6423SLionel Sambuc
110*433d6423SLionel Sambuc return(0);
111*433d6423SLionel Sambuc }
112*433d6423SLionel Sambuc
113*433d6423SLionel Sambuc
114*433d6423SLionel Sambuc /*===========================================================================*
115*433d6423SLionel Sambuc * mthread_attr_setdetachstate *
116*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_setdetachstate(attr,detachstate)117*433d6423SLionel Sambuc int mthread_attr_setdetachstate(attr, detachstate)
118*433d6423SLionel Sambuc mthread_attr_t *attr;
119*433d6423SLionel Sambuc int detachstate;
120*433d6423SLionel Sambuc {
121*433d6423SLionel Sambuc /* Set detachstate of a thread attribute */
122*433d6423SLionel Sambuc struct __mthread_attr *a;
123*433d6423SLionel Sambuc
124*433d6423SLionel Sambuc if (attr == NULL)
125*433d6423SLionel Sambuc return(EINVAL);
126*433d6423SLionel Sambuc
127*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
128*433d6423SLionel Sambuc if (!mthread_attr_valid(attr))
129*433d6423SLionel Sambuc return(EINVAL);
130*433d6423SLionel Sambuc else if(detachstate != MTHREAD_CREATE_JOINABLE &&
131*433d6423SLionel Sambuc detachstate != MTHREAD_CREATE_DETACHED)
132*433d6423SLionel Sambuc return(EINVAL);
133*433d6423SLionel Sambuc
134*433d6423SLionel Sambuc a->ma_detachstate = detachstate;
135*433d6423SLionel Sambuc
136*433d6423SLionel Sambuc return(0);
137*433d6423SLionel Sambuc }
138*433d6423SLionel Sambuc
139*433d6423SLionel Sambuc
140*433d6423SLionel Sambuc /*===========================================================================*
141*433d6423SLionel Sambuc * mthread_attr_getstack *
142*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_getstack(attr,stackaddr,stacksize)143*433d6423SLionel Sambuc int mthread_attr_getstack(attr, stackaddr, stacksize)
144*433d6423SLionel Sambuc mthread_attr_t *attr;
145*433d6423SLionel Sambuc void **stackaddr;
146*433d6423SLionel Sambuc size_t *stacksize;
147*433d6423SLionel Sambuc {
148*433d6423SLionel Sambuc /* Get stack attribute */
149*433d6423SLionel Sambuc struct __mthread_attr *a;
150*433d6423SLionel Sambuc
151*433d6423SLionel Sambuc if (attr == NULL)
152*433d6423SLionel Sambuc return(EINVAL);
153*433d6423SLionel Sambuc
154*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
155*433d6423SLionel Sambuc if (!mthread_attr_valid(attr))
156*433d6423SLionel Sambuc return(EINVAL);
157*433d6423SLionel Sambuc
158*433d6423SLionel Sambuc *stackaddr = a->ma_stackaddr;
159*433d6423SLionel Sambuc *stacksize = a->ma_stacksize;
160*433d6423SLionel Sambuc
161*433d6423SLionel Sambuc return(0);
162*433d6423SLionel Sambuc }
163*433d6423SLionel Sambuc
164*433d6423SLionel Sambuc
165*433d6423SLionel Sambuc /*===========================================================================*
166*433d6423SLionel Sambuc * mthread_attr_getstacksize *
167*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_getstacksize(attr,stacksize)168*433d6423SLionel Sambuc int mthread_attr_getstacksize(attr, stacksize)
169*433d6423SLionel Sambuc mthread_attr_t *attr;
170*433d6423SLionel Sambuc size_t *stacksize;
171*433d6423SLionel Sambuc {
172*433d6423SLionel Sambuc /* Get stack size attribute */
173*433d6423SLionel Sambuc struct __mthread_attr *a;
174*433d6423SLionel Sambuc
175*433d6423SLionel Sambuc if (attr == NULL)
176*433d6423SLionel Sambuc return(EINVAL);
177*433d6423SLionel Sambuc
178*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
179*433d6423SLionel Sambuc if (!mthread_attr_valid(attr))
180*433d6423SLionel Sambuc return(EINVAL);
181*433d6423SLionel Sambuc
182*433d6423SLionel Sambuc *stacksize = a->ma_stacksize;
183*433d6423SLionel Sambuc
184*433d6423SLionel Sambuc return(0);
185*433d6423SLionel Sambuc }
186*433d6423SLionel Sambuc
187*433d6423SLionel Sambuc
188*433d6423SLionel Sambuc /*===========================================================================*
189*433d6423SLionel Sambuc * mthread_attr_setstack *
190*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_setstack(attr,stackaddr,stacksize)191*433d6423SLionel Sambuc int mthread_attr_setstack(attr, stackaddr, stacksize)
192*433d6423SLionel Sambuc mthread_attr_t *attr;
193*433d6423SLionel Sambuc void *stackaddr;
194*433d6423SLionel Sambuc size_t stacksize;
195*433d6423SLionel Sambuc {
196*433d6423SLionel Sambuc /* Set stack attribute */
197*433d6423SLionel Sambuc struct __mthread_attr *a;
198*433d6423SLionel Sambuc
199*433d6423SLionel Sambuc if (attr == NULL)
200*433d6423SLionel Sambuc return(EINVAL);
201*433d6423SLionel Sambuc
202*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
203*433d6423SLionel Sambuc if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN)
204*433d6423SLionel Sambuc return(EINVAL);
205*433d6423SLionel Sambuc
206*433d6423SLionel Sambuc /* We don't care about address alignment (POSIX standard). The ucontext
207*433d6423SLionel Sambuc * system calls will make sure that the provided stack will be aligned (at
208*433d6423SLionel Sambuc * the cost of some memory if needed).
209*433d6423SLionel Sambuc */
210*433d6423SLionel Sambuc
211*433d6423SLionel Sambuc a->ma_stackaddr = stackaddr;
212*433d6423SLionel Sambuc a->ma_stacksize = stacksize;
213*433d6423SLionel Sambuc
214*433d6423SLionel Sambuc return(0);
215*433d6423SLionel Sambuc }
216*433d6423SLionel Sambuc
217*433d6423SLionel Sambuc
218*433d6423SLionel Sambuc /*===========================================================================*
219*433d6423SLionel Sambuc * mthread_attr_setstacksize *
220*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_setstacksize(attr,stacksize)221*433d6423SLionel Sambuc int mthread_attr_setstacksize(attr, stacksize)
222*433d6423SLionel Sambuc mthread_attr_t *attr;
223*433d6423SLionel Sambuc size_t stacksize;
224*433d6423SLionel Sambuc {
225*433d6423SLionel Sambuc /* Set stack size attribute */
226*433d6423SLionel Sambuc struct __mthread_attr *a;
227*433d6423SLionel Sambuc
228*433d6423SLionel Sambuc if (attr == NULL)
229*433d6423SLionel Sambuc return(EINVAL);
230*433d6423SLionel Sambuc
231*433d6423SLionel Sambuc a = (struct __mthread_attr *) *attr;
232*433d6423SLionel Sambuc if (!mthread_attr_valid(attr) || stacksize < MTHREAD_STACK_MIN)
233*433d6423SLionel Sambuc return(EINVAL);
234*433d6423SLionel Sambuc
235*433d6423SLionel Sambuc a->ma_stacksize = stacksize;
236*433d6423SLionel Sambuc
237*433d6423SLionel Sambuc return(0);
238*433d6423SLionel Sambuc }
239*433d6423SLionel Sambuc
240*433d6423SLionel Sambuc
241*433d6423SLionel Sambuc /*===========================================================================*
242*433d6423SLionel Sambuc * mthread_attr_remove *
243*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_remove(a)244*433d6423SLionel Sambuc static void mthread_attr_remove(a)
245*433d6423SLionel Sambuc mthread_attr_t *a;
246*433d6423SLionel Sambuc {
247*433d6423SLionel Sambuc /* Remove attribute from list of valid, initialized attributes */
248*433d6423SLionel Sambuc
249*433d6423SLionel Sambuc if ((*a)->ma_prev == NULL)
250*433d6423SLionel Sambuc va_front = (*a)->ma_next;
251*433d6423SLionel Sambuc else
252*433d6423SLionel Sambuc (*a)->ma_prev->ma_next = (*a)->ma_next;
253*433d6423SLionel Sambuc
254*433d6423SLionel Sambuc if ((*a)->ma_next == NULL)
255*433d6423SLionel Sambuc va_rear = (*a)->ma_prev;
256*433d6423SLionel Sambuc else
257*433d6423SLionel Sambuc (*a)->ma_next->ma_prev = (*a)->ma_prev;
258*433d6423SLionel Sambuc }
259*433d6423SLionel Sambuc
260*433d6423SLionel Sambuc
261*433d6423SLionel Sambuc /*===========================================================================*
262*433d6423SLionel Sambuc * mthread_attr_valid *
263*433d6423SLionel Sambuc *===========================================================================*/
mthread_attr_valid(a)264*433d6423SLionel Sambuc static int mthread_attr_valid(a)
265*433d6423SLionel Sambuc mthread_attr_t *a;
266*433d6423SLionel Sambuc {
267*433d6423SLionel Sambuc /* Check to see if attribute is on the list of valid attributes */
268*433d6423SLionel Sambuc struct __mthread_attr *loopitem;
269*433d6423SLionel Sambuc
270*433d6423SLionel Sambuc loopitem = va_front;
271*433d6423SLionel Sambuc
272*433d6423SLionel Sambuc while (loopitem != NULL) {
273*433d6423SLionel Sambuc if (loopitem == *a)
274*433d6423SLionel Sambuc return(1);
275*433d6423SLionel Sambuc
276*433d6423SLionel Sambuc loopitem = loopitem->ma_next;
277*433d6423SLionel Sambuc }
278*433d6423SLionel Sambuc
279*433d6423SLionel Sambuc return(0);
280*433d6423SLionel Sambuc }
281*433d6423SLionel Sambuc
282*433d6423SLionel Sambuc
283*433d6423SLionel Sambuc /*===========================================================================*
284*433d6423SLionel Sambuc * mthread_attr_verify *
285*433d6423SLionel Sambuc *===========================================================================*/
286*433d6423SLionel Sambuc #ifdef MDEBUG
mthread_attr_verify(void)287*433d6423SLionel Sambuc int mthread_attr_verify(void)
288*433d6423SLionel Sambuc {
289*433d6423SLionel Sambuc /* Return true when no attributes are in use */
290*433d6423SLionel Sambuc struct __mthread_attr *loopitem;
291*433d6423SLionel Sambuc
292*433d6423SLionel Sambuc loopitem = va_front;
293*433d6423SLionel Sambuc
294*433d6423SLionel Sambuc while (loopitem != NULL) {
295*433d6423SLionel Sambuc loopitem = loopitem->ma_next;
296*433d6423SLionel Sambuc return(0);
297*433d6423SLionel Sambuc }
298*433d6423SLionel Sambuc
299*433d6423SLionel Sambuc return(1);
300*433d6423SLionel Sambuc }
301*433d6423SLionel Sambuc #endif
302*433d6423SLionel Sambuc
303*433d6423SLionel Sambuc /* pthread compatibility layer. */
304*433d6423SLionel Sambuc __weak_alias(pthread_attr_destroy, mthread_attr_destroy)
305*433d6423SLionel Sambuc __weak_alias(pthread_attr_getdetachstate, mthread_attr_getdetachstate)
306*433d6423SLionel Sambuc __weak_alias(pthread_attr_getstack, mthread_attr_getstack)
307*433d6423SLionel Sambuc __weak_alias(pthread_attr_getstacksize, mthread_attr_getstacksize)
308*433d6423SLionel Sambuc __weak_alias(pthread_attr_init, mthread_attr_init)
309*433d6423SLionel Sambuc __weak_alias(pthread_attr_setdetachstate, mthread_attr_setdetachstate)
310*433d6423SLionel Sambuc __weak_alias(pthread_attr_setstack, mthread_attr_setstack)
311*433d6423SLionel Sambuc __weak_alias(pthread_attr_setstacksize, mthread_attr_setstacksize)
312*433d6423SLionel Sambuc
313