xref: /openbsd/lib/librthread/rthread_attr.c (revision 404b540a)
1 /*	$OpenBSD: rthread_attr.c,v 1.9 2008/10/13 05:42:46 kevlo 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 <sys/param.h>
23 #include <sys/mman.h>
24 #include <sys/wait.h>
25 
26 #include <machine/spinlock.h>
27 
28 #include <inttypes.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 
36 #include <pthread.h>
37 #include <pthread_np.h>
38 
39 #include "rthread.h"
40 
41 /*
42  * temp: these need to be added to pthread.h
43  */
44 int	pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
45 int	pthread_attr_setguardsize(pthread_attr_t *, size_t);
46 
47 /*
48  * Note: stack_size + guard_size == total stack used
49  *
50  * pthread_attr_init MUST be called before any other attribute function
51  * for proper operation.
52  *
53  * Every call to pthread_attr_init MUST be matched with a call to
54  * pthread_attr_destroy to avoid leaking memory.   This is an implementation
55  * requirement, not a POSIX requirement.
56  */
57 
58 int
59 pthread_attr_init(pthread_attr_t *attrp)
60 {
61 	pthread_attr_t attr;
62 
63 	attr = calloc(1, sizeof(*attr));
64 	if (!attr)
65 		return (errno);
66 	attr->stack_size = RTHREAD_STACK_SIZE_DEF;
67 	attr->guard_size = sysconf(_SC_PAGESIZE);
68 	attr->stack_size -= attr->guard_size;
69 	attr->detach_state = PTHREAD_CREATE_JOINABLE;
70 	*attrp = attr;
71 
72 	return (0);
73 }
74 
75 int
76 pthread_attr_destroy(pthread_attr_t *attrp)
77 {
78 	free(*attrp);
79 	*attrp = NULL;
80 
81 	return (0);
82 }
83 
84 int
85 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize)
86 {
87 	*guardsize = (*attrp)->guard_size;
88 
89 	return (0);
90 }
91 
92 int
93 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize)
94 {
95 	if ((*attrp)->guard_size != guardsize) {
96 		(*attrp)->stack_size += (*attrp)->guard_size;
97 		(*attrp)->guard_size = guardsize;
98 		(*attrp)->stack_size -= (*attrp)->guard_size;
99 	}
100 
101 	return 0;
102 }
103 
104 int
105 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate)
106 {
107 	*detachstate = (*attrp)->detach_state;
108 
109 	return (0);
110 }
111 
112 int
113 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate)
114 {
115 	int retval;
116 
117 	retval = (detachstate == PTHREAD_CREATE_DETACHED ||
118 		  detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL;
119 	if (retval == 0)
120 		(*attrp)->detach_state = detachstate;
121 
122 	return (retval);
123 }
124 
125 int
126 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr,
127     size_t *stacksize)
128 {
129 	*stackaddr = (*attrp)->stack_addr;
130 	*stacksize = (*attrp)->stack_size + (*attrp)->guard_size;
131 
132 	return (0);
133 }
134 
135 int
136 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize)
137 {
138 	int n;
139 
140 	if ((n = pthread_attr_setstackaddr(attrp, stackaddr)))
141 		return (n);
142 	(*attrp)->stack_size = stacksize;
143 	(*attrp)->stack_size -= (*attrp)->guard_size;
144 
145 	return (0);
146 }
147 
148 int
149 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize)
150 {
151 	*stacksize = (*attrp)->stack_size + (*attrp)->guard_size;
152 
153 	return (0);
154 }
155 
156 int
157 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
158 {
159 	(*attrp)->stack_size = stacksize;
160 	if ((*attrp)->stack_size > (*attrp)->guard_size)
161 		(*attrp)->stack_size -= (*attrp)->guard_size;
162 	else
163 		(*attrp)->stack_size = 0;
164 
165 	return (0);
166 }
167 
168 int
169 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr)
170 {
171 	*stackaddr = (*attrp)->stack_addr;
172 
173 	return (0);
174 }
175 
176 int
177 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
178 {
179 	size_t pgsz = sysconf(_SC_PAGESIZE);
180 
181 	if (pgsz == (size_t)-1)
182 		return EINVAL;
183 	if ((uintptr_t)stackaddr & (pgsz - 1))
184 		return EINVAL;
185 	(*attrp)->stack_addr = stackaddr;
186 
187 	return (0);
188 }
189 
190 int
191 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
192 {
193 	*contentionscope = (*attrp)->contention_scope;
194 
195 	return (0);
196 }
197 
198 int
199 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope)
200 {
201 	/* XXX contentionscope should be validated here */
202 	(*attrp)->contention_scope = contentionscope;
203 
204 	return (0);
205 }
206 
207 int
208 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
209 {
210 	(*attr)->create_suspended = 1;
211 	return (0);
212 }
213 
214