thr_attr.c revision 125963
1/*
2 * Copyright (c) 1995-1997 John Birrell <jb@cimlogic.com.au>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by John Birrell.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/lib/libthr/thread/thr_attr.c 125963 2004-02-18 14:56:20Z mtm $
33 */
34
35/*
36 * Copyright (c) 2003 Craig Rodrigues <rodrigc@attbi.com>.
37 * All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 *    notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 *    notice, this list of conditions and the following disclaimer in the
46 *    documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 *    must display the following acknowledgement:
49 *	This product includes software developed by Craig Rodrigues.
50 * 4. Neither the name of the author nor the names of any co-contributors
51 *    may be used to endorse or promote products derived from this software
52 *    without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY CRAIG RODRIGUES AND CONTRIBUTORS ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
56 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
57 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 */
67
68/*
69 * Copyright (c) 1998 Daniel Eischen <eischen@vigrid.com>.
70 * Copyright (C) 2001 Jason Evans <jasone@freebsd.org>.
71 * Copyright (c) 2002,2003 Alexey Zelkin <phantom@FreeBSD.org>
72 * Copyright (c) 2003 Jeff Roberson <jeff@FreeBSD.org>
73 * All rights reserved.
74 *
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
77 * are met:
78 * 1. Redistributions of source code must retain the above copyright
79 *    notice(s), this list of conditions and the following disclaimer
80 *    unmodified other than the allowable addition of one or more
81 *    copyright notices.
82 * 2. Redistributions in binary form must reproduce the above copyright
83 *    notice(s), this list of conditions and the following disclaimer in
84 *    the documentation and/or other materials provided with the
85 *    distribution.
86 *
87 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
88 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
90 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
91 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
92 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
93 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
94 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
95 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
96 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
97 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
98 */
99
100/* XXXTHR I rewrote the entire file, can we lose some of the copyrights? */
101
102#include <sys/param.h>
103
104#include <errno.h>
105#include <pthread.h>
106#include <pthread_np.h>
107#include <stdlib.h>
108#include <string.h>
109
110#include "thr_private.h"
111
112__weak_reference(_pthread_attr_destroy, pthread_attr_destroy);
113__weak_reference(_pthread_attr_init, pthread_attr_init);
114__weak_reference(_pthread_attr_setcreatesuspend_np,
115    pthread_attr_setcreatesuspend_np);
116__weak_reference(_pthread_attr_setdetachstate, pthread_attr_setdetachstate);
117__weak_reference(_pthread_attr_setguardsize, pthread_attr_setguardsize);
118__weak_reference(_pthread_attr_setinheritsched, pthread_attr_setinheritsched);
119__weak_reference(_pthread_attr_setschedparam, pthread_attr_setschedparam);
120__weak_reference(_pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
121__weak_reference(_pthread_attr_setscope, pthread_attr_setscope);
122__weak_reference(_pthread_attr_setstack, pthread_attr_setstack);
123__weak_reference(_pthread_attr_setstackaddr, pthread_attr_setstackaddr);
124__weak_reference(_pthread_attr_setstacksize, pthread_attr_setstacksize);
125__weak_reference(_pthread_attr_get_np, pthread_attr_get_np);
126__weak_reference(_pthread_attr_getdetachstate, pthread_attr_getdetachstate);
127__weak_reference(_pthread_attr_getguardsize, pthread_attr_getguardsize);
128__weak_reference(_pthread_attr_getinheritsched, pthread_attr_getinheritsched);
129__weak_reference(_pthread_attr_getschedparam, pthread_attr_getschedparam);
130__weak_reference(_pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
131__weak_reference(_pthread_attr_getscope, pthread_attr_getscope);
132__weak_reference(_pthread_attr_getstack, pthread_attr_getstack);
133__weak_reference(_pthread_attr_getstackaddr, pthread_attr_getstackaddr);
134__weak_reference(_pthread_attr_getstacksize, pthread_attr_getstacksize);
135
136int
137_pthread_attr_init(pthread_attr_t *attr)
138{
139	pthread_attr_t	pattr;
140
141	if ((pattr = (pthread_attr_t)
142	    malloc(sizeof(struct pthread_attr))) == NULL)
143		return (ENOMEM);
144
145	memcpy(pattr, &pthread_attr_default, sizeof(struct pthread_attr));
146	*attr = pattr;
147
148	return (0);
149}
150
151int
152_pthread_attr_destroy(pthread_attr_t *attr)
153{
154	if (attr == NULL || *attr == NULL)
155		return (EINVAL);
156
157	free(*attr);
158	*attr = NULL;
159
160	return (0);
161}
162
163int
164_pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
165{
166	if (attr == NULL || *attr == NULL) {
167		errno = EINVAL;
168		return (-1);
169	}
170	(*attr)->suspend = PTHREAD_CREATE_SUSPENDED;
171
172	return (0);
173}
174
175int
176_pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
177{
178	if (attr == NULL || *attr == NULL ||
179	    (detachstate != PTHREAD_CREATE_DETACHED &&
180	    detachstate != PTHREAD_CREATE_JOINABLE))
181		return (EINVAL);
182
183	if (detachstate == PTHREAD_CREATE_DETACHED)
184		(*attr)->flags |= PTHREAD_DETACHED;
185	else
186		(*attr)->flags &= ~PTHREAD_DETACHED;
187
188	return (0);
189}
190
191int
192_pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
193{
194
195	if (attr == NULL || *attr == NULL)
196		return (EINVAL);
197
198	(*attr)->guardsize_attr = roundup(guardsize, _pthread_page_size);
199
200	return (0);
201}
202
203int
204_pthread_attr_setinheritsched(pthread_attr_t *attr, int sched_inherit)
205{
206	if (attr == NULL || *attr == NULL)
207		return (EINVAL);
208
209	(*attr)->sched_inherit = sched_inherit;
210
211	return (0);
212}
213
214int
215_pthread_attr_setschedparam(pthread_attr_t *attr,
216    const struct sched_param *param)
217{
218	if (attr == NULL || *attr == NULL)
219		return (EINVAL);
220
221	if (param == NULL)
222		return (ENOTSUP);
223
224	if (param->sched_priority < PTHREAD_MIN_PRIORITY ||
225	    param->sched_priority > PTHREAD_MAX_PRIORITY)
226		return (ENOTSUP);
227
228	(*attr)->prio = param->sched_priority;
229
230	return (0);
231}
232
233int
234_pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
235{
236	if (attr == NULL || *attr == NULL)
237		return (EINVAL);
238
239	if (policy < SCHED_FIFO || policy > SCHED_RR)
240		return (ENOTSUP);
241
242	(*attr)->sched_policy = policy;
243
244	return (0);
245}
246
247int
248_pthread_attr_setscope(pthread_attr_t *attr, int contentionscope)
249{
250	if (attr == NULL || *attr == NULL)
251		return (EINVAL);
252
253	if (contentionscope != PTHREAD_SCOPE_PROCESS ||
254	    contentionscope == PTHREAD_SCOPE_SYSTEM)
255		/* We don't support PTHREAD_SCOPE_SYSTEM. */
256		return (ENOTSUP);
257
258	(*attr)->flags |= contentionscope;
259
260	return (0);
261}
262
263int
264_pthread_attr_setstack(pthread_attr_t *attr, void *stackaddr,
265                        size_t stacksize)
266{
267	if (attr == NULL || *attr == NULL || stackaddr == NULL
268	    || stacksize < PTHREAD_STACK_MIN)
269		return (EINVAL);
270
271	(*attr)->stackaddr_attr = stackaddr;
272	(*attr)->stacksize_attr = stacksize;
273
274	return (0);
275}
276
277int
278_pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
279{
280	if (attr == NULL || *attr == NULL || stackaddr == NULL)
281		return (EINVAL);
282
283	(*attr)->stackaddr_attr = stackaddr;
284
285	return (0);
286}
287
288int
289_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
290{
291	if (attr == NULL || *attr == NULL || stacksize < PTHREAD_STACK_MIN)
292		return (EINVAL);
293
294	(*attr)->stacksize_attr = stacksize;
295
296	return (0);
297}
298
299int
300_pthread_attr_get_np(pthread_t pid, pthread_attr_t *dst)
301{
302	int	ret;
303
304	if (pid == NULL || dst == NULL || *dst == NULL)
305		return (EINVAL);
306
307	if ((ret = _find_thread(pid)) != 0)
308		return (ret);
309
310	memcpy(*dst, &pid->attr, sizeof(struct pthread_attr));
311
312	/*
313	 * Special case, if stack address was not provided by caller
314	 * of pthread_create(), then return address allocated internally
315	 */
316	if ((*dst)->stackaddr_attr == NULL)
317		(*dst)->stackaddr_attr = pid->stack;
318
319	return (0);
320}
321
322int
323_pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
324{
325
326	if (attr == NULL || *attr == NULL || detachstate == NULL)
327		return (EINVAL);
328
329	/* Check if the detached flag is set: */
330	if ((*attr)->flags & PTHREAD_DETACHED)
331		*detachstate = PTHREAD_CREATE_DETACHED;
332	else
333		*detachstate = PTHREAD_CREATE_JOINABLE;
334
335	return (0);
336}
337
338int
339_pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
340{
341	if (attr == NULL || *attr == NULL || guardsize == NULL)
342		return (EINVAL);
343
344	*guardsize = (*attr)->guardsize_attr;
345
346	return (0);
347}
348
349int
350_pthread_attr_getinheritsched(const pthread_attr_t *attr, int *sched_inherit)
351{
352	if (attr == NULL || *attr == NULL)
353		return (EINVAL);
354
355	*sched_inherit = (*attr)->sched_inherit;
356
357	return (0);
358}
359
360int
361_pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param)
362{
363	if (attr == NULL || *attr == NULL || param == NULL)
364		return (EINVAL);
365
366	param->sched_priority = (*attr)->prio;
367
368	return (0);
369}
370
371int
372_pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
373{
374	if (attr == NULL || *attr == NULL || policy == NULL)
375		return (EINVAL);
376
377	*policy = (*attr)->sched_policy;
378
379	return (0);
380}
381
382int
383_pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope)
384{
385	if (attr == NULL || *attr == NULL || contentionscope == NULL)
386		return (EINVAL);
387
388	*contentionscope = (*attr)->flags & PTHREAD_SCOPE_SYSTEM ?
389	    PTHREAD_SCOPE_SYSTEM : PTHREAD_SCOPE_PROCESS;
390
391	return (0);
392}
393
394int
395_pthread_attr_getstack(const pthread_attr_t * __restrict attr,
396                        void ** __restrict stackaddr,
397                        size_t * __restrict stacksize)
398{
399	if (attr == NULL || *attr == NULL || stackaddr == NULL
400	    || stacksize == NULL)
401		return (EINVAL);
402
403	*stackaddr = (*attr)->stackaddr_attr;
404	*stacksize = (*attr)->stacksize_attr;
405
406	return (0);
407}
408
409int
410_pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
411{
412	if (attr == NULL || *attr == NULL || stackaddr == NULL)
413		return (EINVAL);
414
415	*stackaddr = (*attr)->stackaddr_attr;
416
417	return (0);
418}
419
420int
421_pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
422{
423	if (attr == NULL || *attr == NULL || stacksize  == NULL)
424		return (EINVAL);
425
426	*stacksize = (*attr)->stacksize_attr;
427
428	return (0);
429}
430