229 lines
6.5 KiB
C
229 lines
6.5 KiB
C
/* Copyright (C) 2004,2005 David Decotigny
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
USA.
|
|
*/
|
|
#ifndef _SOS_THREAD_H_
|
|
#define _SOS_THREAD_H_
|
|
|
|
/**
|
|
* @file thread.h
|
|
*
|
|
* SOS Thread management API
|
|
*/
|
|
|
|
#include <sos/errno.h>
|
|
|
|
/* Forward declaration */
|
|
struct sos_thread;
|
|
|
|
#include <hwcore/cpu_context.h>
|
|
#include <sos/sched.h>
|
|
#include <sos/kwaitq.h>
|
|
#include <sos/time.h>
|
|
|
|
/**
|
|
* The possible states of a valid thread
|
|
*/
|
|
typedef enum { SOS_THR_CREATED, /**< Thread created, not fully initialized */
|
|
SOS_THR_READY, /**< Thread fully initialized or
|
|
waiting for CPU after having been
|
|
blocked or preempted */
|
|
SOS_THR_RUNNING, /**< Thread currently running on CPU */
|
|
SOS_THR_BLOCKED, /**< Thread waiting for I/O (+ in at LEAST
|
|
one kwaitq) and/or sleeping (+ in NO
|
|
kwaitq) */
|
|
SOS_THR_ZOMBIE, /**< Thread terminated execution, waiting to
|
|
be deleted by kernel */
|
|
} sos_thread_state_t;
|
|
|
|
|
|
/**
|
|
* TCB (Thread Control Block): structure describing a thread. Don't
|
|
* access these fields directly: prefer using the accessor functions
|
|
* below.
|
|
*/
|
|
struct sos_thread
|
|
{
|
|
#define SOS_THR_MAX_NAMELEN 32
|
|
char name[SOS_THR_MAX_NAMELEN];
|
|
|
|
sos_thread_state_t state;
|
|
sos_sched_priority_t priority;
|
|
|
|
/**
|
|
* The hardware context of the thread.
|
|
*
|
|
* It will reflect the CPU state of the thread:
|
|
* - From an interrupt handler: the state of the thread at the time
|
|
* of the OUTERMOST irq. An IRQ is not allowed to make context
|
|
* switches, so this context will remain valid from the begining of
|
|
* the outermost IRQ handler to the end of it, no matter if there
|
|
* are other IRQ handlers nesting in one another. You may safely
|
|
* use it from IRQ handlers to query the state of the interrupted
|
|
* thread, no matter if there has been other IRQ handlers
|
|
* executing meanwhile.
|
|
* - From normal kernel code, exceptions and syscall: the state of
|
|
* the thread the last time there was a context switch from this
|
|
* thread to another one. Thus this field WON'T reflect the
|
|
* current's thread cpu_state in these cases. So, in these cases,
|
|
* simply DO NOT USE IT outside thread.c ! Note: for syscall and
|
|
* exception handlers, the VALID state of the interrupted thread is
|
|
* passed as an argument to the handlers.
|
|
*/
|
|
struct sos_cpu_state *cpu_state;
|
|
|
|
/* Kernel stack parameters */
|
|
sos_vaddr_t kernel_stack_base_addr;
|
|
sos_size_t kernel_stack_size;
|
|
|
|
/* Data specific to each state */
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
struct sos_sched_queue *rdy_queue;
|
|
struct sos_thread *rdy_prev, *rdy_next;
|
|
} ready;
|
|
}; /* Anonymous union (gcc extenion) */
|
|
|
|
|
|
/*
|
|
* Data used by the kwaitq subsystem: list of kwaitqueues the thread
|
|
* is waiting for.
|
|
*
|
|
* @note: a RUNNING or READY thread might be in one or more
|
|
* waitqueues ! The only property we have is that, among these
|
|
* waitqueues (if any), _at least_ one has woken the thread.
|
|
*/
|
|
struct sos_kwaitq_entry *kwaitq_list;
|
|
|
|
|
|
/**
|
|
* Chaining pointers for global ("gbl") list of threads (debug)
|
|
*/
|
|
struct sos_thread *gbl_prev, *gbl_next;
|
|
};
|
|
|
|
|
|
/**
|
|
* Definition of the function executed by a kernel thread
|
|
*/
|
|
typedef void (*sos_kernel_thread_start_routine_t)(void *arg);
|
|
|
|
|
|
/**
|
|
* Initialize the subsystem responsible for thread management
|
|
*
|
|
* Initialize the primary kernel thread so that it can be handled the
|
|
* same way as an ordinary thread created by sos_thread_create().
|
|
*/
|
|
sos_ret_t sos_thread_subsystem_setup(sos_vaddr_t init_thread_stack_base_addr,
|
|
sos_size_t init_thread_stack_size);
|
|
|
|
|
|
/**
|
|
* Create a new kernel thread
|
|
*/
|
|
struct sos_thread *
|
|
sos_create_kernel_thread(const char *name,
|
|
sos_kernel_thread_start_routine_t start_func,
|
|
void *start_arg,
|
|
sos_sched_priority_t priority);
|
|
|
|
|
|
/**
|
|
* Terminate the execution of the current thread. For kernel threads,
|
|
* it is called by default when the start routine returns.
|
|
*/
|
|
void sos_thread_exit() __attribute__((noreturn));
|
|
|
|
|
|
/**
|
|
* Get the identifier of the thread currently running on CPU. Trivial
|
|
* function.
|
|
*/
|
|
struct sos_thread *sos_thread_get_current();
|
|
|
|
|
|
/**
|
|
* If thr == NULL, set the priority of the current thread. Trivial
|
|
* function.
|
|
*
|
|
* @note NOT protected against interrupts
|
|
*/
|
|
sos_sched_priority_t sos_thread_get_priority(struct sos_thread *thr);
|
|
|
|
|
|
/**
|
|
* If thr == NULL, get the state of the current thread. Trivial
|
|
* function.
|
|
*
|
|
* @note NOT protected against interrupts
|
|
*/
|
|
sos_thread_state_t sos_thread_get_state(struct sos_thread *thr);
|
|
|
|
|
|
/**
|
|
* If thr == NULL, set the priority of the current thread
|
|
*
|
|
* @note NO context-switch ever occurs in this function !
|
|
*/
|
|
sos_ret_t sos_thread_set_priority(struct sos_thread *thr,
|
|
sos_sched_priority_t priority);
|
|
|
|
|
|
/**
|
|
* Yield CPU to another ready thread.
|
|
*
|
|
* @note This is a BLOCKING FUNCTION
|
|
*/
|
|
sos_ret_t sos_thread_yield();
|
|
|
|
|
|
/**
|
|
* Release the CPU for (at least) the given delay.
|
|
*
|
|
* @param delay The delay to wait for. If delay == NULL then wait
|
|
* forever that any event occurs.
|
|
*
|
|
* @return SOS_OK when delay expired (and delay is reset to zero),
|
|
* -SOS_EINTR otherwise (and delay contains the amount of time
|
|
* remaining).
|
|
*
|
|
* @note This is a BLOCKING FUNCTION
|
|
*/
|
|
sos_ret_t sos_thread_sleep(/* in/out */struct sos_time *delay);
|
|
|
|
|
|
/**
|
|
* Mark the given thread as READY (if not already ready) even if it is
|
|
* blocked in a kwaitq or in a sleep ! As a result, the interrupted
|
|
* kwaitq/sleep function call of the thread will return with
|
|
* -SOS_EINTR.
|
|
*
|
|
* @return -SOS_EINVAL if thread does not exist, or -SOS_EFATAL if
|
|
* marked ZOMBIE.
|
|
*
|
|
* @note As a result, the semaphore/mutex/conditions/... functions
|
|
* return values SHOULD ALWAYS be checked ! If they are != SOS_OK,
|
|
* then the caller should consider that the resource is not aquired
|
|
* because somebody woke the thread by some way.
|
|
*/
|
|
sos_ret_t sos_thread_force_unblock(struct sos_thread *thread);
|
|
|
|
|
|
#endif /* _SOS_THREAD_H_ */
|