Cooperative multi-threading support. More...
Data Structures | |
struct | _NUTTHREADINFO |
Thread information structure. More... | |
Defines | |
#define | SLEEP_MODE_NONE 0xff |
#define | NUT_THREAD_STACK_MULT 1 |
Stack size factor. | |
#define | NUT_THREAD_STACK_ADD 0 |
Stack size summand. | |
#define | THREAD(threadfn, arg) |
Macro for thread entry definitions. | |
Typedefs | |
typedef struct _NUTTHREADINFO | NUTTHREADINFO |
Functions | |
void | NutThreadInit (void) |
Initialize thread handling in the Linux emulation. | |
HANDLE | NutThreadCreate (char *name, void(*fn)(void *), void *arg, size_t stackSize) |
Create a new thread. | |
uint8_t | NutThreadSetPriority (uint8_t level) |
Set the current thread's priority. | |
void | NutThreadKill (void) |
Kill the running thread. | |
void | NutThreadDestroy (void) |
Free a thread that was previously killed and release memory back to the OS. | |
void | NutThreadExit (void) |
End the current thread. | |
void | NutThreadResume (void) |
Continue with the highest priority thread, which is ready to run. | |
void | NutThreadWake (HANDLE timer, HANDLE th) |
Resume a previously suspended thread. | |
void | NutThreadYield (void) |
Give up the CPU. | |
void | NutThreadAddPriQueue (NUTTHREADINFO *td, NUTTHREADINFO *volatile *tqpp) |
Add a thread to a prioritiy ordered queue. | |
void | NutThreadRemoveQueue (NUTTHREADINFO *td, NUTTHREADINFO *volatile *tqpp) |
Remove a thread from a specified queue. | |
void | NutThreadSwitch (void) |
Switch to another thread. | |
HANDLE | GetThreadByName (char *name) |
Query handle of a thread with a specific name. | |
NUTTHREADINFO * | NutThreadStackCheck (size_t minsiz) |
Check all Nut/OS threads for sufficient stack space. | |
size_t | NutThreadStackAvailable (char *name) |
Return the size of unused stack space. | |
Variables | |
NUTTHREADINFO * | runningThread |
Currently running thread. | |
NUTTHREADINFO * | nutThreadList |
List of all created threads. | |
NUTTHREADINFO * | runQueue |
List of ready-to-run threads. | |
NUTTHREADINFO * | runningThread |
Currently running thread. | |
NUTTHREADINFO * | killedThread |
Thread to be killed. | |
NUTTHREADINFO * | nutThreadList |
List of all created threads. | |
NUTTHREADINFO * | runQueue |
List of ready-to-run threads. | |
Thread States | |
#define | TDS_TERM 0 |
#define | TDS_RUNNING 1 |
#define | TDS_READY 2 |
#define | TDS_SLEEP 3 |
Cooperative multi-threading support.
Typically Nut/OS is at its most useful where there are several concurrent tasks that need to be undertaken at the same time. To support this requirement, Nut/OS offers some kind of light processes called threads. In this context a thread is a sequence of executing software that can be considered to be logically independent from other software that is running on the same CPU.
All threads are executing in the same address space using the same hardware resources, which significantly reduces task switching overhead. Therefore it is important to stop them from causing each other problems. This is particularly an issue where two or more threads need to share a resources like memory locations or peripheral devices.
The system works on the principle that the most urgent thread always runs. One exception to this is if a CPU interrupt arrives and the interrupt has not been disabled. Each thread has a priority which is used to determine how urgent it is. This priority ranges from 0 to 255, with the lowest value indicating the most urgent.
Nut/OS implements cooperative multithreading. That means, that threads are not bound to a fixed timeslice. Unless they are waiting for specific event or explicitly yielding the CPU, they can rely on not being stopped unexpectedly. However, they may be interrupted by hardware interrupt signals. In opposite to pre-emptive multithreading, cooperative multithreading simplifies resource sharing and results in faster and smaller code.
To specify a function named Back as an independent thread, one can write
#include <sys/thread.h> THREAD(Back, arg) { for (;;) { NutSleep(1000); } }
To start this thread, use
#include <sys/thread.h> // Other code here... NutThreadCreate("Bg", Back, NULL, 512); // Execution continues here and concurrently in the background thread.
The functions listed below are hardware independent. Additional API calls are located in the architecture dependant sections.
#define TDS_TERM 0 |
Thread has exited.
#define TDS_RUNNING 1 |
Thread is running.
Referenced by NutSleep(), NutThreadCreate(), NutThreadResume(), NutThreadSetPriority(), and NutThreadSwitch().
#define TDS_READY 2 |
Thread is ready to run.
Referenced by NutEventPostAsync(), NutEventTimeout(), NutThreadCreate(), NutThreadResume(), NutThreadSetPriority(), and NutThreadWake().
#define TDS_SLEEP 3 |
Thread is sleeping.
Referenced by NutEventWait(), and NutSleep().
#define SLEEP_MODE_NONE 0xff |
Referenced by NutIdle().
#define NUT_THREAD_STACK_MULT 1 |
Stack size factor.
Configured stack sizes are multiplied with this value.
All stack size settings of internal Nut/OS threads had been calculated for size optimized code. Probably more stack space is required with other compiler settings.
For example, when GCC generates non-optimized code for source code debugging, a factor of 3 should be applied to all stack sizes.
Application code may also make use of this macro.
#include <sys/thread.h> #define MY_THREAD_STACK ((384 * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) NutThreadCreate("myth", ThreadFunc, 0, MY_THREAD_STACK);
See also NUT_THREAD_STACK_ADD.
Referenced by AhdlcAt91Init(), AhdlcAvrInit(), DmInit(), EmacInit(), LancInit(), Lpc17xxEmacInit(), main(), NicInit(), NutIdle(), NutInit(), NutPppInitStateMachine(), NutRegisterDiscovery(), NutSNTPStartThread(), and NutTcpInitStateMachine().
#define NUT_THREAD_STACK_ADD 0 |
Stack size summand.
The specified value will be added to all configured stack sizes.
Referenced by AhdlcAt91Init(), AhdlcAvrInit(), DmInit(), EmacInit(), LancInit(), Lpc17xxEmacInit(), main(), NicInit(), NutIdle(), NutInit(), NutPppInitStateMachine(), NutRegisterDiscovery(), NutSNTPStartThread(), and NutTcpInitStateMachine().
#define THREAD | ( | threadfn, | |
arg | |||
) |
void threadfn(void *arg) __attribute__ ((noreturn)); \ void threadfn(void *arg)
Macro for thread entry definitions.
typedef struct _NUTTHREADINFO NUTTHREADINFO |
Thread information structure type.
void NutThreadInit | ( | void | ) | [private] |
Initialize thread handling in the Linux emulation.
Used in the Liux emulation only. Has to be initialized once.
Referenced by main().
HANDLE NutThreadCreate | ( | char * | name, |
void(*)(void *) | fn, | ||
void * | arg, | ||
size_t | stackSize | ||
) |
Create a new thread.
If the current thread's priority is lower or equal than the default priority (64), then the current thread is stopped and the new one is started.
name | String containing the symbolic name of the new thread, up to 8 characters long. |
fn | The thread's entry point, typically created by the THREAD macro. |
arg | Argument pointer passed to the new thread. |
stackSize | Number of bytes of the stack space allocated for the new thread. |
If the current thread's priority is lower or equal than the default priority (64), then the current thread is stopped and the new one is started.
name | String containing the symbolic name of the new thread, up to 8 characters long. |
fn | The thread's entry point, typically created by the THREAD macro. |
arg | Argument pointer passed to the new thread. |
stackSize | Number of bytes of the stack space allocated for the new thread. |
References __os_trf, __os_trs, ARM_CPSR_F_BIT, ARM_CPSR_I_BIT, ARM_MODE_SYS, attr, ENTERFRAME::cef_arghi, ENTERFRAME::cef_arglo, ENTERFRAME::cef_pc, ENTERFRAME::cef_pchi, ENTERFRAME::cef_pclo, ENTERFRAME::cef_r0, ENTERFRAME::cef_r1, ENTERFRAME::cef_r12, ENTERFRAME::cef_rampz, ENTERFRAME::cef_sreg, SWITCHFRAME::csf_cpsr, SWITCHFRAME::csf_lr, SWITCHFRAME::csf_pchi, SWITCHFRAME::csf_pclo, DEADBEEF, fprintf(), irq_signal, main_cv, memcpy(), NULL, NutDumpThreadList(), NutEnterCritical, NutExitCritical, NutHeapAlloc, NutStackAlloc, NutThreadAddPriQueue(), nutThreadList, NutThreadSwitch(), printf, runningThread, runQueue, _NUTTHREADINFO::td_memory, _NUTTHREADINFO::td_name, _NUTTHREADINFO::td_next, _NUTTHREADINFO::td_priority, _NUTTHREADINFO::td_queue, _NUTTHREADINFO::td_sp, _NUTTHREADINFO::td_state, _NUTTHREADINFO::td_timer, TDS_READY, TDS_RUNNING, and thread_mutex.
Referenced by AhdlcAt91Init(), AhdlcAvrInit(), AsixInit(), cs8900Init(), CSNicInit(), DmInit(), EmacInit(), IDEInit(), LancInit(), Lpc17xxEmacInit(), main(), NicInit(), NutIdle(), NutInit(), NutPppInitStateMachine(), NutRegisterDiscovery(), NutRegisterKey(), NutRegisterLed(), NutSNTPStartThread(), NutTcpInitStateMachine(), Sc16is752UsartInit(), SJAInit(), upnp_Init(), and wlandrv_Init().
Set the current thread's priority.
The priority of newly created threads is set to 64, but may be changed when the thread starts running.
Changing the priority level to 255 will kill the calling thread.
When another thread with a higher or equal priority is ready to run, the current thread will be stopped and control of the CPU is passed to the other thread.
The function returns the old priority, which makes it easy to temporarily switch to another priority and later set back the old one.
level | New priority level or 255 to kill the thread. Zero specifies the highest priority. The idle thread is running at level 254 (lowest priority). Application threads should use levels from 32 to 253. |
References NutEnterCritical, NutExitCritical, NutThreadAddPriQueue(), NutThreadKill(), NutThreadRemoveQueue(), NutThreadSwitch(), _NUTTHREADINFO::td_priority, _NUTTHREADINFO::td_state, TDS_READY, TDS_RUNNING, TRACE_ADD_ITEM, and TRACE_TAG_THREAD_SETPRIO.
Referenced by AhdlcRx(), CAN_Tx(), CSNICrx(), EmacRxThread(), FeederThread(), High(), Low(), Lpc17xxEmacRxThread(), main(), NicRx(), NicRxAsix(), NicRxLanc(), NutIdle(), NutTcpSm(), NutThreadExit(), OTGTimerEvent(), Receiver(), Sc16is752UsartInterruptProcessing(), Sleeper1(), Sleeper2(), Sleeper3(), Sleeper4(), SNTP_resync(), sys_key(), sys_led(), Thread1(), Thread2(), TimerEvent1(), TimerEvent2(), TimerEvent3(), and TimerEvent4().
void NutThreadKill | ( | void | ) |
Kill the running thread.
The thread is moved from the schedule que and
Applications generally do not call this function.
References NutThreadDestroy(), nutThreadList, runningThread, and _NUTTHREADINFO::td_next.
Referenced by NutThreadSetPriority().
void NutThreadDestroy | ( | void | ) |
Free a thread that was previously killed and release memory back to the OS.
Called when another thread is killed and by the idle thread.
Applications generally do not call this function, however you could call it to try to reclaim memory.
References NutStackFree, and _NUTTHREADINFO::td_memory.
Referenced by NutIdle(), and NutThreadKill().
void NutThreadExit | ( | void | ) |
End the current thread.
Terminates the current thread, in due course the memory associated with the thread will be released back to the OS this is done by the idle thread.
References NutThreadSetPriority().
void NutThreadResume | ( | void | ) | [private] |
Continue with the highest priority thread, which is ready to run.
If the currently running thread lost its top position in the queue of ready-to-run threads, then the context will be switched.
References NutEnterCritical, NutEventPostAsync(), NutExitCritical, nutThreadList, NutThreadSwitch(), NutTimerProcessElapsed(), SIGNALED, _NUTTHREADINFO::td_next, _NUTTHREADINFO::td_qpec, _NUTTHREADINFO::td_queue, TDS_READY, TDS_RUNNING, TRACE_ADD_ITEM, and TRACE_TAG_THREAD_YIELD.
Referenced by NutEventWait(), NutSleep(), and NutThreadYield().
Resume a previously suspended thread.
This routine is called by the system when a sleep timer elapses.
timer | Handle of the elapsed timer. |
th | Handle of the thread to wake up. |
References NULL, NUTASSERT, NutThreadAddPriQueue(), and TDS_READY.
Referenced by NutDumpTimerList(), and NutSleep().
void NutThreadYield | ( | void | ) |
Give up the CPU.
If another thread within the same or higher priority is ready to run, then the current thread is stopped and the other one is started.
References NutEnterCritical, NutExitCritical, NutThreadAddPriQueue(), NutThreadRemoveQueue(), NutThreadResume(), NutUnixThreadYieldHook(), and _NUTTHREADINFO::td_qnxt.
Referenced by NotifyTask(), NutEventBroadcast(), NutEventPost(), NutEventWait(), NutIdle(), NutMsgQSend(), NutSleep(), NutTcpReceive(), NutTcpSend(), NutTcpStateCloseEvent(), ProcessRequests(), Receiver(), and SSDPTask().
void NutThreadAddPriQueue | ( | NUTTHREADINFO * | td, |
NUTTHREADINFO *volatile * | tqpp | ||
) | [private] |
Add a thread to a prioritiy ordered queue.
Insert the thread into a specified queue behind the last thread with lower or equal priority.
td | Pointer to NUTTHREADINFO of the thread to be inserted in the queue. |
tqpp | Pointer to the root of the queue. |
References NULL, NUTASSERT, NutEnterCritical, NutExitCritical, SIGNALED, _NUTTHREADINFO::td_priority, _NUTTHREADINFO::td_qnxt, _NUTTHREADINFO::td_qpec, and _NUTTHREADINFO::td_queue.
Referenced by NutEventPostAsync(), NutEventTimeout(), NutEventWait(), NutThreadCreate(), NutThreadSetPriority(), NutThreadWake(), and NutThreadYield().
void NutThreadRemoveQueue | ( | NUTTHREADINFO * | td, |
NUTTHREADINFO *volatile * | tqpp | ||
) | [private] |
Remove a thread from a specified queue.
td | Pointer to NUTTHREADINFO of the thread to be removed from the queue. |
tqpp | Pointer to the root of the queue. |
References NutEnterCritical, NutExitCritical, SIGNALED, _NUTTHREADINFO::td_qnxt, _NUTTHREADINFO::td_qpec, and _NUTTHREADINFO::td_queue.
Referenced by NutEventWait(), NutSleep(), NutThreadSetPriority(), and NutThreadYield().
void NutThreadSwitch | ( | void | ) | [private] |
Switch to another thread.
Stop the current thread, saving its context. Then start the one with the highest priority, which is ready to run.
Application programs typically do not call this function.
References runningThread, runQueue, _NUTTHREADINFO::td_sp, _NUTTHREADINFO::td_state, and TDS_RUNNING.
Referenced by NutThreadCreate(), NutThreadResume(), and NutThreadSetPriority().
HANDLE GetThreadByName | ( | char * | name | ) |
Query handle of a thread with a specific name.
name | Case sensitive symbolic name of the thread. |
References NULL, runningThread, strcmp(), _NUTTHREADINFO::td_name, and _NUTTHREADINFO::td_next.
Referenced by NutThreadStackAvailable().
NUTTHREADINFO* NutThreadStackCheck | ( | size_t | minsiz | ) |
Check all Nut/OS threads for sufficient stack space.
See NutThreadStackAvailable() for further informations.
minleft | Number of bytes that should have been unused. |
Referenced by NutTimerIntr().
size_t NutThreadStackAvailable | ( | char * | name | ) |
Return the size of unused stack space.
The stack will be treated as an array of 32-bit values, which are initially set to DEADBEEF. Starting at the stack's bottom, this function will simply count the number of array members, which still contain the original value.
This implicates at least three limitations:
This function is available only if NUTDEBUG_CHECK_STACK has been defined during system build.
name | Symbolic name of the thread. |
References GetThreadByName().
Referenced by NutDumpThreadList().
Currently running thread.
Pointer to the NUTTHREADINFO structure of the currently running thread.
Referenced by GetThreadByName(), NutEventWait(), NutMutexDestroy(), NutMutexLock(), NutMutexTrylock(), NutMutexUnlock(), NutSleep(), NutThreadCreate(), NutThreadKill(), and NutThreadSwitch().
List of all created threads.
Linked list of NUTTHREADINFO structures of all threads. New threads are put in front. This list contains at least two threads, the main application thread followed by the idle thread.
Referenced by NutDumpThreadList(), NutThreadCreate(), NutThreadKill(), and NutThreadResume().
List of ready-to-run threads.
Priority ordered linked list of NUTTHREADINFO structures of all threads which are ready to run. The idle thread will always remain at the end of this list.
Referenced by NutEventPostAsync(), NutEventTimeout(), NutEventWait(), NutSleep(), NutThreadCreate(), and NutThreadSwitch().
Currently running thread.
Pointer to the NUTTHREADINFO structure of the currently running thread.
Referenced by GetThreadByName(), NutEventWait(), NutMutexDestroy(), NutMutexLock(), NutMutexTrylock(), NutMutexUnlock(), NutSleep(), NutThreadCreate(), NutThreadKill(), and NutThreadSwitch().
Thread to be killed.
Pointer to the NUTTHREADINFO structure of the latest killed thread.
List of all created threads.
Linked list of NUTTHREADINFO structures of all threads. New threads are put in front. This list contains at least two threads, the main application thread followed by the idle thread.
Referenced by NutDumpThreadList(), NutThreadCreate(), NutThreadKill(), and NutThreadResume().
List of ready-to-run threads.
Priority ordered linked list of NUTTHREADINFO structures of all threads which are ready to run. The idle thread will always remain at the end of this list.
Referenced by NutEventPostAsync(), NutEventTimeout(), NutEventWait(), NutSleep(), NutThreadCreate(), and NutThreadSwitch().