core/include/thread.h File Reference

Threads. More...

Defines

#define OS_INVALID_THREAD   0xFF
 Invalid thread identifier is coded by this value.
#define OS_MAX_THREADS   CFG_OS_MAX_THREADS
 Maximum number of threads.
#define OS_MAX_PRIO   16
 Maximum numbers of priorities.

Typedefs

typedef unsigned char os_thread_prio_t
 Thread identification and priority.
typedef enum os_thread_state_e os_thread_state_t
 Thread state type.
typedef os_result_t(* os_thread_func_t )(void *args)
 Main thread function type.

Enumerations

enum  os_thread_state_e { OS_THREAD_WAIT = 1, OS_THREAD_READY = 2, OS_THREAD_RUNNING = 3 }
 

Thread state.

More...

Functions

void os_thread_init (void)
 Initialization of system threads structures.
os_result_t os_thread_create (os_thread_prio_t priority, os_thread_func_t fun, void *args, unsigned short stack_size)
 Thread create function.
void os_thread_terminated (uni_cpu_reg_t retcode)
 Thread termination function.

Detailed Description

Threads.

Author:
Piotr Romaniuk, (c) ELESOFTROM
Version:
1.0 Feb 3, 2011

Thread in the DioneOS is a separate part of program that can run semi-parallel to other threads. A priority is assigned to each thread. The priority is an ordering norm that defines thread importance and helps to determine which of the threads should be run first. Because performance and compactness features that were main requirements for the system, it has been assumed that priorities are unique. This means that two threads cannot have the same priority. This made simpler to optimize the system code and allowed using the priority as the thread identifier.

The CPU time is assigned to threads by scheduler - the core item of the system. The scheduler always selects the thread with the highest priority from the set of threads that are not waiting. When a function of synchronization object (e.g. semaphore) is called the list of ready threads can be altered and CPU may be redirected to execute another thread. This switch from one thread to another is done by changing a context (stack, CPU registers contents, PC counter) and is handled by the system. Note that the preemption (the switch) may be also caused by ISR that have been triggered by hardware interrupt. In this case the switch happens in the time and code location that the thread is not aware of.

The thread in DioneOS can be in one of following states:
. OS_THREAD_RUNNING - the thread is currently running and owns CPU time. Only one thread can be in running state.
. OS_THREAD_READY - thread is ready to be run, but right now is preempted by higher priority thread.
. OS_THREAD_WAIT - thread is waiting on some synchronization object (semaphore, mutex etc.)
The state change is automatic and is done by the system during context switch.

At the first step threads module should be initialized by os_thread_init() call. After that, but before the scheduler is started, threads should be created. At that point thread properties should be specified (i.e. priority, stack size, main function).
Main function of the thread is C function of specific declaration:

                  os_result_t my_thread_fun( void * args )

The function is entered when corresponding thread is run for the first time. The thread creator can pass arguments to the main thread function. The arguments are passed by universal pointer that can be assigned and then projected on a structure type, hence it does not limit possible options. This pointer is one of the arguments of thread create function. The function should loop forever when it is in regular mode. Nevertheless, there is protection that when it exits it will behaves like a call of os_thread_terminated() with the input argument equal to return code from main thread function. Current implementation throws os_bug() exception when thread is terminated in this way. It may be altered by the user.

In order to implement true independent* thread run, each thread has its own stack. The size of the stack is declared during thread creation and cannot be changed later. Reserved size should take into account a space required for image of all registers. This space is used during context switch and in ISR, because ISR uses running thread stack. Also, regular stack usage must be included in that. The stack stores return addresses (so number of nested calls is important), local variables (in each function in call tree) and saved registers. Note that change of the compilation option (e.g. optimization level) may affect stack requirement.

*) - some systems use so-called "co-routines" that are fake version of multithreading and can be source of errors due to lack of local context.


Define Documentation

#define OS_MAX_THREADS   CFG_OS_MAX_THREADS

Maximum number of threads.

Threads information s stored in an internal table that contains thread controls blocks. This number is used to limit size of tcb table. Set it to number of threads that are created in your program. Use corresponding variable in config.h to configure its value.


Typedef Documentation

typedef os_result_t(* os_thread_func_t)(void *args)

Main thread function type.

The function is called at the first context switch to the thread. It should contain infinite loop. The function should not exit. Nevertheless if execution exits the function it is redirected to os_thread_terminated() function.

 struct my_struct { int field1, char field2 };//example structure for arguments passing
 
 os_result_t my_thread_1( void * args )
 {
    my_struct * a = (args_struct*)args;//conversion to user type allows access to passed items 
    while(1)
    {
    //  ... do thread job here...
    //  ... in infinite loop ...
    //  arguments can be accessed by:
    //   a->field1
    }
 //never return in regular conditions 
 }
Parameters:
[in]argspointer passed to the function, the pointer is defined during thread create function os_thread_create()
Returns:
the function will not return in regular way but returned value is an input argument for os_thread_terminated() where the execution is redirected.
typedef unsigned char os_thread_prio_t

Thread identification and priority.

Priorities of the threads must be unique, hence the priority can be used to identify the thread. Lower value represents higher priority (more significant thread). Priority 15 (the least important thread) should be assigned to Idle Thread.

Note:
1. No two threads can have the same priority
2. Number of threads is limited to capacity of os_set

Enumeration Type Documentation

Thread state.

Warning:
It is required that enum is 16 bits long, do not use --small_enum
Enumerator:
OS_THREAD_WAIT 

Thread is waiting on some waiting object. It cannot be scheduled.

OS_THREAD_READY 

Thread is ready to be scheduled, but now higher priority thread is running.

OS_THREAD_RUNNING 

Thread is running, its context is actual.


Function Documentation

os_result_t os_thread_create ( os_thread_prio_t  priority,
os_thread_func_t  fun,
void *  args,
unsigned short  stack_size 
)

Thread create function.

It registers the thread in system structures. Threads should be created before the scheduler is run. Threads cannot be deleted.
Size of the thread stack depends on number of nested calls, saved space in each function (incl. local variables). The requirements may change when compilation options are altered (e.g. optimization level). The space must be reserved for all registers save, first part is needed for context switch, second for ISR that uses thread stack.

Parameters:
[in]prioritythread priority (0..OS_MAX_THREADS-1), 0 represents the highest priority
[in]funmain thread function
[in]argsarguments passed to thread function by the pointer. May be NULL if thread function is aware of that
[in]stack_sizesize of thread stack
Returns:
OS_STATUS_OK if the thread has been created successfully
OS_ERROR_NO_MEMORY when stack cannot be allocated because insufficient memory
OS_ERROR when required priority is invalid (it is already used, or is outside of the range)
void os_thread_init ( void  )

Initialization of system threads structures.

The function must be called at the beginning of the program, before any thread is created.

void os_thread_terminated ( uni_cpu_reg_t  retcode)

Thread termination function.

Although, the thread function should never exit, if it happens execution is redirected to this function. Because such condition is unexpected and signals exceptional state of the system os_bug() is called.

Parameters:
[in]retcodeValue returned by thread function. It will remain in R12 register.