diff options
Diffstat (limited to 'thread.c')
| -rw-r--r-- | thread.c | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/thread.c b/thread.c new file mode 100644 index 0000000..46e0d42 --- /dev/null +++ b/thread.c @@ -0,0 +1,158 @@ +/************************************************************************/ +/* */ +/* File: thread.c */ +/* Description: thread implementation. */ +/* Version: 1.0 */ +/* Author: Otto Mattik */ +/* */ +/* (C)Copyright Otto Mattik 2014-2021. */ +/* */ +/* This file is a part of 'armen' (a tiny operating system). */ +/* 'armen' is distributed under the CeCILL-V2.1 licence. For more */ +/* details about this licence, please visit the website cecill.info */ +/* */ +/************************************************************************/ + +#include "core.h" + +uint8_t volatile _cur_thread; +_thread_t _threads[ARMEN_THREADS]; + +/* + * identifier of calling thread + * + * input: + * output: + * thread identifier +*/ +thread_t thread_self( void ) +{ + return( _cur_thread ); +} + +/* + * create a thread + * + * input: + * start start routine of new thread + * arg argument of start routine + * output: + * thread identifier if success, otherwise -1 +*/ +thread_t thread_create( void* (*start)(void*), void* arg ) +{ + register uint8_t i, iflag; + + iflag = _disable_intr( ); + for( i = 1; i < ARMEN_THREADS; i++ ) + { + register _thread_t* pthread = &_threads[i]; + + if( pthread->status == TS_UNUSED ) + { + pthread->rank = 127; + pthread->order = 0; + pthread->entry = start; + pthread->param = arg; + pthread->cstack = _init_context( start, arg, pthread->istack ); + pthread->status = TS_RUNNING; + break; + } + } + _enable_intr( iflag ); + return( i == ARMEN_THREADS ? -1 : i ); +} + +/* + * terminate the calling thread + * + * input: + * thread thread identifier + * retval value will be returned (see thread_join) + * output: +*/ +static void _thread_exit_( thread_t thread, void* retval ) +{ + _disable_intr( ); + _threads[thread].status = TS_UNUSED; + _wakeup( EVENT_JOIN, retval ); + _schedule( ); +} +void _thread_exit( void ) +{ + _thread_exit_( _cur_thread, 0 ); +} +void thread_exit( void* retval ) +{ + _thread_exit_( _cur_thread, retval ); +} + +#ifdef USE_FULL_THREAD + + /* + * send a cancellation request to a thread + * + * input: + * thread thread identifier + * output: + */ + void thread_cancel( thread_t thread ) + { + if( + #ifdef CHECK_PARAM + thread > 0 && thread < ARMEN_THREADS && + #endif + thread != _cur_thread + && _threads[thread].status != TS_UNUSED ) + _thread_exit_( thread, (void*)-1 ); + } + + /* + * wait for termination of a thread + * + * input: + * thread thread identifier + * retval address of exit value (see thread_exit) + * output: + */ + void thread_join( thread_t thread, void** retval ) + { + if( + #ifdef CHECK_PARAM + thread > 0 && thread < ARMEN_THREADS && + #endif + thread != _cur_thread + && _threads[thread].status != TS_UNUSED ) + { + wait_event( EVENT_JOIN ); + _schedule( ); + if( retval != (void**)0) + *retval = _threads[_cur_thread].param; + } + } + + /* + * change the priority of a thread + * + * input: + * thread thread identifier + * priority new priority (1 hightest to 254 lowest) + * if 0, just return the current priority + * output: + * priority if success, otherwise -1 + */ + uint8_t thread_nice( thread_t thread, uint8_t priority ) + { + if( + #ifdef CHECK_PARAM + thread <= 0 || thread >= ARMEN_THREADS || + #endif + _threads[thread].status == TS_UNUSED ) + return( 255 ); + + if( priority != 0 ) + _threads[thread].rank = priority; + return( _threads[thread].rank ); + } + +#endif |
