xref: /haiku/src/system/libroot/os/thread.c (revision cfc3fa87da824bdf593eb8b817a83b6376e77935)
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 	tls_set(TLS_ON_EXIT_THREAD_SLOT, NULL);
118 }
119 
120 
121 status_t
122 on_exit_thread(void (*callback)(void *), void *data)
123 {
124 	callback_node **head = (callback_node **)tls_address(TLS_ON_EXIT_THREAD_SLOT);
125 
126 	callback_node *node = malloc(sizeof(callback_node));
127 	if (node == NULL)
128 		return B_NO_MEMORY;
129 
130 	node->function = callback;
131 	node->argument = data;
132 
133 	// add this node to the list
134 	node->next = *head;
135 	*head = node;
136 
137 	return B_OK;
138 }
139 
140 
141 status_t
142 _get_thread_info(thread_id thread, thread_info *info, size_t size)
143 {
144 	if (info == NULL || size != sizeof(thread_info))
145 		return B_BAD_VALUE;
146 
147 	return _kern_get_thread_info(thread, info);
148 }
149 
150 
151 status_t
152 _get_next_thread_info(team_id team, int32 *cookie, thread_info *info, size_t size)
153 {
154 	if (info == NULL || size != sizeof(thread_info))
155 		return B_BAD_VALUE;
156 
157 	return _kern_get_next_thread_info(team, cookie, info);
158 }
159 
160 
161 status_t
162 send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
163 {
164 	return _kern_send_data(thread, code, buffer, bufferSize);
165 }
166 
167 
168 int32
169 receive_data(thread_id *_sender, void *buffer, size_t bufferSize)
170 {
171 	return _kern_receive_data(_sender, buffer, bufferSize);
172 }
173 
174 
175 bool
176 has_data(thread_id thread)
177 {
178 	return _kern_has_data(thread);
179 }
180 
181 
182 status_t
183 snooze_etc(bigtime_t timeout, int timeBase, uint32 flags)
184 {
185 	return _kern_snooze_etc(timeout, timeBase, flags);
186 }
187 
188 
189 status_t
190 snooze(bigtime_t timeout)
191 {
192 	return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT);
193 }
194 
195 
196 status_t
197 snooze_until(bigtime_t timeout, int timeBase)
198 {
199 	return snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT);
200 }
201 
202