|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2004,2005 David Decotigny 002 003 This program is free software; you can redistribute it and/or 004 modify it under the terms of the GNU General Public License 005 as published by the Free Software Foundation; either version 2 006 of the License, or (at your option) any later version. 007 008 This program is distributed in the hope that it will be useful, 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 011 GNU General Public License for more details. 012 013 You should have received a copy of the GNU General Public License 014 along with this program; if not, write to the Free Software 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 016 USA. 017 */ 018 #ifndef _SOS_THREAD_H_ 019 #define _SOS_THREAD_H_ 020 021 /** 022 * @file thread.h 023 * 024 * SOS Thread management API 025 */ 026 027 #include <sos/errno.h> 028 029 /* Forward declaration */ 030 struct sos_thread; 031 032 #include <hwcore/cpu_context.h> 033 #include <sos/sched.h> 034 #include <sos/kwaitq.h> 035 #include <sos/time.h> 036 037 /** 038 * The possible states of a valid thread 039 */ 040 typedef enum { SOS_THR_CREATED, /**< Thread created, not fully initialized */ 041 SOS_THR_READY, /**< Thread fully initialized or 042 waiting for CPU after having been 043 blocked or preempted */ 044 SOS_THR_RUNNING, /**< Thread currently running on CPU */ 045 SOS_THR_BLOCKED, /**< Thread waiting for I/O (+ in at LEAST 046 one kwaitq) and/or sleeping (+ in NO 047 kwaitq) */ 048 SOS_THR_ZOMBIE, /**< Thread terminated execution, waiting to 049 be deleted by kernel */ 050 } sos_thread_state_t; 051 052 053 /** 054 * TCB (Thread Control Block): structure describing a thread. Don't 055 * access these fields directly: prefer using the accessor functions 056 * below. 057 */ 058 struct sos_thread 059 { 060 #define SOS_THR_MAX_NAMELEN 32 061 char name[SOS_THR_MAX_NAMELEN]; 062 063 sos_thread_state_t state; 064 065 /** 066 * The hardware context of the thread. 067 * 068 * It will reflect the CPU state of the thread: 069 * - From an interrupt handler: the state of the thread at the time 070 * of the OUTERMOST irq. An IRQ is not allowed to make context 071 * switches, so this context will remain valid from the begining of 072 * the outermost IRQ handler to the end of it, no matter if there 073 * are other IRQ handlers nesting in one another. You may safely 074 * use it from IRQ handlers to query the state of the interrupted 075 * thread, no matter if there has been other IRQ handlers 076 * executing meanwhile. 077 * - From normal kernel code, exceptions and syscall: the state of 078 * the thread the last time there was a context switch from this 079 * thread to another one. Thus this field WON'T reflect the 080 * current's thread cpu_state in these cases. So, in these cases, 081 * simply DO NOT USE IT outside thread.c ! Note: for syscall and 082 * exception handlers, the VALID state of the interrupted thread is 083 * passed as an argument to the handlers. 084 */ 085 struct sos_cpu_state *cpu_state; 086 087 /* Kernel stack parameters */ 088 sos_vaddr_t kernel_stack_base_addr; 089 sos_size_t kernel_stack_size; 090 091 /* Data specific to each state */ 092 union 093 { 094 struct 095 { 096 struct sos_thread *rdy_prev, *rdy_next; 097 } ready; 098 }; /* Anonymous union (gcc extenion) */ 099 100 101 /* 102 * Data used by the kwaitq subsystem: list of kwaitqueues the thread 103 * is waiting for. 104 * 105 * @note: a RUNNING or READY thread might be in one or more 106 * waitqueues ! The only property we have is that, among these 107 * waitqueues (if any), _at least_ one has woken the thread. 108 */ 109 struct sos_kwaitq_entry *kwaitq_list; 110 111 112 /** 113 * Chaining pointers for global ("gbl") list of threads (debug) 114 */ 115 struct sos_thread *gbl_prev, *gbl_next; 116 }; 117 118 119 /** 120 * Definition of the function executed by a kernel thread 121 */ 122 typedef void (*sos_kernel_thread_start_routine_t)(void *arg); 123 124 125 /** 126 * Initialize the subsystem responsible for thread management 127 * 128 * Initialize the primary kernel thread so that it can be handled the 129 * same way as an ordinary thread created by sos_thread_create(). 130 */ 131 sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr, 132 sos_size_t init_thread_stack_size); 133 134 135 /** 136 * Create a new kernel thread 137 */ 138 struct sos_thread * 139 sos_create_kernel_thread(const char *name, 140 sos_kernel_thread_start_routine_t start_func, 141 void *start_arg); 142 143 144 /** 145 * Terminate the execution of the current thread. For kernel threads, 146 * it is called by default when the start routine returns. 147 */ 148 void sos_thread_exit() __attribute__((noreturn)); 149 150 151 /** 152 * Get the identifier of the thread currently running on CPU. Trivial 153 * function. 154 */ 155 struct sos_thread *sos_thread_get_current(); 156 157 158 /** 159 * If thr == NULL, get the state of the current thread. Trivial 160 * function. 161 * 162 * @note NOT protected against interrupts 163 */ 164 sos_thread_state_t sos_thread_get_state(struct sos_thread *thr); 165 166 167 /** 168 * Yield CPU to another ready thread. 169 * 170 * @note This is a BLOCKING FUNCTION 171 */ 172 sos_ret_t sos_thread_yield(); 173 174 175 /** 176 * Release the CPU for (at least) the given delay. 177 * 178 * @param delay The delay to wait for. If delay == NULL then wait 179 * forever that any event occurs. 180 * 181 * @return SOS_OK when delay expired (and delay is reset to zero), 182 * -SOS_EINTR otherwise (and delay contains the amount of time 183 * remaining). 184 * 185 * @note This is a BLOCKING FUNCTION 186 */ 187 sos_ret_t sos_thread_sleep(/* in/out */struct sos_time *delay); 188 189 190 /** 191 * 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 result, the interrupted 193 * kwaitq/sleep function call of the thread will return with 194 * -SOS_EINTR. 195 * 196 * @return -SOS_EINVAL if thread does not exist, or -SOS_EFATAL if 197 * marked ZOMBIE. 198 * 199 * @note As a result, the semaphore/mutex/conditions/... functions 200 * return values SHOULD ALWAYS be checked ! If they are != SOS_OK, 201 * then the caller should consider that the resource is not aquired 202 * because somebody woke the thread by some way. 203 */ 204 sos_ret_t sos_thread_force_unblock(struct sos_thread *thread); 205 206 207 #endif /* _SOS_THREAD_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |