2 * Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2006, Jérôme Duval. All rights reserved.
4 * Distributed under the terms of the MIT License.
8 #include "pthread_private.h"
16 #include <syscall_utils.h>
18 #include <libroot_private.h>
20 #include <thread_defs.h>
23 #include <user_thread.h>
26 static const pthread_attr pthread_attr_default
= {
27 PTHREAD_CREATE_JOINABLE
,
34 static pthread_thread sMainThread
;
35 static int sConcurrencyLevel
;
39 pthread_thread_entry(void*, void* _thread
)
41 pthread_thread
* thread
= (pthread_thread
*)_thread
;
43 pthread_exit(thread
->entry(thread
->entry_argument
));
48 // #pragma mark - private API
52 __pthread_destroy_thread(void)
54 pthread_thread
* thread
= pthread_self();
56 // call cleanup handlers
58 struct __pthread_cleanup_handler
* handler
59 = __pthread_cleanup_pop_handler();
63 handler
->function(handler
->argument
);
66 __pthread_key_call_destructors(thread
);
68 if ((atomic_or(&thread
->flags
, THREAD_DEAD
) & THREAD_DETACHED
) != 0)
74 __allocate_pthread(void* (*entry
)(void*), void *data
)
76 pthread_thread
* thread
= (pthread_thread
*)malloc(sizeof(pthread_thread
));
80 __init_pthread(thread
, entry
, data
);
87 __init_pthread(pthread_thread
* thread
, void* (*entry
)(void*), void* data
)
89 thread
->entry
= entry
;
90 thread
->entry_argument
= data
;
91 thread
->exit_value
= NULL
;
92 thread
->cleanup_handlers
= NULL
;
93 thread
->flags
= THREAD_CANCEL_ENABLED
;
94 // thread cancellation enabled, but deferred
96 memset(thread
->specific
, 0, sizeof(thread
->specific
));
101 __pthread_init_creation_attributes(const pthread_attr_t
* pthreadAttributes
,
102 pthread_t thread
, status_t (*entryFunction
)(void*, void*),
103 void* argument1
, void* argument2
, const char* name
,
104 thread_creation_attributes
* attributes
)
106 const pthread_attr
* attr
= NULL
;
107 if (pthreadAttributes
== NULL
) {
108 attr
= &pthread_attr_default
;
110 attr
= *pthreadAttributes
;
115 attributes
->entry
= entryFunction
;
116 attributes
->name
= name
;
117 attributes
->priority
= attr
->sched_priority
;
118 attributes
->args1
= argument1
;
119 attributes
->args2
= argument2
;
120 attributes
->stack_address
= NULL
;
121 attributes
->stack_size
= attr
->stack_size
;
122 attributes
->guard_size
= attr
->guard_size
;
123 attributes
->pthread
= thread
;
124 attributes
->flags
= 0;
126 if (thread
!= NULL
&& attr
->detach_state
== PTHREAD_CREATE_DETACHED
)
127 thread
->flags
|= THREAD_DETACHED
;
133 // #pragma mark - public API
137 pthread_create(pthread_t
* _thread
, const pthread_attr_t
* attr
,
138 void* (*startRoutine
)(void*), void* arg
)
143 pthread_thread
* thread
= __allocate_pthread(startRoutine
, arg
);
147 thread_creation_attributes attributes
;
148 status_t error
= __pthread_init_creation_attributes(attr
, thread
,
149 &pthread_thread_entry
, NULL
, thread
, "pthread func", &attributes
);
155 thread
->id
= _kern_spawn_thread(&attributes
);
156 if (thread
->id
< 0) {
157 // stupid error code but demanded by POSIX
162 __set_stack_protection();
163 resume_thread(thread
->id
);
173 pthread_thread
* thread
= get_user_thread()->pthread
;
182 pthread_equal(pthread_t t1
, pthread_t t2
)
189 pthread_join(pthread_t thread
, void** _value
)
194 error
= wait_for_thread(thread
->id
, &dummy
);
195 } while (error
== B_INTERRUPTED
);
197 if (error
== B_BAD_THREAD_ID
)
198 RETURN_AND_TEST_CANCEL(ESRCH
);
201 *_value
= thread
->exit_value
;
203 if ((atomic_or(&thread
->flags
, THREAD_DETACHED
) & THREAD_DEAD
) != 0)
206 RETURN_AND_TEST_CANCEL(error
);
211 pthread_exit(void* value
)
213 pthread_self()->exit_value
= value
;
219 pthread_kill(pthread_t thread
, int sig
)
221 status_t status
= send_signal(thread
->id
, (uint
)sig
);
222 if (status
!= B_OK
) {
223 if (status
== B_BAD_THREAD_ID
)
234 pthread_detach(pthread_t thread
)
241 flags
= atomic_or(&thread
->flags
, THREAD_DETACHED
);
242 if ((flags
& THREAD_DETACHED
) != 0)
245 if ((flags
& THREAD_DEAD
) != 0)
253 pthread_getconcurrency(void)
255 return sConcurrencyLevel
;
260 pthread_setconcurrency(int newLevel
)
265 sConcurrencyLevel
= newLevel
;
271 pthread_getschedparam(pthread_t thread
, int *policy
, struct sched_param
*param
)
274 status_t status
= _kern_get_thread_info(thread
->id
, &info
);
275 if (status
== B_BAD_THREAD_ID
)
277 param
->sched_priority
= info
.priority
;
285 pthread_setschedparam(pthread_t thread
, int policy
,
286 const struct sched_param
*param
)
289 if (policy
!= SCHED_RR
)
291 status
= _kern_set_thread_priority(thread
->id
, param
->sched_priority
);
292 if (status
== B_BAD_THREAD_ID
)
298 // #pragma mark - Haiku thread API bridge
302 get_pthread_thread_id(pthread_t thread
)