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