thread.c revision 44c0c4d3
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>
1444c0c4d3SPawel Dziepak#include <runtime_loader.h>
156b202f4eSIngo Weinhold#include <thread_defs.h>
166b202f4eSIngo Weinhold#include <tls.h>
176b202f4eSIngo Weinhold#include <syscalls.h>
18712ec3d7SAxel Dörfler
19712ec3d7SAxel Dörfler
208120de45SAxel Dörfler#undef thread_entry
218120de45SAxel Dörfler	// thread_entry is still defined in OS.h for compatibility reasons
228120de45SAxel Dörfler
238120de45SAxel Dörfler
248120de45SAxel Dörflertypedef struct callback_node {
258120de45SAxel Dörfler	struct callback_node *next;
268120de45SAxel Dörfler	void (*function)(void *);
278120de45SAxel Dörfler	void *argument;
288120de45SAxel Dörfler} callback_node;
298120de45SAxel Dörfler
308120de45SAxel Dörfler
31a4248cf5SJérôme Duvalvoid _thread_do_exit_work(void);
32ceee0a32SFrançois Revolvoid _thread_do_exit_notification(void);
338120de45SAxel Dörfler
348120de45SAxel Dörfler
35ecf6b86cSAxel Dörflerstatic status_t
3624df6592SIngo Weinholdthread_entry(void* _entry, void* _thread)
378120de45SAxel Dörfler{
3824df6592SIngo Weinhold	thread_func entry = (thread_func)_entry;
39ecf6b86cSAxel Dörfler	pthread_thread* thread = (pthread_thread*)_thread;
40ecf6b86cSAxel Dörfler	status_t returnCode;
41ecf6b86cSAxel Dörfler
42ecf6b86cSAxel Dörfler	returnCode = entry(thread->entry_argument);
438120de45SAxel Dörfler
44a4248cf5SJérôme Duval	_thread_do_exit_work();
458120de45SAxel Dörfler
468120de45SAxel Dörfler	return returnCode;
478120de45SAxel Dörfler}
488120de45SAxel Dörfler
498120de45SAxel Dörfler
50ecf6b86cSAxel Dörflervoid
51ecf6b86cSAxel Dörfler_thread_do_exit_notification(void)
52a4248cf5SJérôme Duval{
53585a28afSJérôme Duval	// empty stub for R5 compatibility
54a4248cf5SJérôme Duval}
55a4248cf5SJérôme Duval
56a4248cf5SJérôme Duval
57a4248cf5SJérôme Duvalvoid
58a4248cf5SJérôme Duval_thread_do_exit_work(void)
59ecf6b86cSAxel Dörfler{
60ecf6b86cSAxel Dörfler	callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT);
61ecf6b86cSAxel Dörfler	callback_node *next;
62ecf6b86cSAxel Dörfler
63ecf6b86cSAxel Dörfler	while (node != NULL) {
64ecf6b86cSAxel Dörfler		next = node->next;
65ecf6b86cSAxel Dörfler
66ecf6b86cSAxel Dörfler		node->function(node->argument);
67ecf6b86cSAxel Dörfler		free(node);
68ecf6b86cSAxel Dörfler
69ecf6b86cSAxel Dörfler		node = next;
70ecf6b86cSAxel Dörfler	}
71ecf6b86cSAxel Dörfler
72ecf6b86cSAxel Dörfler	tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL);
73ecf6b86cSAxel Dörfler
7444c0c4d3SPawel Dziepak	__gRuntimeLoader->destroy_thread_tls();
7544c0c4d3SPawel Dziepak
76ecf6b86cSAxel Dörfler	__pthread_destroy_thread();
77ecf6b86cSAxel Dörfler}
78ecf6b86cSAxel Dörfler
79ecf6b86cSAxel Dörfler
805d0a1da8SPawel Dziepakvoid
815d0a1da8SPawel Dziepak__set_stack_protection(void)
825d0a1da8SPawel Dziepak{
8307e1875eSPawel Dziepak	if (__gABIVersion < B_HAIKU_ABI_GCC_2_HAIKU) {
845d0a1da8SPawel Dziepak		area_info info;
855d0a1da8SPawel Dziepak		ssize_t cookie = 0;
865d0a1da8SPawel Dziepak
875d0a1da8SPawel Dziepak		while (get_next_area_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) {
885d0a1da8SPawel Dziepak			if ((info.protection & B_STACK_AREA) != 0) {
895d0a1da8SPawel Dziepak				_kern_set_area_protection(info.area,
905d0a1da8SPawel Dziepak					B_READ_AREA | B_WRITE_AREA | B_EXECUTE_AREA | B_STACK_AREA);
915d0a1da8SPawel Dziepak			}
925d0a1da8SPawel Dziepak		}
935d0a1da8SPawel Dziepak	}
945d0a1da8SPawel Dziepak}
955d0a1da8SPawel Dziepak
965d0a1da8SPawel Dziepak
97ecf6b86cSAxel Dörfler// #pragma mark -
98ecf6b86cSAxel Dörfler
99ecf6b86cSAxel Dörfler
100712ec3d7SAxel Dörflerthread_id
1018120de45SAxel Dörflerspawn_thread(thread_func entry, const char *name, int32 priority, void *data)
102712ec3d7SAxel Dörfler{
1034c49f205SIngo Weinhold	struct thread_creation_attributes attributes;
104ecf6b86cSAxel Dörfler	pthread_thread* thread;
10585b2f68bSPhilippe Saint-Pierre	thread_id id;
106ecf6b86cSAxel Dörfler
10724df6592SIngo Weinhold	thread = __allocate_pthread(NULL, data);
108ecf6b86cSAxel Dörfler	if (thread == NULL)
109ecf6b86cSAxel Dörfler		return B_NO_MEMORY;
1104c49f205SIngo Weinhold
1115685273fSAxel Dörfler	_single_threaded = false;
1125685273fSAxel Dörfler		// used for I/O locking - BeOS compatibility issue
1135685273fSAxel Dörfler
11424df6592SIngo Weinhold	__pthread_init_creation_attributes(NULL, thread, &thread_entry, entry,
11524df6592SIngo Weinhold		thread, name, &attributes);
1161bc85a38SJérôme Duval	thread->flags |= THREAD_DETACHED;
11724df6592SIngo Weinhold
1184c49f205SIngo Weinhold	attributes.priority = priority;
1194c49f205SIngo Weinhold
12085b2f68bSPhilippe Saint-Pierre	id = _kern_spawn_thread(&attributes);
1213a04b749SJérôme Duval	if (id < 0)
122bafa7591SJérôme Duval		free(thread);
1235d0a1da8SPawel Dziepak	else {
1243a04b749SJérôme Duval		thread->id = id;
1255d0a1da8SPawel Dziepak		__set_stack_protection();
1265d0a1da8SPawel Dziepak	}
1275d0a1da8SPawel Dziepak
1283a04b749SJérôme Duval	return id;
129712ec3d7SAxel Dörfler}
130712ec3d7SAxel Dörfler
131712ec3d7SAxel Dörfler
132712ec3d7SAxel Dörflerstatus_t
133712ec3d7SAxel Dörflerkill_thread(thread_id thread)
134712ec3d7SAxel Dörfler{
1353dbf98a5SAxel Dörfler	return _kern_kill_thread(thread);
136712ec3d7SAxel Dörfler}
137712ec3d7SAxel Dörfler
138712ec3d7SAxel Dörfler
139712ec3d7SAxel Dörflerstatus_t
140712ec3d7SAxel Dörflerresume_thread(thread_id thread)
141712ec3d7SAxel Dörfler{
1423dbf98a5SAxel Dörfler	return _kern_resume_thread(thread);
143712ec3d7SAxel Dörfler}
144712ec3d7SAxel Dörfler
145712ec3d7SAxel Dörfler
146712ec3d7SAxel Dörflerstatus_t
147712ec3d7SAxel Dörflersuspend_thread(thread_id thread)
148712ec3d7SAxel Dörfler{
1493dbf98a5SAxel Dörfler	return _kern_suspend_thread(thread);
150712ec3d7SAxel Dörfler}
151712ec3d7SAxel Dörfler
152712ec3d7SAxel Dörfler
153712ec3d7SAxel Dörflerstatus_t
154712ec3d7SAxel Dörflerrename_thread(thread_id thread, const char *name)
155712ec3d7SAxel Dörfler{
1560865e4b2SAxel Dörfler	return _kern_rename_thread(thread, name);
157712ec3d7SAxel Dörfler}
158712ec3d7SAxel Dörfler
159712ec3d7SAxel Dörfler
160712ec3d7SAxel Dörflerstatus_t
161712ec3d7SAxel Dörflerset_thread_priority(thread_id thread, int32 priority)
162712ec3d7SAxel Dörfler{
1633dbf98a5SAxel Dörfler	return _kern_set_thread_priority(thread, priority);
164712ec3d7SAxel Dörfler}
165712ec3d7SAxel Dörfler
166712ec3d7SAxel Dörfler
167712ec3d7SAxel Dörflervoid
168712ec3d7SAxel Dörflerexit_thread(status_t status)
169712ec3d7SAxel Dörfler{
17035c16bd3SAdrien Destugues	_thread_do_exit_work();
1712f9720f0SAxel Dörfler	_kern_exit_thread(status);
172712ec3d7SAxel Dörfler}
173712ec3d7SAxel Dörfler
174712ec3d7SAxel Dörfler
175712ec3d7SAxel Dörflerstatus_t
1763dbf98a5SAxel Dörflerwait_for_thread(thread_id thread, status_t *_returnCode)
177712ec3d7SAxel Dörfler{
1783dbf98a5SAxel Dörfler	return _kern_wait_for_thread(thread, _returnCode);
179712ec3d7SAxel Dörfler}
180712ec3d7SAxel Dörfler
181712ec3d7SAxel Dörfler
1828120de45SAxel Dörflerstatus_t
1838120de45SAxel Dörfleron_exit_thread(void (*callback)(void *), void *data)
1848120de45SAxel Dörfler{
1858120de45SAxel Dörfler	callback_node **head = (callback_node **)tls_address(TLS_ON_EXIT_THREAD_SLOT);
1868120de45SAxel Dörfler
1878120de45SAxel Dörfler	callback_node *node = malloc(sizeof(callback_node));
1888120de45SAxel Dörfler	if (node == NULL)
1898120de45SAxel Dörfler		return B_NO_MEMORY;
1908120de45SAxel Dörfler
1918120de45SAxel Dörfler	node->function = callback;
1928120de45SAxel Dörfler	node->argument = data;
1938120de45SAxel Dörfler
1948120de45SAxel Dörfler	// add this node to the list
1958120de45SAxel Dörfler	node->next = *head;
1968120de45SAxel Dörfler	*head = node;
1978120de45SAxel Dörfler
1988120de45SAxel Dörfler	return B_OK;
199712ec3d7SAxel Dörfler}
200712ec3d7SAxel Dörfler
201712ec3d7SAxel Dörfler
202712ec3d7SAxel Dörflerstatus_t
203712ec3d7SAxel Dörfler_get_thread_info(thread_id thread, thread_info *info, size_t size)
204712ec3d7SAxel Dörfler{
2053dbf98a5SAxel Dörfler	if (info == NULL || size != sizeof(thread_info))
2063dbf98a5SAxel Dörfler		return B_BAD_VALUE;
2073dbf98a5SAxel Dörfler
2083dbf98a5SAxel Dörfler	return _kern_get_thread_info(thread, info);
209712ec3d7SAxel Dörfler}
210712ec3d7SAxel Dörfler
211712ec3d7SAxel Dörfler
212712ec3d7SAxel Dörflerstatus_t
213712ec3d7SAxel Dörfler_get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size)
214712ec3d7SAxel Dörfler{
2153dbf98a5SAxel Dörfler	if (info == NULL || size != sizeof(thread_info))
2163dbf98a5SAxel Dörfler		return B_BAD_VALUE;
2173dbf98a5SAxel Dörfler
2183dbf98a5SAxel Dörfler	return _kern_get_next_thread_info(team, cookie, info);
219712ec3d7SAxel Dörfler}
220712ec3d7SAxel Dörfler
221712ec3d7SAxel Dörfler
222712ec3d7SAxel Dörflerstatus_t
223712ec3d7SAxel Dörflersend_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
224712ec3d7SAxel Dörfler{
2253dbf98a5SAxel Dörfler	return _kern_send_data(thread, code, buffer, bufferSize);
226712ec3d7SAxel Dörfler}
227712ec3d7SAxel Dörfler
228712ec3d7SAxel Dörfler
229183dee22SAxel Dörflerint32
2303dbf98a5SAxel Dörflerreceive_data(thread_id *_sender, void *buffer, size_t bufferSize)
231712ec3d7SAxel Dörfler{
2323dbf98a5SAxel Dörfler	return _kern_receive_data(_sender, buffer, bufferSize);
233712ec3d7SAxel Dörfler}
234712ec3d7SAxel Dörfler
235712ec3d7SAxel Dörfler
236712ec3d7SAxel Dörflerbool
237712ec3d7SAxel Dörflerhas_data(thread_id thread)
238712ec3d7SAxel Dörfler{
2393dbf98a5SAxel Dörfler	return _kern_has_data(thread);
240712ec3d7SAxel Dörfler}
2413dbf98a5SAxel Dörfler
242712ec3d7SAxel Dörfler
243712ec3d7SAxel Dörflerstatus_t
2444b2d22c0SAxel Dörflersnooze_etc(bigtime_t timeout, int timeBase, uint32 flags)
245712ec3d7SAxel Dörfler{
24624df6592SIngo Weinhold	return _kern_snooze_etc(timeout, timeBase, flags, NULL);
247712ec3d7SAxel Dörfler}
248712ec3d7SAxel Dörfler
249712ec3d7SAxel Dörfler
250712ec3d7SAxel Dörflerstatus_t
2514b2d22c0SAxel Dörflersnooze(bigtime_t timeout)
252712ec3d7SAxel Dörfler{
25324df6592SIngo Weinhold	return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT,
25424df6592SIngo Weinhold		NULL);
2554b2d22c0SAxel Dörfler}
2564b2d22c0SAxel Dörfler
2574b2d22c0SAxel Dörfler
2584b2d22c0SAxel Dörflerstatus_t
2594b2d22c0SAxel Dörflersnooze_until(bigtime_t timeout, int timeBase)
2604b2d22c0SAxel Dörfler{
26124df6592SIngo Weinhold	return _kern_snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT, NULL);
262712ec3d7SAxel Dörfler}
263