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