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