|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2004,2005 David Decotigny 001 /* Copyright (C) 2004,2005 David Decotigny 002 002 003 This program is free software; you can redi 003 This program is free software; you can redistribute it and/or 004 modify it under the terms of the GNU Genera 004 modify it under the terms of the GNU General Public License 005 as published by the Free Software Foundatio 005 as published by the Free Software Foundation; either version 2 006 of the License, or (at your option) any lat 006 of the License, or (at your option) any later version. 007 007 008 This program is distributed in the hope tha 008 This program is distributed in the hope that it will be useful, 009 but WITHOUT ANY WARRANTY; without even the 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 011 GNU General Public License for more details 011 GNU General Public License for more details. 012 012 013 You should have received a copy of the GNU 013 You should have received a copy of the GNU General Public License 014 along with this program; if not, write to t 014 along with this program; if not, write to the Free Software 015 Foundation, Inc., 59 Temple Place - Suite 3 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 016 USA. 016 USA. 017 */ 017 */ 018 #ifndef _SOS_THREAD_H_ 018 #ifndef _SOS_THREAD_H_ 019 #define _SOS_THREAD_H_ 019 #define _SOS_THREAD_H_ 020 020 021 /** 021 /** 022 * @file thread.h 022 * @file thread.h 023 * 023 * 024 * SOS Thread management API 024 * SOS Thread management API 025 */ 025 */ 026 026 027 #include <sos/errno.h> 027 #include <sos/errno.h> 028 028 029 /* Forward declaration */ 029 /* Forward declaration */ 030 struct sos_thread; 030 struct sos_thread; 031 031 032 #include <hwcore/cpu_context.h> 032 #include <hwcore/cpu_context.h> 033 #include <sos/sched.h> 033 #include <sos/sched.h> 034 #include <sos/kwaitq.h> 034 #include <sos/kwaitq.h> 035 #include <sos/time.h> 035 #include <sos/time.h> 036 #include <sos/process.h> << 037 036 038 /** 037 /** 039 * The possible states of a valid thread 038 * The possible states of a valid thread 040 */ 039 */ 041 typedef enum { SOS_THR_CREATED, /**< Thread cr 040 typedef enum { SOS_THR_CREATED, /**< Thread created, not fully initialized */ 042 SOS_THR_READY, /**< Thread fu 041 SOS_THR_READY, /**< Thread fully initialized or 043 waiting f 042 waiting for CPU after having been 044 blocked o 043 blocked or preempted */ 045 SOS_THR_RUNNING, /**< Thread cu 044 SOS_THR_RUNNING, /**< Thread currently running on CPU */ 046 SOS_THR_BLOCKED, /**< Thread wa 045 SOS_THR_BLOCKED, /**< Thread waiting for I/O (+ in at LEAST 047 one kwait 046 one kwaitq) and/or sleeping (+ in NO 048 kwaitq) * 047 kwaitq) */ 049 SOS_THR_ZOMBIE, /**< Thread te 048 SOS_THR_ZOMBIE, /**< Thread terminated execution, waiting to 050 be delete 049 be deleted by kernel */ 051 } sos_thread_state_t; 050 } sos_thread_state_t; 052 051 053 052 054 /** 053 /** 055 * TCB (Thread Control Block): structure descr 054 * TCB (Thread Control Block): structure describing a thread. Don't 056 * access these fields directly: prefer using 055 * access these fields directly: prefer using the accessor functions 057 * below. 056 * below. 058 */ 057 */ 059 struct sos_thread 058 struct sos_thread 060 { 059 { 061 #define SOS_THR_MAX_NAMELEN 32 060 #define SOS_THR_MAX_NAMELEN 32 062 char name[SOS_THR_MAX_NAMELEN]; 061 char name[SOS_THR_MAX_NAMELEN]; 063 062 064 sos_thread_state_t state; 063 sos_thread_state_t state; 065 sos_sched_priority_t priority; << 066 064 067 /** 065 /** 068 * The hardware context of the thread. 066 * The hardware context of the thread. 069 * 067 * 070 * It will reflect the CPU state of the thre 068 * It will reflect the CPU state of the thread: 071 * - From an interrupt handler: the state o 069 * - From an interrupt handler: the state of the thread at the time 072 * of the OUTERMOST irq. An IRQ is not al 070 * of the OUTERMOST irq. An IRQ is not allowed to make context 073 * switches, so this context will remain 071 * switches, so this context will remain valid from the begining of 074 * the outermost IRQ handler to the end o 072 * the outermost IRQ handler to the end of it, no matter if there 075 * are other IRQ handlers nesting in one 073 * are other IRQ handlers nesting in one another. You may safely 076 * use it from IRQ handlers to query the 074 * use it from IRQ handlers to query the state of the interrupted 077 * thread, no matter if there has been ot 075 * thread, no matter if there has been other IRQ handlers 078 * executing meanwhile. 076 * executing meanwhile. 079 * - From normal kernel code, exceptions an 077 * - From normal kernel code, exceptions and syscall: the state of 080 * the thread the last time there was a c 078 * the thread the last time there was a context switch from this 081 * thread to another one. Thus this field 079 * thread to another one. Thus this field WON'T reflect the 082 * current's thread cpu_state in these ca 080 * current's thread cpu_state in these cases. So, in these cases, 083 * simply DO NOT USE IT outside thread.c 081 * simply DO NOT USE IT outside thread.c ! Note: for syscall and 084 * exception handlers, the VALID state of 082 * exception handlers, the VALID state of the interrupted thread is 085 * passed as an argument to the handlers. 083 * passed as an argument to the handlers. 086 */ 084 */ 087 struct sos_cpu_state *cpu_state; 085 struct sos_cpu_state *cpu_state; 088 086 089 /* Kernel stack parameters */ 087 /* Kernel stack parameters */ 090 sos_vaddr_t kernel_stack_base_addr; 088 sos_vaddr_t kernel_stack_base_addr; 091 sos_size_t kernel_stack_size; 089 sos_size_t kernel_stack_size; 092 090 093 /* Process this thread belongs to. Always NU << 094 thread */ << 095 struct sos_process *process; << 096 << 097 /** << 098 * Address space currently "squatted" by the << 099 * active when the thread was interrupted/pr << 100 * configuration expected before the cpu_sta << 101 * restored on CPU. << 102 * - For kernel threads: should normally b << 103 * thread will squat the current mm_cont << 104 * MMU. Might be NON NULL when a kernel << 105 * process to manipulate its address spa << 106 * - For user threads: should normally be << 107 * - in user mode: the thread->process << 108 * set on MMU. squatted_mm_context i << 109 * situation, meaning that the threa << 110 * process-space as expected << 111 * - in kernel mode: NULL means that w << 112 * mm_context currently set on MMU, << 113 * mm_context of another process. Th << 114 * thread in kernel mode normally on << 115 * space. BTW, this limits the numbe << 116 * there are exceptions where this s << 117 * NOT be NULL. One is the copy_from << 118 * force the effective mm_context so << 119 * (re)configured upon every context << 120 * the squatted_mm_context. Another << 121 * thread creates the address space << 122 * which case the parent thread migh << 123 * switch to the child's process spa << 124 * << 125 * This is the SOS implementation of the Lin << 126 * address-space loaning. << 127 */ << 128 struct sos_mm_context *squatted_mm_context; << 129 << 130 /* Data specific to each state */ 091 /* Data specific to each state */ 131 union 092 union 132 { 093 { 133 struct 094 struct 134 { 095 { 135 struct sos_sched_queue *rdy_queue; << 136 struct sos_thread *rdy_prev, *rdy_ne 096 struct sos_thread *rdy_prev, *rdy_next; 137 } ready; 097 } ready; 138 << 139 struct << 140 { << 141 struct sos_time user_time_spent_in_slice << 142 } running; << 143 }; /* Anonymous union (gcc extenion) */ 098 }; /* Anonymous union (gcc extenion) */ 144 099 145 100 146 /* 101 /* 147 * Data used by the kwaitq subsystem: list o 102 * Data used by the kwaitq subsystem: list of kwaitqueues the thread 148 * is waiting for. 103 * is waiting for. 149 * 104 * 150 * @note: a RUNNING or READY thread might be 105 * @note: a RUNNING or READY thread might be in one or more 151 * waitqueues ! The only property we have is 106 * waitqueues ! The only property we have is that, among these 152 * waitqueues (if any), _at least_ one has w 107 * waitqueues (if any), _at least_ one has woken the thread. 153 */ 108 */ 154 struct sos_kwaitq_entry *kwaitq_list; 109 struct sos_kwaitq_entry *kwaitq_list; 155 110 156 111 157 /** 112 /** 158 * Some statistics << 159 */ << 160 struct rusage << 161 { << 162 /* Updated by sched.c */ << 163 struct sos_time ru_utime; /* Time spent in << 164 struct sos_time ru_stime; /* Time spent in << 165 } rusage; << 166 << 167 << 168 /** << 169 * Chaining pointers for the list of threads << 170 */ << 171 struct sos_thread *prev_in_process, *next_in << 172 << 173 << 174 /** << 175 * Chaining pointers for global ("gbl") list 113 * Chaining pointers for global ("gbl") list of threads (debug) 176 */ 114 */ 177 struct sos_thread *gbl_prev, *gbl_next; 115 struct sos_thread *gbl_prev, *gbl_next; 178 }; 116 }; 179 117 180 118 181 /** 119 /** 182 * Definition of the function executed by a ke 120 * Definition of the function executed by a kernel thread 183 */ 121 */ 184 typedef void (*sos_kernel_thread_start_routine 122 typedef void (*sos_kernel_thread_start_routine_t)(void *arg); 185 123 186 124 187 /** 125 /** 188 * Initialize the subsystem responsible for th 126 * Initialize the subsystem responsible for thread management 189 * 127 * 190 * Initialize the primary kernel thread so tha 128 * Initialize the primary kernel thread so that it can be handled the 191 * same way as an ordinary thread created by s 129 * same way as an ordinary thread created by sos_thread_create(). 192 */ 130 */ 193 sos_ret_t sos_thread_subsystem_setup(sos_vaddr 131 sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr, 194 sos_size_ 132 sos_size_t init_thread_stack_size); 195 133 196 134 197 /** 135 /** 198 * Create a new kernel thread 136 * Create a new kernel thread 199 */ 137 */ 200 struct sos_thread * 138 struct sos_thread * 201 sos_create_kernel_thread(const char *name, 139 sos_create_kernel_thread(const char *name, 202 sos_kernel_thread_sta 140 sos_kernel_thread_start_routine_t start_func, 203 void *start_arg, !! 141 void *start_arg); 204 sos_sched_priority_t << 205 << 206 << 207 /** << 208 * Create a new user thread << 209 */ << 210 struct sos_thread * << 211 sos_create_user_thread(const char *name, << 212 struct sos_process *pro << 213 sos_uaddr_t user_initia << 214 sos_ui32_t user_start_ << 215 sos_ui32_t user_start_ << 216 sos_uaddr_t user_initia << 217 sos_sched_priority_t pr << 218 142 219 143 220 /** 144 /** 221 * Terminate the execution of the current thre 145 * Terminate the execution of the current thread. For kernel threads, 222 * it is called by default when the start rout 146 * it is called by default when the start routine returns. 223 */ 147 */ 224 void sos_thread_exit() __attribute__((noreturn 148 void sos_thread_exit() __attribute__((noreturn)); 225 149 226 150 227 /** 151 /** 228 * Get the identifier of the thread currently 152 * Get the identifier of the thread currently running on CPU. Trivial 229 * function. 153 * function. 230 */ 154 */ 231 struct sos_thread *sos_thread_get_current(); 155 struct sos_thread *sos_thread_get_current(); 232 156 233 157 234 /** 158 /** 235 * If thr == NULL, set the priority of the cur << 236 * function. << 237 * << 238 * @note NOT protected against interrupts << 239 */ << 240 sos_sched_priority_t sos_thread_get_priority(s << 241 << 242 << 243 /** << 244 * If thr == NULL, get the state of the curren 159 * If thr == NULL, get the state of the current thread. Trivial 245 * function. 160 * function. 246 * 161 * 247 * @note NOT protected against interrupts 162 * @note NOT protected against interrupts 248 */ 163 */ 249 sos_thread_state_t sos_thread_get_state(struct 164 sos_thread_state_t sos_thread_get_state(struct sos_thread *thr); 250 165 251 166 252 /** 167 /** 253 * If thr == NULL, set the priority of the cur << 254 * << 255 * @note NO context-switch ever occurs in this << 256 */ << 257 sos_ret_t sos_thread_set_priority(struct sos_t << 258 sos_sched_pr << 259 << 260 << 261 /** << 262 * Yield CPU to another ready thread. 168 * Yield CPU to another ready thread. 263 * 169 * 264 * @note This is a BLOCKING FUNCTION 170 * @note This is a BLOCKING FUNCTION 265 */ 171 */ 266 sos_ret_t sos_thread_yield(); 172 sos_ret_t sos_thread_yield(); 267 173 268 174 269 /** 175 /** 270 * Release the CPU for (at least) the given de 176 * Release the CPU for (at least) the given delay. 271 * 177 * 272 * @param delay The delay to wait for. If dela 178 * @param delay The delay to wait for. If delay == NULL then wait 273 * forever that any event occurs. 179 * forever that any event occurs. 274 * 180 * 275 * @return SOS_OK when delay expired (and dela 181 * @return SOS_OK when delay expired (and delay is reset to zero), 276 * -SOS_EINTR otherwise (and delay contains th 182 * -SOS_EINTR otherwise (and delay contains the amount of time 277 * remaining). 183 * remaining). 278 * 184 * 279 * @note This is a BLOCKING FUNCTION 185 * @note This is a BLOCKING FUNCTION 280 */ 186 */ 281 sos_ret_t sos_thread_sleep(/* in/out */struct 187 sos_ret_t sos_thread_sleep(/* in/out */struct sos_time *delay); 282 188 283 189 284 /** 190 /** 285 * Mark the given thread as READY (if not alre 191 * Mark the given thread as READY (if not already ready) even if it is 286 * blocked in a kwaitq or in a sleep ! As a re 192 * blocked in a kwaitq or in a sleep ! As a result, the interrupted 287 * kwaitq/sleep function call of the thread wi 193 * kwaitq/sleep function call of the thread will return with 288 * -SOS_EINTR. 194 * -SOS_EINTR. 289 * 195 * 290 * @return -SOS_EINVAL if thread does not exis 196 * @return -SOS_EINVAL if thread does not exist, or -SOS_EFATAL if 291 * marked ZOMBIE. 197 * marked ZOMBIE. 292 * 198 * 293 * @note As a result, the semaphore/mutex/cond 199 * @note As a result, the semaphore/mutex/conditions/... functions 294 * return values SHOULD ALWAYS be checked ! If 200 * return values SHOULD ALWAYS be checked ! If they are != SOS_OK, 295 * then the caller should consider that the re 201 * then the caller should consider that the resource is not aquired 296 * because somebody woke the thread by some wa 202 * because somebody woke the thread by some way. 297 */ 203 */ 298 sos_ret_t sos_thread_force_unblock(struct sos_ 204 sos_ret_t sos_thread_force_unblock(struct sos_thread *thread); 299 << 300 /** << 301 * Dump the backtrace of the current thread to << 302 */ << 303 void sos_thread_dump_backtrace(sos_bool_t on_c << 304 sos_bool_t on_b << 305 << 306 << 307 /* ******************************************* << 308 * Restricted functions << 309 */ << 310 << 311 << 312 /** << 313 * Restricted function to change the current m << 314 * squatted_mm_context of the current thread i << 315 * in this context << 316 * << 317 * @param mm_ctxt The mm_ctxt to restore. Mi << 318 * - for a Kernel thread: the current MMU c << 319 * modified. The address space to use is << 320 * space, user space might change due to << 321 * processes << 322 * - for a User thread in kernel mode: same << 323 * - when a User thread will go back in use << 324 * be reconfigured to match the mm_contex << 325 * process << 326 * << 327 * @note A non NULL parameter is allowed only << 328 * squatted_mm_context is not already set. A N << 329 * only if the squatted_mm_context was already << 330 * << 331 * @note The use of this function is RESERVED << 332 * and the copy_from/to_user functions << 333 */ << 334 sos_ret_t << 335 sos_thread_change_current_mm_context(struct so << 336 << 337 << 338 /** << 339 * Restricted callback called when a syscall g << 340 * to reconfigure the MMU to match that of the << 341 * process MMU context. << 342 * << 343 * @note The use of this function is RESERVED << 344 */ << 345 void sos_thread_prepare_syscall_switch_back(st << 346 << 347 << 348 /** << 349 * Restricted callback called when an exceptio << 350 * the interrupted thread to reconfigure the M << 351 * current thread's process MMU context. << 352 * << 353 * @note The use of this function is RESERVED << 354 */ << 355 void sos_thread_prepare_exception_switch_back( << 356 << 357 << 358 /** << 359 * Restricted callback called when an IRQ is e << 360 * NOT already servicing any other IRQ (ie the << 361 * is entered). This callback simply updates t << 362 * that IRQ handlers always know the state of << 363 * even if they are imbricated in other IRQ ha << 364 * << 365 * @note The use of this function is RESERVED << 366 */ << 367 void << 368 sos_thread_prepare_irq_servicing(struct sos_cp << 369 << 370 << 371 /** << 372 * Restricted callback called when the outermo << 373 * to select the thread to return to. This cal << 374 * - preemption of user threads in user mode << 375 * - non-preemption of user threads in kerne << 376 * is restored on CPU "as is") << 377 * - non-preemption of kernel threads (same << 378 * The MMU is reconfigured correctly to match << 379 * selected thread. << 380 * << 381 * @return The CPU context of the thread to re << 382 * << 383 * @note The use of this function is RESERVED << 384 */ << 385 struct sos_cpu_state * << 386 sos_thread_prepare_irq_switch_back(void); << 387 205 388 206 389 #endif /* _SOS_THREAD_H_ */ 207 #endif /* _SOS_THREAD_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |