1 /* 2 * Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 #ifndef _THREAD_H 9 #define _THREAD_H 10 11 12 #include <OS.h> 13 #include <thread_types.h> 14 #include <arch/thread.h> 15 16 // For the thread blocking inline functions only. 17 #include <kscheduler.h> 18 #include <ksignal.h> 19 20 21 struct kernel_args; 22 struct select_info; 23 struct thread_creation_attributes; 24 25 26 #ifdef __cplusplus 27 extern "C" { 28 #endif 29 30 void thread_enqueue(struct thread *t, struct thread_queue *q); 31 struct thread *thread_lookat_queue(struct thread_queue *q); 32 struct thread *thread_dequeue(struct thread_queue *q); 33 struct thread *thread_dequeue_id(struct thread_queue *q, thread_id id); 34 35 void thread_at_kernel_entry(bigtime_t now); 36 // called when the thread enters the kernel on behalf of the thread 37 void thread_at_kernel_exit(void); 38 void thread_at_kernel_exit_no_signals(void); 39 void thread_reset_for_exec(void); 40 41 status_t thread_init(struct kernel_args *args); 42 status_t thread_preboot_init_percpu(struct kernel_args *args, int32 cpuNum); 43 void thread_yield(bool force); 44 void thread_exit(void); 45 46 int32 thread_max_threads(void); 47 int32 thread_used_threads(void); 48 49 #define thread_get_current_thread arch_thread_get_current_thread 50 51 struct thread *thread_get_thread_struct(thread_id id); 52 struct thread *thread_get_thread_struct_locked(thread_id id); 53 54 static thread_id thread_get_current_thread_id(void); 55 static inline thread_id 56 thread_get_current_thread_id(void) 57 { 58 struct thread *thread = thread_get_current_thread(); 59 return thread ? thread->id : 0; 60 } 61 62 static inline bool 63 thread_is_idle_thread(struct thread *thread) 64 { 65 return thread->entry == NULL; 66 } 67 68 thread_id allocate_thread_id(void); 69 thread_id peek_next_thread_id(void); 70 71 thread_id spawn_kernel_thread_etc(thread_func, const char *name, int32 priority, 72 void *args, team_id team, thread_id threadID); 73 status_t wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, 74 status_t *_returnCode); 75 76 status_t select_thread(int32 object, struct select_info *info, bool kernel); 77 status_t deselect_thread(int32 object, struct select_info *info, bool kernel); 78 79 #define syscall_64_bit_return_value() arch_syscall_64_bit_return_value() 80 81 status_t thread_block(); 82 status_t thread_block_with_timeout(uint32 timeoutFlags, bigtime_t timeout); 83 status_t thread_block_with_timeout_locked(uint32 timeoutFlags, 84 bigtime_t timeout); 85 bool thread_unblock(status_t threadID, status_t status); 86 87 // used in syscalls.c 88 status_t _user_set_thread_priority(thread_id thread, int32 newPriority); 89 status_t _user_rename_thread(thread_id thread, const char *name); 90 status_t _user_suspend_thread(thread_id thread); 91 status_t _user_resume_thread(thread_id thread); 92 status_t _user_rename_thread(thread_id thread, const char *name); 93 thread_id _user_spawn_thread(struct thread_creation_attributes* attributes); 94 status_t _user_wait_for_thread(thread_id id, status_t *_returnCode); 95 status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags); 96 status_t _user_kill_thread(thread_id thread); 97 void _user_thread_yield(void); 98 void _user_exit_thread(status_t return_value); 99 bool _user_has_data(thread_id thread); 100 status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size); 101 status_t _user_receive_data(thread_id *_sender, void *buffer, size_t buffer_size); 102 thread_id _user_find_thread(const char *name); 103 status_t _user_get_thread_info(thread_id id, thread_info *info); 104 status_t _user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info); 105 106 status_t _user_block_thread(uint32 flags, bigtime_t timeout); 107 status_t _user_unblock_thread(thread_id thread, status_t status); 108 status_t _user_unblock_threads(thread_id* threads, uint32 count, 109 status_t status); 110 111 // ToDo: these don't belong here 112 struct rlimit; 113 int _user_getrlimit(int resource, struct rlimit * rlp); 114 int _user_setrlimit(int resource, const struct rlimit * rlp); 115 116 #ifdef __cplusplus 117 } 118 #endif 119 120 121 /*! 122 \a thread must be the current thread. 123 Thread lock can be, but doesn't need to be held. 124 */ 125 static inline bool 126 thread_is_interrupted(struct thread* thread, uint32 flags) 127 { 128 return ((flags & B_CAN_INTERRUPT) 129 && (thread->sig_pending & ~thread->sig_block_mask) != 0) 130 || ((flags & B_KILL_CAN_INTERRUPT) 131 && (thread->sig_pending & KILL_SIGNALS)); 132 } 133 134 135 static inline bool 136 thread_is_blocked(struct thread* thread) 137 { 138 return thread->wait.status == 1; 139 } 140 141 142 /*! 143 \a thread must be the current thread. 144 Thread lock can be, but doesn't need to be locked. 145 */ 146 static inline void 147 thread_prepare_to_block(struct thread* thread, uint32 flags, uint32 type, 148 const void* object) 149 { 150 thread->wait.flags = flags; 151 thread->wait.type = type; 152 thread->wait.object = object; 153 atomic_set(&thread->wait.status, 1); 154 // Set status last to guarantee that the other fields are initialized 155 // when a thread is waiting. 156 } 157 158 159 static inline status_t 160 thread_block_locked(struct thread* thread) 161 { 162 if (thread->wait.status == 1) { 163 // check for signals, if interruptable 164 if (thread_is_interrupted(thread, thread->wait.flags)) { 165 thread->wait.status = B_INTERRUPTED; 166 } else { 167 thread->next_state = B_THREAD_WAITING; 168 scheduler_reschedule(); 169 } 170 } 171 172 return thread->wait.status; 173 } 174 175 176 static inline bool 177 thread_unblock_locked(struct thread* thread, status_t status) 178 { 179 if (atomic_test_and_set(&thread->wait.status, status, 1) != 1) 180 return false; 181 182 // wake up the thread, if it is sleeping 183 if (thread->state == B_THREAD_WAITING) 184 scheduler_enqueue_in_run_queue(thread); 185 186 return true; 187 } 188 189 190 static inline status_t 191 thread_interrupt(struct thread* thread, bool kill) 192 { 193 if ((thread->wait.flags & B_CAN_INTERRUPT) != 0 194 || (kill && (thread->wait.flags & B_KILL_CAN_INTERRUPT) != 0)) { 195 thread_unblock_locked(thread, B_INTERRUPTED); 196 return B_OK; 197 } 198 199 return B_NOT_ALLOWED; 200 } 201 202 203 #endif /* _THREAD_H */ 204