xref: /haiku/src/system/libroot/os/thread.c (revision fef6144999c2fa611f59ee6ffe6dd7999501385c)
1 /*
2  * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
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 "tls.h"
14 #include "syscalls.h"
15 
16 
17 #undef thread_entry
18 	// thread_entry is still defined in OS.h for compatibility reasons
19 
20 
21 typedef struct callback_node {
22 	struct callback_node *next;
23 	void (*function)(void *);
24 	void *argument;
25 } callback_node;
26 
27 
28 void _thread_do_exit_notification(void);
29 
30 
31 static int32
32 thread_entry(thread_func entry, void *data)
33 {
34 	int32 returnCode = entry(data);
35 
36 	_thread_do_exit_notification();
37 
38 	return returnCode;
39 }
40 
41 
42 thread_id
43 spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
44 {
45 	_single_threaded = false;
46 		// used for I/O locking - BeOS compatibility issue
47 
48 	return _kern_spawn_thread(thread_entry, name, priority, entry, data);
49 }
50 
51 
52 status_t
53 kill_thread(thread_id thread)
54 {
55 	return _kern_kill_thread(thread);
56 }
57 
58 
59 status_t
60 resume_thread(thread_id thread)
61 {
62 	return _kern_resume_thread(thread);
63 }
64 
65 
66 status_t
67 suspend_thread(thread_id thread)
68 {
69 	return _kern_suspend_thread(thread);
70 }
71 
72 
73 status_t
74 rename_thread(thread_id thread, const char *name)
75 {
76 	return _kern_rename_thread(thread, name);
77 }
78 
79 
80 status_t
81 set_thread_priority(thread_id thread, int32 priority)
82 {
83 	return _kern_set_thread_priority(thread, priority);
84 }
85 
86 
87 void
88 exit_thread(status_t status)
89 {
90 	_thread_do_exit_notification();
91 	_kern_exit_thread(status);
92 }
93 
94 
95 status_t
96 wait_for_thread(thread_id thread, status_t *_returnCode)
97 {
98 	return _kern_wait_for_thread(thread, _returnCode);
99 }
100 
101 
102 void
103 _thread_do_exit_notification(void)
104 {
105 	callback_node *node = tls_get(TLS_ON_EXIT_THREAD_SLOT);
106 	callback_node *next;
107 
108 	while (node != NULL) {
109 		next = node->next;
110 
111 		node->function(node->argument);
112 		free(node);
113 
114 		node = next;
115 	}
116 }
117 
118 
119 status_t
120 on_exit_thread(void (*callback)(void *), void *data)
121 {
122 	callback_node **head = (callback_node **)tls_address(TLS_ON_EXIT_THREAD_SLOT);
123 
124 	callback_node *node = malloc(sizeof(callback_node));
125 	if (node == NULL)
126 		return B_NO_MEMORY;
127 
128 	node->function = callback;
129 	node->argument = data;
130 
131 	// add this node to the list
132 	node->next = *head;
133 	*head = node;
134 
135 	return B_OK;
136 }
137 
138 
139 status_t
140 _get_thread_info(thread_id thread, thread_info *info, size_t size)
141 {
142 	if (info == NULL || size != sizeof(thread_info))
143 		return B_BAD_VALUE;
144 
145 	return _kern_get_thread_info(thread, info);
146 }
147 
148 
149 status_t
150 _get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size)
151 {
152 	if (info == NULL || size != sizeof(thread_info))
153 		return B_BAD_VALUE;
154 
155 	return _kern_get_next_thread_info(team, cookie, info);
156 }
157 
158 
159 status_t
160 send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
161 {
162 	return _kern_send_data(thread, code, buffer, bufferSize);
163 }
164 
165 
166 int32
167 receive_data(thread_id *_sender, void *buffer, size_t bufferSize)
168 {
169 	return _kern_receive_data(_sender, buffer, bufferSize);
170 }
171 
172 
173 bool
174 has_data(thread_id thread)
175 {
176 	return _kern_has_data(thread);
177 }
178 
179 
180 status_t
181 snooze_etc(bigtime_t timeout, int timeBase, uint32 flags)
182 {
183 	return _kern_snooze_etc(timeout, timeBase, flags);
184 }
185 
186 
187 status_t
188 snooze(bigtime_t timeout)
189 {
190 	return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
191 }
192 
193 
194 status_t
195 snooze_until(bigtime_t timeout, int timeBase)
196 {
197 	return snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT);
198 }
199 
200