1/*
2 * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <OS.h>
8
9#include <stdlib.h>
10#include <stdio.h>
11
12#include <libroot_private.h>
13#include <pthread_private.h>
14#include <thread_defs.h>
15#include <tls.h>
16#include <syscalls.h>
17
18
19#undef thread_entry
20	// thread_entry is still defined in OS.h for compatibility reasons
21
22
23typedef struct callback_node {
24	struct callback_node *next;
25	void (*function)(void *);
26	void *argument;
27} callback_node;
28
29
30void _thread_do_exit_work(void);
31void _thread_do_exit_notification(void);
32
33
34static status_t
35thread_entry(void* _entry, void* _thread)
36{
37	thread_func entry = (thread_func)_entry;
38	pthread_thread* thread = (pthread_thread*)_thread;
39	status_t returnCode;
40
41	returnCode = entry(thread->entry_argument);
42
43	_thread_do_exit_work();
44
45	return returnCode;
46}
47
48
49void
50_thread_do_exit_notification(void)
51{
52	// empty stub for R5 compatibility
53}
54
55
56void
57_thread_do_exit_work(void)
58{
59	callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT);
60	callback_node *next;
61
62	while (node != NULL) {
63		next = node->next;
64
65		node->function(node->argument);
66		free(node);
67
68		node = next;
69	}
70
71	tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL);
72
73	__pthread_destroy_thread();
74}
75
76
77// #pragma mark -
78
79
80thread_id
81spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
82{
83	struct thread_creation_attributes attributes;
84	pthread_thread* thread;
85	thread_id id;
86
87	thread = __allocate_pthread(NULL, data);
88	if (thread == NULL)
89		return B_NO_MEMORY;
90
91	_single_threaded = false;
92		// used for I/O locking - BeOS compatibility issue
93
94	__pthread_init_creation_attributes(NULL, thread, &thread_entry, entry,
95		thread, name, &attributes);
96
97	attributes.priority = priority;
98
99	id = _kern_spawn_thread(&attributes);
100	if (id < 0)
101		free(thread);
102	else
103		thread->id = id;
104	return id;
105}
106
107
108status_t
109kill_thread(thread_id thread)
110{
111	return _kern_kill_thread(thread);
112}
113
114
115status_t
116resume_thread(thread_id thread)
117{
118	return _kern_resume_thread(thread);
119}
120
121
122status_t
123suspend_thread(thread_id thread)
124{
125	return _kern_suspend_thread(thread);
126}
127
128
129status_t
130rename_thread(thread_id thread, const char *name)
131{
132	return _kern_rename_thread(thread, name);
133}
134
135
136status_t
137set_thread_priority(thread_id thread, int32 priority)
138{
139	return _kern_set_thread_priority(thread, priority);
140}
141
142
143void
144exit_thread(status_t status)
145{
146	_thread_do_exit_work();
147	_kern_exit_thread(status);
148}
149
150
151status_t
152wait_for_thread(thread_id thread, status_t *_returnCode)
153{
154	return _kern_wait_for_thread(thread, _returnCode);
155}
156
157
158status_t
159on_exit_thread(void (*callback)(void *), void *data)
160{
161	callback_node **head = (callback_node **)tls_address(TLS_ON_EXIT_THREAD_SLOT);
162
163	callback_node *node = malloc(sizeof(callback_node));
164	if (node == NULL)
165		return B_NO_MEMORY;
166
167	node->function = callback;
168	node->argument = data;
169
170	// add this node to the list
171	node->next = *head;
172	*head = node;
173
174	return B_OK;
175}
176
177
178status_t
179_get_thread_info(thread_id thread, thread_info *info, size_t size)
180{
181	if (info == NULL || size != sizeof(thread_info))
182		return B_BAD_VALUE;
183
184	return _kern_get_thread_info(thread, info);
185}
186
187
188status_t
189_get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size)
190{
191	if (info == NULL || size != sizeof(thread_info))
192		return B_BAD_VALUE;
193
194	return _kern_get_next_thread_info(team, cookie, info);
195}
196
197
198status_t
199send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
200{
201	return _kern_send_data(thread, code, buffer, bufferSize);
202}
203
204
205int32
206receive_data(thread_id *_sender, void *buffer, size_t bufferSize)
207{
208	return _kern_receive_data(_sender, buffer, bufferSize);
209}
210
211
212bool
213has_data(thread_id thread)
214{
215	return _kern_has_data(thread);
216}
217
218
219status_t
220snooze_etc(bigtime_t timeout, int timeBase, uint32 flags)
221{
222	return _kern_snooze_etc(timeout, timeBase, flags, NULL);
223}
224
225
226status_t
227snooze(bigtime_t timeout)
228{
229	return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT,
230		NULL);
231}
232
233
234status_t
235snooze_until(bigtime_t timeout, int timeBase)
236{
237	return _kern_snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT, NULL);
238}
239
240