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