1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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
|