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(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 49 void 50 _thread_do_exit_notification(void) 51 { 52 // empty stub for R5 compatibility 53 } 54 55 56 void 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 80 thread_id 81 spawn_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 108 status_t 109 kill_thread(thread_id thread) 110 { 111 return _kern_kill_thread(thread); 112 } 113 114 115 status_t 116 resume_thread(thread_id thread) 117 { 118 return _kern_resume_thread(thread); 119 } 120 121 122 status_t 123 suspend_thread(thread_id thread) 124 { 125 return _kern_suspend_thread(thread); 126 } 127 128 129 status_t 130 rename_thread(thread_id thread, const char *name) 131 { 132 return _kern_rename_thread(thread, name); 133 } 134 135 136 status_t 137 set_thread_priority(thread_id thread, int32 priority) 138 { 139 return _kern_set_thread_priority(thread, priority); 140 } 141 142 143 void 144 exit_thread(status_t status) 145 { 146 _thread_do_exit_work(); 147 _kern_exit_thread(status); 148 } 149 150 151 status_t 152 wait_for_thread(thread_id thread, status_t *_returnCode) 153 { 154 return _kern_wait_for_thread(thread, _returnCode); 155 } 156 157 158 status_t 159 on_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 178 status_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 188 status_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 198 status_t 199 send_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 205 int32 206 receive_data(thread_id *_sender, void *buffer, size_t bufferSize) 207 { 208 return _kern_receive_data(_sender, buffer, bufferSize); 209 } 210 211 212 bool 213 has_data(thread_id thread) 214 { 215 return _kern_has_data(thread); 216 } 217 218 219 status_t 220 snooze_etc(bigtime_t timeout, int timeBase, uint32 flags) 221 { 222 return _kern_snooze_etc(timeout, timeBase, flags, NULL); 223 } 224 225 226 status_t 227 snooze(bigtime_t timeout) 228 { 229 return _kern_snooze_etc(timeout, B_SYSTEM_TIMEBASE, B_RELATIVE_TIMEOUT, 230 NULL); 231 } 232 233 234 status_t 235 snooze_until(bigtime_t timeout, int timeBase) 236 { 237 return _kern_snooze_etc(timeout, timeBase, B_ABSOLUTE_TIMEOUT, NULL); 238 } 239 240