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