SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

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

source navigation ] diff markup ] identifier search ] general search ]