/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT 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 3 of the License, or
(at your option) any later version.
ChibiOS/RT 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, see .
*/
/**
* @addtogroup Threads
* @{
*/
#ifndef _THREADS_H_
#define _THREADS_H_
/**
* Structure representing a thread.
* @note Not all the listed fields are always needed, by switching off some
* not needed ChibiOS/RT subsystems it is possible to save RAM space by
* shrinking the \p Thread structure.
*/
struct Thread {
/** Next \p Thread in the threads list.*/
Thread *p_next;
/* End of the fields shared with the ThreadsList structure. */
/** Previous \p Thread in the threads list.*/
Thread *p_prev;
/* End of the fields shared with the ThreadsQueue structure. */
/** The thread priority.*/
tprio_t p_prio;
/* End of the fields shared with the ReadyList structure. */
/** Thread identifier. */
tid_t p_tid;
/** Current thread state.*/
tstate_t p_state;
/** Mode flags.*/
tmode_t p_flags;
/** Machine dependent processor context.*/
Context p_ctx;
/*
* The following fields are merged in unions because they are all
* state-specific fields. This trick saves some extra space for each
* thread in the system.
*/
union {
/** Thread wakeup code (only valid when exiting the \p PRREADY state).*/
msg_t p_rdymsg;
/** The thread exit code (only while in \p PREXIT state).*/
msg_t p_exitcode;
#ifdef CH_USE_SEMAPHORES
/** Semaphore where the thread is waiting on (only in \p PRWTSEM state).*/
Semaphore *p_wtsemp;
#endif
#ifdef CH_USE_MUTEXES
/** Mutex where the thread is waiting on (only in \p PRWTMTX state).*/
Mutex *p_wtmtxp;
#endif
#ifdef CH_USE_MESSAGES
/** Destination thread for message send (only in \p PRSNDMSG state).*/
Thread *p_wtthdp;
#endif
#ifdef CH_USE_EVENTS
/** Enabled events mask (only while in \p PRWTEVENT state).*/
eventmask_t p_ewmask;
#endif
#ifdef CH_USE_TRACE
/** Kernel object where the thread is waiting on. It is only valid when
the thread is some sleeping states.*/
void *p_wtobjp;
#endif
};
/*
* Start of the optional fields.
*/
#ifdef CH_USE_WAITEXIT
/** The list of the threads waiting for this thread termination.*/
ThreadsList p_waiting;
#endif
#ifdef CH_USE_EXIT_EVENT
/** The thread termination \p EventSource.*/
EventSource p_exitesource;
#endif
#ifdef CH_USE_MESSAGES
ThreadsQueue p_msgqueue;
msg_t p_msg;
#endif
#ifdef CH_USE_EVENTS
/** Pending events mask.*/
eventmask_t p_epending;
#endif
#ifdef CH_USE_MUTEXES
/** Owner mutexes list, \p NULL terminated.*/
Mutex *p_mtxlist;
tprio_t p_realprio;
#endif
};
/** Thread state: Thread in the ready list.*/
#define PRREADY 0
/** Thread state: Current.*/
#define PRCURR 1
/** Thread state: Thread created in suspended state.*/
#define PRSUSPENDED 2
/** Thread state: Waiting on a semaphore.*/
#define PRWTSEM 3
/** Thread state: Waiting on a mutex.*/
#define PRWTMTX 4
/** Thread state: Waiting in \p chThdSleep() or \p chThdSleepUntil().*/
#define PRSLEEP 5
/** Thread state: Waiting in \p chThdWait().*/
#define PRWAIT 6
/** Thread state: Waiting in \p chEvtWait().*/
#define PRWTEVENT 7
/** Thread state: Waiting in \p chMsgSend().*/
#define PRSNDMSG 8
/** Thread state: Waiting in \p chMsgWait().*/
#define PRWTMSG 9
/** Thread state: After termination.*/
#define PREXIT 10
#ifdef CH_USE_TERMINATE
/** Thread option: Termination requested flag.*/
#define P_TERMINATE 1
#endif
#ifdef CH_USE_RESUME
/** Thread option: Create suspended thread.*/
#define P_SUSPENDED 2
#endif
#ifdef CH_USE_MESSAGES_PRIORITY
/** Thread option: Serve messages by priority instead of FIFO order.*/
#define P_MSGBYPRIO 4
#endif
/** Pseudo priority used by the ready list header, do not use.*/
#define NOPRIO 0
/** Idle thread priority.*/
#define IDLEPRIO 1
/** Lowest user priority.*/
#define LOWPRIO 2
/** Normal user priority.*/
#define NORMALPRIO 64
/** Highest user priority.*/
#define HIGHPRIO 127
/** Greatest possible priority.*/
#define ABSPRIO 255
/* Not an API, don't use into the application code.*/
void _InitThread(tprio_t prio, tmode_t mode, Thread *tp);
/** Thread function.*/
typedef msg_t (*tfunc_t)(void *);
/*
* Threads APIs.
*/
#ifdef __cplusplus
extern "C" {
#endif
Thread *chThdCreate(tprio_t prio, tmode_t mode, void *workspace,
size_t wsize, tfunc_t pf, void *arg);
void chThdSetPriority(tprio_t newprio);
void chThdExit(msg_t msg);
#ifdef CH_USE_RESUME
void chThdResume(Thread *tp);
#endif
#ifdef CH_USE_SUSPEND
void chThdSuspend(Thread **tpp);
#endif
#ifdef CH_USE_TERMINATE
void chThdTerminate(Thread *tp);
#endif
#ifdef CH_USE_WAITEXIT
msg_t chThdWait(Thread *tp);
#endif
#ifdef __cplusplus
}
#endif
/** Returns the pointer to the \p Thread currently in execution.*/
#define chThdSelf() currp
/** Returns the thread priority.*/
#define chThdGetPriority() (currp->p_prio)
/** Returns the pointer to the \p Thread local storage area, if any.*/
#define chThdLS() (void *)(currp + 1)
/** Verifies if the specified thread is in the \p PREXIT state.*/
#define chThdTerminated(tp) ((tp)->p_state == PREXIT)
/**
* Verifies if the current thread has a termination request pending.
*/
#define chThdShouldTerminate() (currp->p_flags & P_TERMINATE)
/**
* Returns the exit event source for the specified thread. The source is
* signaled when the thread terminates.
* @param tp the pointer to the thread
* @note When registering on a thread termination make sure the thread
* is still alive, if you do that after the thread termination
* then you would miss the event. There are two ways to ensure
* this:
*
* - Create the thread suspended, register on the event source
* and then resume the thread (recommended).
* - Create the thread with a lower priority then register on it.
* This does not work if the hardware is capable of multiple
* physical threads.
*
* @note You dont need to unregister from a terminated thread because
* the event source becomes inactive.
* @note The function is available only if the \p CH_USE_EXIT_EVENT
* option is enabled in \p chconf.h.
*/
#define chThdGetExitEventSource(tp) (&(tp)->p_exitesource)
/**
* Resumes a thread created with the \p P_SUSPENDED option or suspended with
* \p chThdSuspend().
* @param tp the pointer to the thread
*/
#define chThdResumeI(tp) chSchReadyI((tp), RDY_OK)
#endif /* _THREADS_H_ */
/** @} */