|
[ 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 #include <sos/umem_vmm.h> 036 038 037 /** 039 /** 038 * The possible states of a valid thread 040 * The possible states of a valid thread 039 */ 041 */ 040 typedef enum { SOS_THR_CREATED, /**< Thread cr 042 typedef enum { SOS_THR_CREATED, /**< Thread created, not fully initialized */ 041 SOS_THR_READY, /**< Thread fu 043 SOS_THR_READY, /**< Thread fully initialized or 042 waiting f 044 waiting for CPU after having been 043 blocked o 045 blocked or preempted */ 044 SOS_THR_RUNNING, /**< Thread cu 046 SOS_THR_RUNNING, /**< Thread currently running on CPU */ 045 SOS_THR_BLOCKED, /**< Thread wa 047 SOS_THR_BLOCKED, /**< Thread waiting for I/O (+ in at LEAST 046 one kwait 048 one kwaitq) and/or sleeping (+ in NO 047 kwaitq) * 049 kwaitq) */ 048 SOS_THR_ZOMBIE, /**< Thread te 050 SOS_THR_ZOMBIE, /**< Thread terminated execution, waiting to 049 be delete 051 be deleted by kernel */ 050 } sos_thread_state_t; 052 } sos_thread_state_t; 051 053 052 054 053 /** 055 /** 054 * TCB (Thread Control Block): structure descr 056 * TCB (Thread Control Block): structure describing a thread. Don't 055 * access these fields directly: prefer using 057 * access these fields directly: prefer using the accessor functions 056 * below. 058 * below. 057 */ 059 */ 058 struct sos_thread 060 struct sos_thread 059 { 061 { 060 #define SOS_THR_MAX_NAMELEN 32 062 #define SOS_THR_MAX_NAMELEN 32 061 char name[SOS_THR_MAX_NAMELEN]; 063 char name[SOS_THR_MAX_NAMELEN]; 062 064 063 sos_thread_state_t state; 065 sos_thread_state_t state; >> 066 sos_sched_priority_t priority; 064 067 065 /** 068 /** 066 * The hardware context of the thread. 069 * The hardware context of the thread. 067 * 070 * 068 * It will reflect the CPU state of the thre 071 * It will reflect the CPU state of the thread: 069 * - From an interrupt handler: the state o 072 * - From an interrupt handler: the state of the thread at the time 070 * of the OUTERMOST irq. An IRQ is not al 073 * of the OUTERMOST irq. An IRQ is not allowed to make context 071 * switches, so this context will remain 074 * switches, so this context will remain valid from the begining of 072 * the outermost IRQ handler to the end o 075 * the outermost IRQ handler to the end of it, no matter if there 073 * are other IRQ handlers nesting in one 076 * are other IRQ handlers nesting in one another. You may safely 074 * use it from IRQ handlers to query the 077 * use it from IRQ handlers to query the state of the interrupted 075 * thread, no matter if there has been ot 078 * thread, no matter if there has been other IRQ handlers 076 * executing meanwhile. 079 * executing meanwhile. 077 * - From normal kernel code, exceptions an 080 * - From normal kernel code, exceptions and syscall: the state of 078 * the thread the last time there was a c 081 * the thread the last time there was a context switch from this 079 * thread to another one. Thus this field 082 * thread to another one. Thus this field WON'T reflect the 080 * current's thread cpu_state in these ca 083 * current's thread cpu_state in these cases. So, in these cases, 081 * simply DO NOT USE IT outside thread.c 084 * simply DO NOT USE IT outside thread.c ! Note: for syscall and 082 * exception handlers, the VALID state of 085 * exception handlers, the VALID state of the interrupted thread is 083 * passed as an argument to the handlers. 086 * passed as an argument to the handlers. 084 */ 087 */ 085 struct sos_cpu_state *cpu_state; 088 struct sos_cpu_state *cpu_state; 086 089 087 /* Kernel stack parameters */ 090 /* Kernel stack parameters */ 088 sos_vaddr_t kernel_stack_base_addr; 091 sos_vaddr_t kernel_stack_base_addr; 089 sos_size_t kernel_stack_size; 092 sos_size_t kernel_stack_size; 090 093 >> 094 /* Process this thread belongs to. Always NULL for a kernel >> 095 thread */ >> 096 struct sos_process *process; >> 097 >> 098 /** >> 099 * Address space currently "squatted" by the thread, or used to be >> 100 * active when the thread was interrupted/preempted. This is the MMU >> 101 * configuration expected before the cpu_state of the thread is >> 102 * restored on CPU. >> 103 * - For kernel threads: should normally be NULL, meaning that the >> 104 * thread will squat the current mm_context currently set in the >> 105 * MMU. Might be NON NULL when a kernel thread squats a given >> 106 * process to manipulate its address space. >> 107 * - For user threads: should normally be NULL. More precisely: >> 108 * - in user mode: the thread->process.mm_context is ALWAYS >> 109 * set on MMU. squatted_mm_context is ALWAYS NULL in this >> 110 * situation, meaning that the thread in user mode uses its >> 111 * process-space as expected >> 112 * - in kernel mode: NULL means that we keep on using the >> 113 * mm_context currently set on MMU, which might be the >> 114 * mm_context of another process. This is natural since a >> 115 * thread in kernel mode normally only uses data in kernel >> 116 * space. BTW, this limits the number of TLB flushes. However, >> 117 * there are exceptions where this squatted_mm_context will >> 118 * NOT be NULL. One is the copy_from/to_user API, which can >> 119 * force the effective mm_context so that the MMU will be >> 120 * (re)configured upon every context to the thread to match >> 121 * the squatted_mm_context. Another exception is when a parent >> 122 * thread creates the address space of a child process, in >> 123 * which case the parent thread might temporarilly decide to >> 124 * switch to the child's process space. >> 125 * >> 126 * This is the SOS implementation of the Linux "Lazy TLB" and >> 127 * address-space loaning. >> 128 */ >> 129 struct sos_mm_context *squatted_mm_context; >> 130 091 /* Data specific to each state */ 131 /* Data specific to each state */ 092 union 132 union 093 { 133 { 094 struct 134 struct 095 { 135 { >> 136 struct sos_sched_queue *rdy_queue; 096 struct sos_thread *rdy_prev, *rdy_ne 137 struct sos_thread *rdy_prev, *rdy_next; 097 } ready; 138 } ready; 098 }; /* Anonymous union (gcc extenion) */ 139 }; /* Anonymous union (gcc extenion) */ 099 140 >> 141 struct sos_time user_time_spent_in_slice; >> 142 >> 143 >> 144 /** >> 145 * When a thread in kernel mode is accessing the user space, it may >> 146 * page fault in the usual way only if return_vaddr below is >> 147 * set. This structure holds information regarding what to do when a >> 148 * page fault from kernel into user space could not be resolved. >> 149 * >> 150 * @note the fields below should be considered read-only. @see >> 151 * sos_thread_prepare_user_space_access() and @see >> 152 * sos_thread_end_user_space_access() to modify them. >> 153 */ >> 154 struct >> 155 { >> 156 /** This is the address (in kernel code) to return to when a >> 157 user-space page fault from a kernel-mode thread could not be >> 158 resolved. @see sos_thread_prepare_user_space_access() */ >> 159 sos_vaddr_t return_vaddr; >> 160 >> 161 /** This is the address of the user-space address that caused the >> 162 unresolved page fault (set by the page fault handler) */ >> 163 sos_uaddr_t faulted_uaddr; >> 164 } fixup_uaccess; >> 165 100 166 101 /* 167 /* 102 * Data used by the kwaitq subsystem: list o 168 * Data used by the kwaitq subsystem: list of kwaitqueues the thread 103 * is waiting for. 169 * is waiting for. 104 * 170 * 105 * @note: a RUNNING or READY thread might be 171 * @note: a RUNNING or READY thread might be in one or more 106 * waitqueues ! The only property we have is 172 * waitqueues ! The only property we have is that, among these 107 * waitqueues (if any), _at least_ one has w 173 * waitqueues (if any), _at least_ one has woken the thread. 108 */ 174 */ 109 struct sos_kwaitq_entry *kwaitq_list; 175 struct sos_kwaitq_entry *kwaitq_list; 110 176 111 177 112 /** 178 /** >> 179 * Some statistics >> 180 */ >> 181 struct rusage >> 182 { >> 183 /* Updated by sched.c */ >> 184 struct sos_time ru_utime; /* Time spent in user mode */ >> 185 struct sos_time ru_stime; /* Time spent in kernel mode */ >> 186 } rusage; >> 187 >> 188 >> 189 /** >> 190 * Chaining pointers for the list of threads in the parent process >> 191 */ >> 192 struct sos_thread *prev_in_process, *next_in_process; >> 193 >> 194 >> 195 /** 113 * Chaining pointers for global ("gbl") list 196 * Chaining pointers for global ("gbl") list of threads (debug) 114 */ 197 */ 115 struct sos_thread *gbl_prev, *gbl_next; 198 struct sos_thread *gbl_prev, *gbl_next; 116 }; 199 }; 117 200 118 201 119 /** 202 /** 120 * Definition of the function executed by a ke 203 * Definition of the function executed by a kernel thread 121 */ 204 */ 122 typedef void (*sos_kernel_thread_start_routine 205 typedef void (*sos_kernel_thread_start_routine_t)(void *arg); 123 206 124 207 125 /** 208 /** 126 * Initialize the subsystem responsible for th 209 * Initialize the subsystem responsible for thread management 127 * 210 * 128 * Initialize the primary kernel thread so tha 211 * Initialize the primary kernel thread so that it can be handled the 129 * same way as an ordinary thread created by s 212 * same way as an ordinary thread created by sos_thread_create(). 130 */ 213 */ 131 sos_ret_t sos_thread_subsystem_setup(sos_vaddr 214 sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr, 132 sos_size_ 215 sos_size_t init_thread_stack_size); 133 216 134 217 135 /** 218 /** 136 * Create a new kernel thread 219 * Create a new kernel thread 137 */ 220 */ 138 struct sos_thread * 221 struct sos_thread * 139 sos_create_kernel_thread(const char *name, 222 sos_create_kernel_thread(const char *name, 140 sos_kernel_thread_sta 223 sos_kernel_thread_start_routine_t start_func, 141 void *start_arg); !! 224 void *start_arg, >> 225 sos_sched_priority_t priority); >> 226 >> 227 >> 228 /** >> 229 * Create a new user thread >> 230 */ >> 231 struct sos_thread * >> 232 sos_create_user_thread(const char *name, >> 233 struct sos_process *process, >> 234 sos_uaddr_t user_initial_PC, >> 235 sos_ui32_t user_start_arg1, >> 236 sos_ui32_t user_start_arg2, >> 237 sos_uaddr_t user_initial_SP, >> 238 sos_sched_priority_t priority); >> 239 >> 240 >> 241 /** >> 242 * Create a new user thread, copy of the given user thread with the >> 243 * given user context >> 244 */ >> 245 struct sos_thread * >> 246 sos_duplicate_user_thread(const char *name, >> 247 struct sos_process *process, >> 248 const struct sos_thread * model_thread, >> 249 const struct sos_cpu_state * model_uctxt, >> 250 sos_ui32_t retval); 142 251 143 252 144 /** 253 /** 145 * Terminate the execution of the current thre 254 * Terminate the execution of the current thread. For kernel threads, 146 * it is called by default when the start rout 255 * it is called by default when the start routine returns. 147 */ 256 */ 148 void sos_thread_exit() __attribute__((noreturn !! 257 void sos_thread_exit(void) __attribute__((noreturn)); 149 258 150 259 151 /** 260 /** 152 * Get the identifier of the thread currently 261 * Get the identifier of the thread currently running on CPU. Trivial 153 * function. 262 * function. 154 */ 263 */ 155 struct sos_thread *sos_thread_get_current(); !! 264 struct sos_thread *sos_thread_get_current(void); >> 265 >> 266 >> 267 /** >> 268 * If thr == NULL, set the priority of the current thread. Trivial >> 269 * function. >> 270 * >> 271 * @note NOT protected against interrupts >> 272 */ >> 273 sos_sched_priority_t sos_thread_get_priority(struct sos_thread *thr); 156 274 157 275 158 /** 276 /** 159 * If thr == NULL, get the state of the curren 277 * If thr == NULL, get the state of the current thread. Trivial 160 * function. 278 * function. 161 * 279 * 162 * @note NOT protected against interrupts 280 * @note NOT protected against interrupts 163 */ 281 */ 164 sos_thread_state_t sos_thread_get_state(struct 282 sos_thread_state_t sos_thread_get_state(struct sos_thread *thr); 165 283 166 284 167 /** 285 /** >> 286 * If thr == NULL, set the priority of the current thread >> 287 * >> 288 * @note NO context-switch ever occurs in this function ! >> 289 */ >> 290 sos_ret_t sos_thread_set_priority(struct sos_thread *thr, >> 291 sos_sched_priority_t priority); >> 292 >> 293 >> 294 /** 168 * Yield CPU to another ready thread. 295 * Yield CPU to another ready thread. 169 * 296 * 170 * @note This is a BLOCKING FUNCTION 297 * @note This is a BLOCKING FUNCTION 171 */ 298 */ 172 sos_ret_t sos_thread_yield(); !! 299 sos_ret_t sos_thread_yield(void); 173 300 174 301 175 /** 302 /** 176 * Release the CPU for (at least) the given de 303 * Release the CPU for (at least) the given delay. 177 * 304 * 178 * @param delay The delay to wait for. If dela 305 * @param delay The delay to wait for. If delay == NULL then wait 179 * forever that any event occurs. 306 * forever that any event occurs. 180 * 307 * 181 * @return SOS_OK when delay expired (and dela 308 * @return SOS_OK when delay expired (and delay is reset to zero), 182 * -SOS_EINTR otherwise (and delay contains th 309 * -SOS_EINTR otherwise (and delay contains the amount of time 183 * remaining). 310 * remaining). 184 * 311 * 185 * @note This is a BLOCKING FUNCTION 312 * @note This is a BLOCKING FUNCTION 186 */ 313 */ 187 sos_ret_t sos_thread_sleep(/* in/out */struct 314 sos_ret_t sos_thread_sleep(/* in/out */struct sos_time *delay); 188 315 189 316 190 /** 317 /** 191 * Mark the given thread as READY (if not alre 318 * Mark the given thread as READY (if not already ready) even if it is 192 * blocked in a kwaitq or in a sleep ! As a re 319 * blocked in a kwaitq or in a sleep ! As a result, the interrupted 193 * kwaitq/sleep function call of the thread wi 320 * kwaitq/sleep function call of the thread will return with 194 * -SOS_EINTR. 321 * -SOS_EINTR. 195 * 322 * 196 * @return -SOS_EINVAL if thread does not exis 323 * @return -SOS_EINVAL if thread does not exist, or -SOS_EFATAL if 197 * marked ZOMBIE. 324 * marked ZOMBIE. 198 * 325 * 199 * @note As a result, the semaphore/mutex/cond 326 * @note As a result, the semaphore/mutex/conditions/... functions 200 * return values SHOULD ALWAYS be checked ! If 327 * return values SHOULD ALWAYS be checked ! If they are != SOS_OK, 201 * then the caller should consider that the re 328 * then the caller should consider that the resource is not aquired 202 * because somebody woke the thread by some wa 329 * because somebody woke the thread by some way. 203 */ 330 */ 204 sos_ret_t sos_thread_force_unblock(struct sos_ 331 sos_ret_t sos_thread_force_unblock(struct sos_thread *thread); >> 332 >> 333 /** >> 334 * Dump the backtrace of the current thread to console and/or bochs >> 335 */ >> 336 void sos_thread_dump_backtrace(sos_bool_t on_console, >> 337 sos_bool_t on_bochs); >> 338 >> 339 >> 340 /* ********************************************** >> 341 * Restricted functions >> 342 */ >> 343 >> 344 >> 345 /** >> 346 * Restricted function to indicate that we are to access the given >> 347 * user address space from inside the kernel. >> 348 * >> 349 * @param dest_as The address space we want to access, or NULL to >> 350 * access current thread's address space >> 351 * >> 352 * @param fixup_retvaddr When != 0, then dest_as MUST BE NULL (we >> 353 * don't allow controlled access from kernel into user space from a >> 354 * foreign thread). In this case, the page fault handler should accept >> 355 * page faults from the kernel in user space, and resolve them in the >> 356 * usual way. The value in retvaddr is where the page fault handler >> 357 * has to return to in case the page fault remains unresolved. The >> 358 * address of the faulting address is kept in >> 359 * éthread->fixup_uaccess.faulted_uaddr >> 360 * >> 361 * @note typical values for fixup_retvaddr are obtained by "Labels as >> 362 * values" (see gcc's doc: operator "&&"). See uaccess.c for example >> 363 * code. >> 364 */ >> 365 sos_ret_t >> 366 sos_thread_prepare_user_space_access(struct sos_umem_vmm_as * dest_as, >> 367 sos_vaddr_t fixup_retvaddr); >> 368 >> 369 >> 370 /** >> 371 * Restricted function to signal we are not accessing any user address >> 372 * space anymore >> 373 */ >> 374 sos_ret_t >> 375 sos_thread_end_user_space_access(void); >> 376 >> 377 >> 378 /** >> 379 * Restricted callback called when a syscall goes back in user mode, >> 380 * to reconfigure the MMU to match that of the current thread's >> 381 * process MMU context. >> 382 * >> 383 * @note The use of this function is RESERVED to the syscall wrapper >> 384 */ >> 385 void sos_thread_prepare_syscall_switch_back(struct sos_cpu_state *cpu_state); >> 386 >> 387 >> 388 /** >> 389 * Restricted callback called when an exception handler goes back to >> 390 * the interrupted thread to reconfigure the MMU to match that of the >> 391 * current thread's process MMU context. >> 392 * >> 393 * @note The use of this function is RESERVED to the exception wrappers >> 394 */ >> 395 void sos_thread_prepare_exception_switch_back(struct sos_cpu_state *cpu_state); >> 396 >> 397 >> 398 /** >> 399 * Restricted callback called when an IRQ is entered while the CPU was >> 400 * NOT already servicing any other IRQ (ie the outermost IRQ handler >> 401 * is entered). This callback simply updates the "cpu_state" field so >> 402 * that IRQ handlers always know the state of the interrupted thread, >> 403 * even if they are imbricated in other IRQ handlers. >> 404 * >> 405 * @note The use of this function is RESERVED to the irq wrappers >> 406 */ >> 407 void >> 408 sos_thread_prepare_irq_servicing(struct sos_cpu_state *interrupted_state); >> 409 >> 410 >> 411 /** >> 412 * Restricted callback called when the outermost IRQ handler returns, >> 413 * to select the thread to return to. This callbacks implements: >> 414 * - preemption of user threads in user mode (time sharing / FIFO) >> 415 * - non-preemption of user threads in kernel mode (interrupted thread >> 416 * is restored on CPU "as is") >> 417 * - non-preemption of kernel threads (same remark) >> 418 * The MMU is reconfigured correctly to match the address space of the >> 419 * selected thread. >> 420 * >> 421 * @return The CPU context of the thread to return to >> 422 * >> 423 * @note The use of this function is RESERVED to the irq wrappers >> 424 */ >> 425 struct sos_cpu_state * >> 426 sos_thread_prepare_irq_switch_back(void); 205 427 206 428 207 #endif /* _SOS_THREAD_H_ */ 429 #endif /* _SOS_THREAD_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |