xref: /minix3/minix/lib/libmthread/attribute.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
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