1 /*
2 ** GNU Pth - The GNU Portable Threads
3 ** Copyright (c) 1999-2006 Ralf S. Engelschall <rse@engelschall.com>
4 **
5 ** This file is part of GNU Pth, a non-preemptive thread scheduling
6 ** library which can be found at http://www.gnu.org/software/pth/.
7 **
8 ** This library is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU Lesser General Public
10 ** License as published by the Free Software Foundation; either
11 ** version 2.1 of the License, or (at your option) any later version.
12 **
13 ** This library is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** Lesser General Public License for more details.
17 **
18 ** You should have received a copy of the GNU Lesser General Public
19 ** License along with this library; if not, write to the Free Software
20 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 ** USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
22 **
23 ** pth_attr.c: Pth thread attributes
24 */
25 /* ``Unix -- where you can do anything
26 in two keystrokes, or less...''
27 -- Unknown */
28 #include "pth_p.h"
29
30 #if cpp
31
32 enum {
33 PTH_ATTR_GET,
34 PTH_ATTR_SET
35 };
36
37 struct pth_attr_st {
38 pth_t a_tid;
39 int a_prio;
40 int a_dispatches;
41 char a_name[PTH_TCB_NAMELEN];
42 int a_joinable;
43 unsigned int a_cancelstate;
44 unsigned int a_stacksize;
45 char *a_stackaddr;
46 };
47
48 #endif /* cpp */
49
pth_attr_of(pth_t t)50 pth_attr_t pth_attr_of(pth_t t)
51 {
52 pth_attr_t a;
53
54 if (t == NULL)
55 return pth_error((pth_attr_t)NULL, EINVAL);
56 if ((a = (pth_attr_t)malloc(sizeof(struct pth_attr_st))) == NULL)
57 return pth_error((pth_attr_t)NULL, ENOMEM);
58 a->a_tid = t;
59 return a;
60 }
61
pth_attr_new(void)62 pth_attr_t pth_attr_new(void)
63 {
64 pth_attr_t a;
65
66 if ((a = (pth_attr_t)malloc(sizeof(struct pth_attr_st))) == NULL)
67 return pth_error((pth_attr_t)NULL, ENOMEM);
68 a->a_tid = NULL;
69 pth_attr_init(a);
70 return a;
71 }
72
pth_attr_destroy(pth_attr_t a)73 int pth_attr_destroy(pth_attr_t a)
74 {
75 if (a == NULL)
76 return pth_error(FALSE, EINVAL);
77 free(a);
78 return TRUE;
79 }
80
pth_attr_init(pth_attr_t a)81 int pth_attr_init(pth_attr_t a)
82 {
83 if (a == NULL)
84 return pth_error(FALSE, EINVAL);
85 if (a->a_tid != NULL)
86 return pth_error(FALSE, EPERM);
87 a->a_prio = PTH_PRIO_STD;
88 pth_util_cpystrn(a->a_name, "unknown", PTH_TCB_NAMELEN);
89 a->a_dispatches = 0;
90 a->a_joinable = TRUE;
91 a->a_cancelstate = PTH_CANCEL_DEFAULT;
92 a->a_stacksize = 64*1024;
93 a->a_stackaddr = NULL;
94 return TRUE;
95 }
96
pth_attr_get(pth_attr_t a,int op,...)97 int pth_attr_get(pth_attr_t a, int op, ...)
98 {
99 va_list ap;
100 int rc;
101
102 va_start(ap, op);
103 rc = pth_attr_ctrl(PTH_ATTR_GET, a, op, ap);
104 va_end(ap);
105 return rc;
106 }
107
pth_attr_set(pth_attr_t a,int op,...)108 int pth_attr_set(pth_attr_t a, int op, ...)
109 {
110 va_list ap;
111 int rc;
112
113 va_start(ap, op);
114 rc = pth_attr_ctrl(PTH_ATTR_SET, a, op, ap);
115 va_end(ap);
116 return rc;
117 }
118
pth_attr_ctrl(int cmd,pth_attr_t a,int op,va_list ap)119 intern int pth_attr_ctrl(int cmd, pth_attr_t a, int op, va_list ap)
120 {
121 if (a == NULL)
122 return pth_error(FALSE, EINVAL);
123 switch (op) {
124 case PTH_ATTR_PRIO: {
125 /* priority */
126 int val, *src, *dst;
127 if (cmd == PTH_ATTR_SET) {
128 src = &val; val = va_arg(ap, int);
129 dst = (a->a_tid != NULL ? &a->a_tid->prio : &a->a_prio);
130 }
131 else {
132 src = (a->a_tid != NULL ? &a->a_tid->prio : &a->a_prio);
133 dst = va_arg(ap, int *);
134 }
135 *dst = *src;
136 break;
137 }
138 case PTH_ATTR_NAME: {
139 /* name */
140 if (cmd == PTH_ATTR_SET) {
141 char *src, *dst;
142 src = va_arg(ap, char *);
143 dst = (a->a_tid != NULL ? a->a_tid->name : a->a_name);
144 pth_util_cpystrn(dst, src, PTH_TCB_NAMELEN);
145 }
146 else {
147 char *src, **dst;
148 src = (a->a_tid != NULL ? a->a_tid->name : a->a_name);
149 dst = va_arg(ap, char **);
150 *dst = src;
151 }
152 break;
153 }
154 case PTH_ATTR_DISPATCHES: {
155 /* incremented on every context switch */
156 int val, *src, *dst;
157 if (cmd == PTH_ATTR_SET) {
158 src = &val; val = va_arg(ap, int);
159 dst = (a->a_tid != NULL ? &a->a_tid->dispatches : &a->a_dispatches);
160 }
161 else {
162 src = (a->a_tid != NULL ? &a->a_tid->dispatches : &a->a_dispatches);
163 dst = va_arg(ap, int *);
164 }
165 *dst = *src;
166 break;
167 }
168 case PTH_ATTR_JOINABLE: {
169 /* detachment type */
170 int val, *src, *dst;
171 if (cmd == PTH_ATTR_SET) {
172 src = &val; val = va_arg(ap, int);
173 dst = (a->a_tid != NULL ? &a->a_tid->joinable : &a->a_joinable);
174 }
175 else {
176 src = (a->a_tid != NULL ? &a->a_tid->joinable : &a->a_joinable);
177 dst = va_arg(ap, int *);
178 }
179 *dst = *src;
180 break;
181 }
182 case PTH_ATTR_CANCEL_STATE: {
183 /* cancellation state */
184 unsigned int val, *src, *dst;
185 if (cmd == PTH_ATTR_SET) {
186 src = &val; val = va_arg(ap, unsigned int);
187 dst = (a->a_tid != NULL ? &a->a_tid->cancelstate : &a->a_cancelstate);
188 }
189 else {
190 src = (a->a_tid != NULL ? &a->a_tid->cancelstate : &a->a_cancelstate);
191 dst = va_arg(ap, unsigned int *);
192 }
193 *dst = *src;
194 break;
195 }
196 case PTH_ATTR_STACK_SIZE: {
197 /* stack size */
198 unsigned int val, *src, *dst;
199 if (cmd == PTH_ATTR_SET) {
200 if (a->a_tid != NULL)
201 return pth_error(FALSE, EPERM);
202 src = &val; val = va_arg(ap, unsigned int);
203 dst = &a->a_stacksize;
204 }
205 else {
206 src = (a->a_tid != NULL ? &a->a_tid->stacksize : &a->a_stacksize);
207 dst = va_arg(ap, unsigned int *);
208 }
209 *dst = *src;
210 break;
211 }
212 case PTH_ATTR_STACK_ADDR: {
213 /* stack address */
214 char *val, **src, **dst;
215 if (cmd == PTH_ATTR_SET) {
216 if (a->a_tid != NULL)
217 return pth_error(FALSE, EPERM);
218 src = &val; val = va_arg(ap, char *);
219 dst = &a->a_stackaddr;
220 }
221 else {
222 src = (a->a_tid != NULL ? &a->a_tid->stack : &a->a_stackaddr);
223 dst = va_arg(ap, char **);
224 }
225 *dst = *src;
226 break;
227 }
228 case PTH_ATTR_TIME_SPAWN: {
229 pth_time_t *dst;
230 pth_itime_t dst1;
231 if (cmd == PTH_ATTR_SET)
232 return pth_error(FALSE, EPERM);
233 dst = va_arg(ap, pth_time_t *);
234 if (a->a_tid != NULL)
235 pth_time_set(&dst1, &a->a_tid->spawned);
236 else
237 pth_time_set(&dst1, PTH_TIME_ZERO);
238 pth_itime_to_time(dst, &dst1);
239 break;
240 }
241 case PTH_ATTR_TIME_LAST: {
242 pth_time_t *dst;
243 pth_itime_t dst1;
244 if (cmd == PTH_ATTR_SET)
245 return pth_error(FALSE, EPERM);
246 dst = va_arg(ap, pth_time_t *);
247 if (a->a_tid != NULL)
248 pth_time_set(&dst1, &a->a_tid->lastran);
249 else
250 pth_time_set(&dst1, PTH_TIME_ZERO);
251 pth_itime_to_time(dst, &dst1);
252 break;
253 }
254 case PTH_ATTR_TIME_RAN: {
255 pth_time_t *dst;
256 pth_itime_t dst1;
257 if (cmd == PTH_ATTR_SET)
258 return pth_error(FALSE, EPERM);
259 dst = va_arg(ap, pth_time_t *);
260 if (a->a_tid != NULL)
261 pth_time_set(&dst1, &a->a_tid->running);
262 else
263 pth_time_set(&dst1, PTH_TIME_ZERO);
264 pth_itime_to_time_iv(dst, &dst1);
265 break;
266 }
267 case PTH_ATTR_START_FUNC: {
268 void *(**dst)(void *);
269 if (cmd == PTH_ATTR_SET)
270 return pth_error(FALSE, EPERM);
271 if (a->a_tid == NULL)
272 return pth_error(FALSE, EACCES);
273 dst = (void *(**)(void *))va_arg(ap, void *);
274 *dst = a->a_tid->start_func;
275 break;
276 }
277 case PTH_ATTR_START_ARG: {
278 void **dst;
279 if (cmd == PTH_ATTR_SET)
280 return pth_error(FALSE, EPERM);
281 if (a->a_tid == NULL)
282 return pth_error(FALSE, EACCES);
283 dst = va_arg(ap, void **);
284 *dst = a->a_tid->start_arg;
285 break;
286 }
287 case PTH_ATTR_STATE: {
288 pth_state_t *dst;
289 if (cmd == PTH_ATTR_SET)
290 return pth_error(FALSE, EPERM);
291 if (a->a_tid == NULL)
292 return pth_error(FALSE, EACCES);
293 dst = va_arg(ap, pth_state_t *);
294 *dst = a->a_tid->state;
295 break;
296 }
297 case PTH_ATTR_EVENTS: {
298 pth_event_t *dst;
299 if (cmd == PTH_ATTR_SET)
300 return pth_error(FALSE, EPERM);
301 if (a->a_tid == NULL)
302 return pth_error(FALSE, EACCES);
303 dst = va_arg(ap, pth_event_t *);
304 *dst = a->a_tid->events;
305 break;
306 }
307 case PTH_ATTR_BOUND: {
308 int *dst;
309 if (cmd == PTH_ATTR_SET)
310 return pth_error(FALSE, EPERM);
311 dst = va_arg(ap, int *);
312 *dst = (a->a_tid != NULL ? TRUE : FALSE);
313 break;
314 }
315 default:
316 return pth_error(FALSE, EINVAL);
317 }
318 return TRUE;
319 }
320
321