xref: /openbsd-src/lib/librthread/rthread_attr.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: rthread_attr.c,v 1.8 2006/01/05 08:15:16 otto 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 = malloc(sizeof(*attr));
64 	if (!attr)
65 		return (errno);
66 	memset(attr, 0, sizeof(*attr));
67 	attr->stack_size = RTHREAD_STACK_SIZE_DEF;
68 	attr->guard_size = sysconf(_SC_PAGESIZE);
69 	attr->stack_size -= attr->guard_size;
70 	attr->detach_state = PTHREAD_CREATE_JOINABLE;
71 	*attrp = attr;
72 
73 	return (0);
74 }
75 
76 int
77 pthread_attr_destroy(pthread_attr_t *attrp)
78 {
79 	free(*attrp);
80 	*attrp = NULL;
81 
82 	return (0);
83 }
84 
85 int
86 pthread_attr_getguardsize(const pthread_attr_t *attrp, size_t *guardsize)
87 {
88 	*guardsize = (*attrp)->guard_size;
89 
90 	return (0);
91 }
92 
93 int
94 pthread_attr_setguardsize(pthread_attr_t *attrp, size_t guardsize)
95 {
96 	if ((*attrp)->guard_size != guardsize) {
97 		(*attrp)->stack_size += (*attrp)->guard_size;
98 		(*attrp)->guard_size = guardsize;
99 		(*attrp)->stack_size -= (*attrp)->guard_size;
100 	}
101 
102 	return 0;
103 }
104 
105 int
106 pthread_attr_getdetachstate(const pthread_attr_t *attrp, int *detachstate)
107 {
108 	*detachstate = (*attrp)->detach_state;
109 
110 	return (0);
111 }
112 
113 int
114 pthread_attr_setdetachstate(pthread_attr_t *attrp, int detachstate)
115 {
116 	int retval;
117 
118 	retval = (detachstate == PTHREAD_CREATE_DETACHED ||
119 		  detachstate == PTHREAD_CREATE_JOINABLE) ? 0 : EINVAL;
120 	if (retval == 0)
121 		(*attrp)->detach_state = detachstate;
122 
123 	return (retval);
124 }
125 
126 int
127 pthread_attr_getstack(const pthread_attr_t *attrp, void **stackaddr,
128     size_t *stacksize)
129 {
130 	*stackaddr = (*attrp)->stack_addr;
131 	*stacksize = (*attrp)->stack_size + (*attrp)->guard_size;
132 
133 	return (0);
134 }
135 
136 int
137 pthread_attr_setstack(pthread_attr_t *attrp, void *stackaddr, size_t stacksize)
138 {
139 	int n;
140 
141 	if ((n = pthread_attr_setstackaddr(attrp, stackaddr)))
142 		return (n);
143 	(*attrp)->stack_size = stacksize;
144 	(*attrp)->stack_size -= (*attrp)->guard_size;
145 
146 	return (0);
147 }
148 
149 int
150 pthread_attr_getstacksize(const pthread_attr_t *attrp, size_t *stacksize)
151 {
152 	*stacksize = (*attrp)->stack_size + (*attrp)->guard_size;
153 
154 	return (0);
155 }
156 
157 int
158 pthread_attr_setstacksize(pthread_attr_t *attrp, size_t stacksize)
159 {
160 	(*attrp)->stack_size = stacksize;
161 	if ((*attrp)->stack_size > (*attrp)->guard_size)
162 		(*attrp)->stack_size -= (*attrp)->guard_size;
163 	else
164 		(*attrp)->stack_size = 0;
165 
166 	return (0);
167 }
168 
169 int
170 pthread_attr_getstackaddr(const pthread_attr_t *attrp, void **stackaddr)
171 {
172 	*stackaddr = (*attrp)->stack_addr;
173 
174 	return (0);
175 }
176 
177 int
178 pthread_attr_setstackaddr(pthread_attr_t *attrp, void *stackaddr)
179 {
180 	size_t pgsz = sysconf(_SC_PAGESIZE);
181 
182 	if (pgsz == (size_t)-1)
183 		return EINVAL;
184 	if ((uintptr_t)stackaddr & (pgsz - 1))
185 		return EINVAL;
186 	(*attrp)->stack_addr = stackaddr;
187 
188 	return (0);
189 }
190 
191 int
192 pthread_attr_getscope(const pthread_attr_t *attrp, int *contentionscope)
193 {
194 	*contentionscope = (*attrp)->contention_scope;
195 
196 	return (0);
197 }
198 
199 int
200 pthread_attr_setscope(pthread_attr_t *attrp, int contentionscope)
201 {
202 	/* XXX contentionscope should be validated here */
203 	(*attrp)->contention_scope = contentionscope;
204 
205 	return (0);
206 }
207 
208 int
209 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
210 {
211 	(*attr)->create_suspended = 1;
212 	return (0);
213 }
214 
215