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