1/*
2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2008, Axel D��rfler, axeld@pinc-software.de.
4 * Copyright 2006, J��r��me Duval. All rights reserved.
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include <pthread.h>
10#include "pthread_private.h"
11
12#include <limits.h>
13#include <stdlib.h>
14
15#include <Debug.h>
16
17#include <syscalls.h>
18#include <thread_defs.h>
19
20
21int __pthread_attr_get_np(pthread_t thread, pthread_attr_t *_attr);
22int __pthread_getattr_np(pthread_t thread, pthread_attr_t *_attr);
23
24
25int
26pthread_attr_init(pthread_attr_t *_attr)
27{
28	pthread_attr *attr;
29
30	if (_attr == NULL)
31		return B_BAD_VALUE;
32
33	attr = (pthread_attr *)malloc(sizeof(pthread_attr));
34	if (attr == NULL)
35		return B_NO_MEMORY;
36
37	attr->detach_state = PTHREAD_CREATE_JOINABLE;
38	attr->sched_priority = B_NORMAL_PRIORITY;
39	attr->stack_size = USER_STACK_SIZE;
40	attr->guard_size = USER_STACK_GUARD_SIZE;
41	attr->stack_address = NULL;
42
43	*_attr = attr;
44	return B_OK;
45}
46
47
48int
49pthread_attr_destroy(pthread_attr_t *_attr)
50{
51	pthread_attr *attr;
52
53	if (_attr == NULL || (attr = *_attr) == NULL)
54		return B_BAD_VALUE;
55
56	*_attr = NULL;
57	free(attr);
58
59	return B_OK;
60}
61
62
63int
64pthread_attr_getdetachstate(const pthread_attr_t *_attr, int *state)
65{
66	pthread_attr *attr;
67
68	if (_attr == NULL || (attr = *_attr) == NULL || state == NULL)
69		return B_BAD_VALUE;
70
71	*state = attr->detach_state;
72
73	return B_OK;
74}
75
76
77int
78pthread_attr_setdetachstate(pthread_attr_t *_attr, int state)
79{
80	pthread_attr *attr;
81
82	if (_attr == NULL || (attr = *_attr) == NULL)
83		return B_BAD_VALUE;
84
85	if (state != PTHREAD_CREATE_JOINABLE && state != PTHREAD_CREATE_DETACHED)
86		return B_BAD_VALUE;
87
88	attr->detach_state = state;
89
90	return B_OK;
91}
92
93
94int
95pthread_attr_getstacksize(const pthread_attr_t *_attr, size_t *stacksize)
96{
97	pthread_attr *attr;
98
99	if (_attr == NULL || (attr = *_attr) == NULL || stacksize == NULL)
100		return B_BAD_VALUE;
101
102	*stacksize = attr->stack_size;
103
104	return 0;
105}
106
107
108int
109pthread_attr_setstacksize(pthread_attr_t *_attr, size_t stacksize)
110{
111	pthread_attr *attr;
112
113	if (_attr == NULL || (attr = *_attr) == NULL)
114		return B_BAD_VALUE;
115
116	STATIC_ASSERT(PTHREAD_STACK_MIN >= MIN_USER_STACK_SIZE
117		&& PTHREAD_STACK_MIN <= MAX_USER_STACK_SIZE);
118	if (stacksize < PTHREAD_STACK_MIN || stacksize > MAX_USER_STACK_SIZE)
119		return B_BAD_VALUE;
120
121	attr->stack_size = stacksize;
122
123	return 0;
124}
125
126
127int
128pthread_attr_getscope(const pthread_attr_t *attr, int *contentionScope)
129{
130	if (attr == NULL || contentionScope == NULL)
131		return EINVAL;
132
133	*contentionScope = PTHREAD_SCOPE_SYSTEM;
134	return 0;
135}
136
137
138int
139pthread_attr_setscope(pthread_attr_t *attr, int contentionScope)
140{
141	if (attr == NULL)
142		return EINVAL;
143
144	if (contentionScope != PTHREAD_SCOPE_SYSTEM)
145		return ENOTSUP;
146
147	return 0;
148}
149
150
151int
152pthread_attr_setschedparam(pthread_attr_t *attr,
153	const struct sched_param *param)
154{
155	if (attr == NULL || param == NULL)
156		return EINVAL;
157
158	(*attr)->sched_priority = param->sched_priority;
159
160	return 0;
161}
162
163
164int
165pthread_attr_getschedparam(const pthread_attr_t *attr,
166	struct sched_param *param)
167{
168	if (attr == NULL || param == NULL)
169		return EINVAL;
170
171	param->sched_priority = (*attr)->sched_priority;
172
173	return 0;
174}
175
176
177int
178pthread_attr_getguardsize(const pthread_attr_t *_attr, size_t *guardsize)
179{
180	pthread_attr *attr;
181
182	if (_attr == NULL || (attr = *_attr) == NULL || guardsize == NULL)
183		return B_BAD_VALUE;
184
185	*guardsize = attr->guard_size;
186
187	return 0;
188}
189
190
191int
192pthread_attr_setguardsize(pthread_attr_t *_attr, size_t guardsize)
193{
194	pthread_attr *attr;
195
196	if (_attr == NULL || (attr = *_attr) == NULL)
197		return B_BAD_VALUE;
198
199	attr->guard_size = guardsize;
200
201	return 0;
202}
203
204
205int
206pthread_attr_getstack(const pthread_attr_t *_attr, void **stackaddr,
207	size_t *stacksize)
208{
209	pthread_attr *attr;
210
211	if (_attr == NULL || (attr = *_attr) == NULL || stackaddr == NULL
212		|| stacksize == NULL) {
213		return B_BAD_VALUE;
214	}
215
216	*stacksize = attr->stack_size;
217	*stackaddr = attr->stack_address;
218
219	return 0;
220}
221
222
223int
224pthread_attr_setstack(pthread_attr_t *_attr, void *stackaddr,
225	size_t stacksize)
226{
227	pthread_attr *attr;
228
229	if (_attr == NULL || (attr = *_attr) == NULL)
230		return B_BAD_VALUE;
231
232	STATIC_ASSERT(PTHREAD_STACK_MIN >= MIN_USER_STACK_SIZE
233		&& PTHREAD_STACK_MIN <= MAX_USER_STACK_SIZE);
234	if (stacksize < PTHREAD_STACK_MIN || stacksize > MAX_USER_STACK_SIZE)
235		return B_BAD_VALUE;
236
237	attr->stack_size = stacksize;
238	attr->stack_address = stackaddr;
239
240	return 0;
241}
242
243
244int
245__pthread_attr_get_np(pthread_t thread, pthread_attr_t *_attr)
246{
247	pthread_attr *attr;
248	status_t status;
249	thread_info info;
250
251	if (_attr == NULL || (attr = *_attr) == NULL)
252		return B_BAD_VALUE;
253
254	status = _kern_get_thread_info(thread->id, &info);
255	if (status == B_BAD_THREAD_ID)
256		return ESRCH;
257
258	if ((thread->flags & THREAD_DETACHED) != 0)
259		attr->detach_state = PTHREAD_CREATE_DETACHED;
260	else
261		attr->detach_state = PTHREAD_CREATE_JOINABLE;
262	attr->sched_priority = info.priority;
263	attr->stack_address = info.stack_base;
264	attr->stack_size = (size_t)info.stack_end - (size_t)info.stack_base;
265	// not in thread_info
266	attr->guard_size = 0;
267
268	return 0;
269}
270
271
272int
273__pthread_getattr_np(pthread_t thread, pthread_attr_t *_attr)
274{
275	int err = pthread_attr_init(_attr);
276	if (err == 0)
277		err = __pthread_attr_get_np(thread, _attr);
278	return err;
279}
280
281
282B_DEFINE_WEAK_ALIAS(__pthread_getattr_np, pthread_getattr_np);
283B_DEFINE_WEAK_ALIAS(__pthread_attr_get_np, pthread_attr_get_np);
284
285