thread.c revision 24df6592
10865e4b2SAxel Dörfler/*
2ecf6b86cSAxel Dörfler * Copyright 2002-2009, Axel D��rfler, axeld@pinc-software.de.
32f9720f0SAxel Dörfler * Distributed under the terms of the MIT License.
42f9720f0SAxel Dörfler */
5712ec3d7SAxel Dörfler
6712ec3d7SAxel Dörfler
7712ec3d7SAxel Dörfler#include <OS.h>
88120de45SAxel Dörfler
98120de45SAxel Dörfler#include <stdlib.h>
10712ec3d7SAxel Dörfler#include <stdio.h>
11712ec3d7SAxel Dörfler
126b202f4eSIngo Weinhold#include <libroot_private.h>
13ecf6b86cSAxel Dörfler#include <pthread_private.h>
146b202f4eSIngo Weinhold#include <thread_defs.h>
156b202f4eSIngo Weinhold#include <tls.h>
166b202f4eSIngo Weinhold#include <syscalls.h>
17712ec3d7SAxel Dörfler
18712ec3d7SAxel Dörfler
198120de45SAxel Dörfler#undef thread_entry
208120de45SAxel Dörfler	// thread_entry is still defined in OS.h for compatibility reasons
218120de45SAxel Dörfler
228120de45SAxel Dörfler
238120de45SAxel Dörflertypedef struct callback_node {
248120de45SAxel Dörfler	struct callback_node *next;
258120de45SAxel Dörfler	void (*function)(void *);
268120de45SAxel Dörfler	void *argument;
278120de45SAxel Dörfler} callback_node;
288120de45SAxel Dörfler
298120de45SAxel Dörfler
30a4248cf5SJérôme Duvalvoid _thread_do_exit_work(void);
31ceee0a32SFrançois Revolvoid _thread_do_exit_notification(void);
328120de45SAxel Dörfler
338120de45SAxel Dörfler
34ecf6b86cSAxel Dörflerstatic status_t
3524df6592SIngo Weinholdthread_entry(void* _entry, void* _thread)
368120de45SAxel Dörfler{
3724df6592SIngo Weinhold	thread_func entry = (thread_func)_entry;
38ecf6b86cSAxel Dörfler	pthread_thread* thread = (pthread_thread*)_thread;
39ecf6b86cSAxel Dörfler	status_t returnCode;
40ecf6b86cSAxel Dörfler
41ecf6b86cSAxel Dörfler	returnCode = entry(thread->entry_argument);
428120de45SAxel Dörfler
43a4248cf5SJérôme Duval	_thread_do_exit_work();
448120de45SAxel Dörfler
458120de45SAxel Dörfler	return returnCode;
468120de45SAxel Dörfler}
478120de45SAxel Dörfler
488120de45SAxel Dörfler
49ecf6b86cSAxel Dörflervoid
50ecf6b86cSAxel Dörfler_thread_do_exit_notification(void)
51a4248cf5SJérôme Duval{
52585a28afSJérôme Duval	// empty stub for R5 compatibility
53a4248cf5SJérôme Duval}
54a4248cf5SJérôme Duval
55a4248cf5SJérôme Duval
56a4248cf5SJérôme Duvalvoid
57a4248cf5SJérôme Duval_thread_do_exit_work(void)
58ecf6b86cSAxel Dörfler{
59ecf6b86cSAxel Dörfler	callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT);
60ecf6b86cSAxel Dörfler	callback_node *next;
61ecf6b86cSAxel Dörfler
62ecf6b86cSAxel Dörfler	while (node != NULL) {
63ecf6b86cSAxel Dörfler		next = node->next;
64ecf6b86cSAxel Dörfler
65ecf6b86cSAxel Dörfler		node->function(node->argument);
66ecf6b86cSAxel Dörfler		free(node);
67ecf6b86cSAxel Dörfler
68ecf6b86cSAxel Dörfler		node = next;
69ecf6b86cSAxel Dörfler	}
70ecf6b86cSAxel Dörfler
71ecf6b86cSAxel Dörfler	tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL);
72ecf6b86cSAxel Dörfler
73ecf6b86cSAxel Dörfler	__pthread_destroy_thread();
74ecf6b86cSAxel Dörfler}
75ecf6b86cSAxel Dörfler
76ecf6b86cSAxel Dörfler
77ecf6b86cSAxel Dörfler// #pragma mark -
78ecf6b86cSAxel Dörfler
79ecf6b86cSAxel Dörfler
80712ec3d7SAxel Dörflerthread_id
818120de45SAxel Dörflerspawn_thread(thread_func entry, const char *name, int32 priority, void *data)
82712ec3d7SAxel Dörfler{
834c49f205SIngo Weinhold	struct thread_creation_attributes attributes;
84ecf6b86cSAxel Dörfler	pthread_thread* thread;
8585b2f68bSPhilippe Saint-Pierre	thread_id id;
86ecf6b86cSAxel Dörfler
8724df6592SIngo Weinhold	thread = __allocate_pthread(NULL, data);
88ecf6b86cSAxel Dörfler	if (thread == NULL)
89ecf6b86cSAxel Dörfler		return B_NO_MEMORY;
904c49f205SIngo Weinhold
915685273fSAxel Dörfler	_single_threaded = false;
925685273fSAxel Dörfler		// used for I/O locking - BeOS compatibility issue
935685273fSAxel Dörfler
9424df6592SIngo Weinhold	__pthread_init_creation_attributes(NULL, thread, &thread_entry, entry,
9524df6592SIngo Weinhold		thread, name, &attributes);
9624df6592SIngo Weinhold
974c49f205SIngo Weinhold	attributes.priority = priority;
984c49f205SIngo Weinhold
9985b2f68bSPhilippe Saint-Pierre	id = _kern_spawn_thread(&attributes);
1003a04b749SJérôme Duval	if (id < 0)
101bafa7591SJérôme Duval		free(thread);
1023a04b749SJérôme Duval	else
1033a04b749SJérôme Duval		thread->id = id;
1043a04b749SJérôme Duval	return id;
105712ec3d7SAxel Dörfler}
106712ec3d7SAxel Dörfler
107712ec3d7SAxel Dörfler
108712ec3d7SAxel Dörflerstatus_t
109712ec3d7SAxel Dörflerkill_thread(thread_id thread)
110712ec3d7SAxel Dörfler{
1113dbf98a5SAxel Dörfler	return _kern_kill_thread(thread);
112712ec3d7SAxel Dörfler}
113712ec3d7SAxel Dörfler
114712ec3d7SAxel Dörfler
115712ec3d7SAxel Dörflerstatus_t
116712ec3d7SAxel Dörflerresume_thread(thread_id thread)
117712ec3d7SAxel Dörfler{
1183dbf98a5SAxel Dörfler	return _kern_resume_thread(thread);
119712ec3d7SAxel Dörfler}
120712ec3d7SAxel Dörfler
121712ec3d7SAxel Dörfler
122712ec3d7SAxel Dörflerstatus_t
123712ec3d7SAxel Dörflersuspend_thread(thread_id thread)
124712ec3d7SAxel Dörfler{
1253dbf98a5SAxel Dörfler	return _kern_suspend_thread(thread);
126712ec3d7SAxel Dörfler}
127712ec3d7SAxel Dörfler
128712ec3d7SAxel Dörfler
129712ec3d7SAxel Dörflerstatus_t
130712ec3d7SAxel Dörflerrename_thread(thread_id thread, const char *name)
131712ec3d7SAxel Dörfler{
1320865e4b2SAxel Dörfler	return _kern_rename_thread(thread, name);
133712ec3d7SAxel Dörfler}
134712ec3d7SAxel Dörfler
135712ec3d7SAxel Dörfler
136712ec3d7SAxel Dörflerstatus_t
137712ec3d7SAxel Dörflerset_thread_priority(thread_id thread, int32 priority)
138712ec3d7SAxel Dörfler{
1393dbf98a5SAxel Dörfler	return _kern_set_thread_priority(thread, priority);
140712ec3d7SAxel Dörfler}
141712ec3d7SAxel Dörfler
142712ec3d7SAxel Dörfler
143712ec3d7SAxel Dörflervoid
144712ec3d7SAxel Dörflerexit_thread(status_t status)
145712ec3d7SAxel Dörfler{
14635c16bd3SAdrien Destugues	_thread_do_exit_work();
1472f9720f0SAxel Dörfler	_kern_exit_thread(status);
148712ec3d7SAxel Dörfler}
149712ec3d7SAxel Dörfler
150712ec3d7SAxel Dörfler
151712ec3d7SAxel Dörflerstatus_t
1523dbf98a5SAxel Dörflerwait_for_thread(thread_id thread, status_t *_returnCode)
153712ec3d7SAxel Dörfler{
1543dbf98a5SAxel Dörfler	return _kern_wait_for_thread(thread, _returnCode);
155712ec3d7SAxel Dörfler}
156712ec3d7SAxel Dörfler
157712ec3d7SAxel Dörfler
1588120de45SAxel Dörflerstatus_t
1598120de45SAxel Dörfleron_exit_thread(void (*callback)(void *), void *data)
1608120de45SAxel Dörfler{
1618120de45SAxel Dörfler	callback_node **head = (callback_node **)tls_address(TLS_ON_EXIT_THREAD_SLOT);
1628120de45SAxel Dörfler
1638120de45SAxel Dörfler	callback_node *node = malloc(sizeof(callback_node));
1648120de45SAxel Dörfler	if (node == NULL)
1658120de45SAxel Dörfler		return B_NO_MEMORY;
1668120de45SAxel Dörfler
1678120de45SAxel Dörfler	node->function = callback;
1688120de45SAxel Dörfler	node->argument = data;
1698120de45SAxel Dörfler
1708120de45SAxel Dörfler	// add this node to the list
1718120de45SAxel Dörfler	node->next = *head;
1728120de45SAxel Dörfler	*head = node;
1738120de45SAxel Dörfler
1748120de45SAxel Dörfler	return B_OK;
175712ec3d7SAxel Dörfler}
176712ec3d7SAxel Dörfler
177712ec3d7SAxel Dörfler
178712ec3d7SAxel Dörflerstatus_t
179712ec3d7SAxel Dörfler_get_thread_info(thread_id thread, thread_info *info, size_t size)
180712ec3d7SAxel Dörfler{
1813dbf98a5SAxel Dörfler	if (info == NULL || size != sizeof(thread_info))
1823dbf98a5SAxel Dörfler		return B_BAD_VALUE;
1833dbf98a5SAxel Dörfler
1843dbf98a5SAxel Dörfler	return _kern_get_thread_info(thread, info);
185712ec3d7SAxel Dörfler}
186712ec3d7SAxel Dörfler
187712ec3d7SAxel Dörfler
188712ec3d7SAxel Dörflerstatus_t
189712ec3d7SAxel Dörfler_get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size)
190712ec3d7SAxel Dörfler{
1913dbf98a5SAxel Dörfler	if (info == NULL || size != sizeof(thread_info))
1923dbf98a5SAxel Dörfler		return B_BAD_VALUE;
1933dbf98a5SAxel Dörfler
1943dbf98a5SAxel Dörfler	return _kern_get_next_thread_info(team, cookie, info);
195712ec3d7SAxel Dörfler}
196712ec3d7SAxel Dörfler
197712ec3d7SAxel Dörfler
198712ec3d7SAxel Dörflerstatus_t
199712ec3d7SAxel Dörflersend_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
200712ec3d7SAxel Dörfler{
2013dbf98a5SAxel Dörfler	return _kern_send_data(thread, code, buffer, bufferSize);
202712ec3d7SAxel Dörfler}
203712ec3d7SAxel Dörfler
204712ec3d7SAxel Dörfler
205183dee22SAxel Dörflerint32
2063dbf98a5SAxel Dörflerreceive_data(thread_id *_sender, void *buffer, size_t bufferSize)
207712ec3d7SAxel Dörfler{
2083dbf98a5SAxel Dörfler	return _kern_receive_data(_sender, buffer, bufferSize);
209712ec3d7SAxel Dörfler}
210712ec3d7SAxel Dörfler
211712ec3d7SAxel Dörfler
212712ec3d7SAxel Dörflerbool
213712ec3d7SAxel Dörflerhas_data(thread_id thread)
214712ec3d7SAxel Dörfler{
2153dbf98a5SAxel Dörfler	return _kern_has_data(thread);
216712ec3d7SAxel Dörfler}
2173dbf98a5SAxel Dörfler
218712ec3d7SAxel Dörfler
219712ec3d7SAxel Dörflerstatus_t
2204b2d22c0SAxel Dörflersnooze_etc(bigtime_t timeout, int timeBase, uint32 flags)
221712ec3d7SAxel Dörfler{
22224df6592SIngo Weinhold	return _kern_snooze_etc(timeout, timeBase, flags, NULL);
223712ec3d7SAxel Dörfler}
224712ec3d7SAxel Dörfler
225712ec3d7SAxel Dörfler
226712ec3d7SAxel Dörflerstatus_t
2274b2d22c0SAxel Dörflersnooze(bigtime_t timeout)
228712ec3d7SAxel Dörfler{
22924df6592SIngo Weinhold	return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT,
23024df6592SIngo Weinhold		NULL);
2314b2d22c0SAxel Dörfler}
2324b2d22c0SAxel Dörfler
2334b2d22c0SAxel Dörfler
2344b2d22c0SAxel Dörflerstatus_t
2354b2d22c0SAxel Dörflersnooze_until(bigtime_t timeout, int timeBase)
2364b2d22c0SAxel Dörfler{
23724df6592SIngo Weinhold	return _kern_snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT, NULL);
238712ec3d7SAxel Dörfler}
239712ec3d7SAxel Dörfler
240