xref: /openbsd-src/lib/librthread/rthread_attr.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /*	$OpenBSD: rthread_attr.c,v 1.19 2012/03/22 15:26:04 kurt Exp $ */
2 /*
3  * Copyright (c) 2004,2005 Ted Unangst <tedu@openbsd.org>
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*
19  * generic attribute support
20  */
21 
22 #include <inttypes.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <errno.h>
26 
27 #include <pthread.h>
28 #include <pthread_np.h>
29 
30 #include "rthread.h"
31 
32 /*
33  * Note: stack_size + guard_size == total stack used
34  *
35  * pthread_attr_init MUST be called before any other attribute function
36  * for proper operation.
37  *
38  * Every call to pthread_attr_init MUST be matched with a call to
39  * pthread_attr_destroy to avoid leaking memory.   This is an implementation
40  * requirement, not a POSIX requirement.
41  */
42 
43 int
44 pthread_attr_init(pthread_attr_t *attrp)
45 {
46 	pthread_attr_t attr;
47 	int error;
48 
49 	/* make sure _rthread_attr_default has been initialized */
50 	if (!_threads_ready)
51 		if ((error = _rthread_init()))
52 			return (error);
53 
54 	attr = calloc(1, sizeof(*attr));
55 	if (!attr)
56 		return (errno);
57 	*attr = _rthread_attr_default;
58 	*attrp = attr;
59 
60 	return (0);
61 }
62 
63 int
64 pthread_attr_destroy(pthread_attr_t *attrp)
65 {
66 	free(*attrp);
67 	*attrp = NULL;
68 
69 	return (0);
70 }
71 
72 int
73 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize)
74 {
75 	*guardsize = (*attrp)->guard_size;
76 
77 	return (0);
78 }
79 
80 int
81 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize)
82 {
83 	(*attrp)->guard_size = guardsize;
84 
85 	return (0);
86 }
87 
88 int
89 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate)
90 {
91 	*detachstate = (*attrp)->detach_state;
92 
93 	return (0);
94 }
95 
96 int
97 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate)
98 {
99 	int error;
100 
101 	error = (detachstate == PTHREAD_CREATE_DETACHED ||
102 		  detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL;
103 	if (error == 0)
104 		(*attrp)->detach_state = detachstate;
105 
106 	return (error);
107 }
108 
109 int
110 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr,
111     size_t *stacksize)
112 {
113 	*stackaddr = (*attrp)->stack_addr;
114 	*stacksize = (*attrp)->stack_size;
115 
116 	return (0);
117 }
118 
119 int
120 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize)
121 {
122 	int error;
123 
124 	/*
125 	 * XXX Add an alignment test, on stackaddr for stack-grows-up
126 	 * archs or on stackaddr+stacksize for stack-grows-down archs
127 	 */
128 	if (stacksize < PTHREAD_STACK_MIN)
129 		return (EINVAL);
130 	if ((error = pthread_attr_setstackaddr(attrp, stackaddr)))
131 		return (error);
132 	(*attrp)->stack_size = stacksize;
133 
134 	return (0);
135 }
136 
137 int
138 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize)
139 {
140 	*stacksize = (*attrp)->stack_size;
141 
142 	return (0);
143 }
144 
145 int
146 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
147 {
148 	if (stacksize < PTHREAD_STACK_MIN ||
149 	    stacksize > ROUND_TO_PAGE(stacksize))
150 		return (EINVAL);
151 	(*attrp)->stack_size = stacksize;
152 
153 	return (0);
154 }
155 
156 int
157 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr)
158 {
159 	*stackaddr = (*attrp)->stack_addr;
160 
161 	return (0);
162 }
163 
164 int
165 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
166 {
167 	if (stackaddr == NULL || (uintptr_t)stackaddr & (_thread_pagesize - 1))
168 		return (EINVAL);
169 	(*attrp)->stack_addr = stackaddr;
170 
171 	return (0);
172 }
173 
174 int
175 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
176 {
177 	*contentionscope = (*attrp)->contention_scope;
178 
179 	return (0);
180 }
181 
182 int
183 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope)
184 {
185 	if (contentionscope != PTHREAD_SCOPE_SYSTEM &&
186 	    contentionscope != PTHREAD_SCOPE_PROCESS)
187 		return (EINVAL);
188 	(*attrp)->contention_scope = contentionscope;
189 
190 	return (0);
191 }
192 
193