xref: /openbsd-src/lib/librthread/rthread_attr.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /*	$OpenBSD: rthread_attr.c,v 1.23 2017/09/05 02:40:54 guenther 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 <stdint.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 
48 	/* make sure _rthread_attr_default has been initialized */
49 	if (!_threads_ready)
50 		_rthread_init();
51 
52 	attr = calloc(1, sizeof(*attr));
53 	if (!attr)
54 		return (errno);
55 	*attr = _rthread_attr_default;
56 	*attrp = attr;
57 
58 	return (0);
59 }
60 
61 int
62 pthread_attr_destroy(pthread_attr_t *attrp)
63 {
64 	free(*attrp);
65 	*attrp = NULL;
66 
67 	return (0);
68 }
69 
70 int
71 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize)
72 {
73 	*guardsize = (*attrp)->guard_size;
74 
75 	return (0);
76 }
77 
78 int
79 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize)
80 {
81 	(*attrp)->guard_size = guardsize;
82 
83 	return (0);
84 }
85 
86 int
87 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate)
88 {
89 	*detachstate = (*attrp)->detach_state;
90 
91 	return (0);
92 }
93 
94 int
95 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate)
96 {
97 	int error;
98 
99 	error = (detachstate == PTHREAD_CREATE_DETACHED ||
100 		  detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL;
101 	if (error == 0)
102 		(*attrp)->detach_state = detachstate;
103 
104 	return (error);
105 }
106 
107 int
108 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr,
109     size_t *stacksize)
110 {
111 	*stackaddr = (*attrp)->stack_addr;
112 	*stacksize = (*attrp)->stack_size;
113 
114 	return (0);
115 }
116 
117 int
118 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize)
119 {
120 	int error;
121 
122 	/*
123 	 * XXX Add an alignment test, on stackaddr for stack-grows-up
124 	 * archs or on stackaddr+stacksize for stack-grows-down archs
125 	 */
126 	if (stacksize < PTHREAD_STACK_MIN)
127 		return (EINVAL);
128 	if ((error = pthread_attr_setstackaddr(attrp, stackaddr)))
129 		return (error);
130 	(*attrp)->stack_size = stacksize;
131 
132 	return (0);
133 }
134 
135 int
136 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize)
137 {
138 	*stacksize = (*attrp)->stack_size;
139 
140 	return (0);
141 }
142 
143 int
144 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
145 {
146 	if (!_threads_ready)		/* for ROUND_TO_PAGE */
147 		_rthread_init();
148 
149 	if (stacksize < PTHREAD_STACK_MIN ||
150 	    stacksize > ROUND_TO_PAGE(stacksize))
151 		return (EINVAL);
152 	(*attrp)->stack_size = stacksize;
153 
154 	return (0);
155 }
156 
157 int
158 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr)
159 {
160 	*stackaddr = (*attrp)->stack_addr;
161 
162 	return (0);
163 }
164 
165 int
166 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
167 {
168 	if (!_threads_ready)
169 		_rthread_init();		/* for _thread_pagesize */
170 
171 	if (stackaddr == NULL || (uintptr_t)stackaddr & (_thread_pagesize - 1))
172 		return (EINVAL);
173 	(*attrp)->stack_addr = stackaddr;
174 
175 	return (0);
176 }
177 DEF_NONSTD(pthread_attr_setstackaddr);
178 
179 int
180 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
181 {
182 	*contentionscope = (*attrp)->contention_scope;
183 
184 	return (0);
185 }
186 
187 int
188 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope)
189 {
190 	if (contentionscope != PTHREAD_SCOPE_SYSTEM &&
191 	    contentionscope != PTHREAD_SCOPE_PROCESS)
192 		return (EINVAL);
193 	(*attrp)->contention_scope = contentionscope;
194 
195 	return (0);
196 }
197 
198