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