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