aboutsummaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorOtto Mattik <otto@mattik.org>2021-07-08 18:10:55 +0200
committerOtto Mattik <otto@mattik.org>2021-07-08 18:10:55 +0200
commitda34d97efb21719b2b332f8c60b2750d11bcde1f (patch)
tree2de9fe89f6d79b8ebfcde64c5e86204e904aedf2 /thread.c
downloadarmen-da34d97efb21719b2b332f8c60b2750d11bcde1f.tar.gz
armen-da34d97efb21719b2b332f8c60b2750d11bcde1f.zip
git: update to v1.0HEADv1.0master
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c158
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