-
Notifications
You must be signed in to change notification settings - Fork 0
/
kernel_sched.h
288 lines (206 loc) · 7.89 KB
/
kernel_sched.h
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*
* Scheduler API and implementation
*
*/
#ifndef __KERNEL_SCHED_H
#define __KERNEL_SCHED_H
/**
@file kernel_sched.h
@brief TinyOS kernel: The Scheduler API
@defgroup scheduler Scheduler
@ingroup kernel
@brief The Scheduler API
This file contains the definition of the scheduler API, exported to other modules
of the kernel.
@{
*/
#include "util.h"
#include "bios.h"
#include "tinyos.h"
/*****************************
*
* The Thread Control Block
*
*****************************/
/** @brief Thread state.
A value of this type, together with a @c Thread_phase value, completely
determines the state of the current API.
@see Thread_phase
*/
typedef enum {
INIT, /**< TCB initialising */
READY, /**< A thread ready to be scheduled. */
RUNNING, /**< A thread running on some core */
STOPPED, /**< A blocked thread */
EXITED /**< A terminated thread */
} Thread_state;
/** @brief Thread phase.
@see Thread_state
*/
typedef enum {
CTX_CLEAN, /**< Means that, the context stored in the TCB is up-to-date. */
CTX_DIRTY /**< Means that, the context stored in the TCN is garbage. */
} Thread_phase;
/** @brief Thread type. */
typedef enum {
IDLE_THREAD, /**< Marks an idle thread. */
NORMAL_THREAD /**< Marks a normal thread */
} Thread_type;
/**
@brief Designate different origins of scheduler invocation.
This is used in the scheduler heuristics to determine how to
adjust the dynamic priority of the current thread.
*/
enum SCHED_CAUSE {
SCHED_QUANTUM, /**< The quantum has expired */
SCHED_IO, /**< The thread is waiting for I/O */
SCHED_MUTEX, /**< Mutex_Lock yielded on contention */
SCHED_PIPE, /**< Sleep at a pipe or socket */
SCHED_POLL, /**< The thread is polling a device */
SCHED_IDLE, /**< The idle thread called yield */
SCHED_USER /**< User-space code called yield */
};
//=============================PTCB Data Structure=============================//
typedef struct Process_Thread_Control_Block
{
rlnode ptcb_node; //PTCB Node.
TCB *tcb; //The TCB of this ptcb.
PCB *pcb; //The process of this ptcb.
Task task; //Main function to run for this thread.
int argl; //Length of main's funtion arguments.
void *args; //Arguments of main's function.
int ref_cnt; //Thread counter.
int exit_value; //Exit value of this thread.
int exited_flag; //Exit flag of this thread.
int is_main; //Is this the main thread.
int is_detached; //Is this thread detached.
CondVar joinVar; //Threads that are sleeping inside this thread.
}PTCB;
//=============================PTCB Data Structure=============================//
/**
@brief The thread control block
An object of this type is associated to every thread. In this object
are stored all the metadata that relate to the thread.
*/
typedef struct thread_control_block
{
PCB* owner_pcb; /**< This is null for a free TCB */
cpu_context_t context; /**< The thread context */
#ifndef NVALGRIND
unsigned valgrind_stack_id; /**< This is useful in order to register the thread stack to valgrind */
#endif
Thread_type type; /**< The type of thread */
Thread_state state; /**< The state of the thread */
Thread_phase phase; /**< The phase of the thread */
void (*thread_func)(); /**< The function executed by this thread */
TimerDuration wakeup_time; /**< The time this thread will be woken up by the scheduler */
rlnode sched_node; /**< node to use when queueing in the scheduler lists */
struct thread_control_block * prev; /**< previous context */
struct thread_control_block * next; /**< next context */
//Priority Index.
unsigned int prio;
//PTCB.
PTCB *tcb_ptcb;
} TCB;
/** Thread stack size */
#define THREAD_STACK_SIZE (128*1024)
/************************
*
* Scheduler
*
************************/
/** @brief Core control block.
Per-core info in memory (basically scheduler-related)
*/
typedef struct core_control_block {
uint id; /**< The core id */
TCB* current_thread; /**< Points to the thread currently owning the core */
TCB idle_thread; /**< Used by the scheduler to handle the core's idle thread */
sig_atomic_t preemption; /**< Marks preemption, used by the locking code */
} CCB;
/** @brief the array of Core Control Blocks (CCB) for the kernel */
extern CCB cctx[MAX_CORES];
/** @brief The current core's CCB */
#define CURCORE (cctx[cpu_core_id])
/**
@brief The current thread.
This is a pointer to the TCB of the thread currently executing on this core.
*/
#define CURTHREAD (CURCORE.current_thread)
/**
@brief The current thread.
This is a pointer to the PCB of the owner process of the current thread,
i.e., the thread currently executing on this core.
*/
#define CURPROC (CURTHREAD->owner_pcb)
/**
@brief A timeout constant, denoting no timeout for sleep.
*/
#define NO_TIMEOUT ((TimerDuration)-1)
/**
@brief Create a new thread.
This call creates a new thread, initializing and returning its TCB.
The thread will belong to process @c pcb and execute @c func.
Note that, the new thread is returned in the @c INIT state.
The caller must use @c wakeup() to start it.
*/
TCB* spawn_thread(PCB* pcb, void (*func)());
/**
@brief Wakeup a blocked thread.
This call will change the state of a thread from @c STOPPED or @c INIT (where the
thread is blocked) to @c READY.
@param tcb the thread to be made @c READY.
@returns 1 if the thread state was @c STOPPED or @c INIT, 0 otherwise
*/
int wakeup(TCB* tcb);
/**
@brief Block the current thread.
This call will block the current thread, changing its state to @c STOPPED
or @c EXITED. Also, the mutex @c mx, if not `NULL`, will be unlocked, atomically
with the blocking of the thread.
In particular, what is meant by 'atomically' is that the thread state will change
to @c newstate atomically with the mutex unlocking. Note that, the state of
the current thread is @c RUNNING.
Therefore, no other state change (such as a wakeup, a yield, another sleep etc)
can happen "between" the thread's state change and the unlocking.
If the @c newstate is @c EXITED, the thread will block and also will eventually be
cleaned-up by the scheduler. Its TCB should not be accessed in any way after this
call.
A cause for the sleep must be provided; this parameter indicates to the scheduler the
source of the sleeping operation, and can be used in scheduler heuristics to adjust
scheduling decisions.
A timeout can also be provided. If the timeout is not @c NO_TIMEOUT, then the thread will
be made ready by the scheduler after the timeout duration has passed, even without a call to
@c wakeup() by another thread.
@param newstate the new state for the thread
@param mx the mutex to unlock.
@param cause the cause of the sleep
@param timeout a timeout for the sleep, or
*/
void sleep_releasing(Thread_state newstate, Mutex* mx, enum SCHED_CAUSE cause, TimerDuration timeout);
/**
@brief Give up the CPU.
This call asks the scheduler to terminate the quantum of the current thread
and possibly switch to a different thread. The scheduler may decide that
it will renew the quantum for the current thread.
*/
void yield(enum SCHED_CAUSE cause);
/**
@brief Enter the scheduler.
This function is called at kernel initialization, by each core,
to enter the scheduler. When this function returns, the scheduler
has stopped (there are no more active threads) and the
*/
void run_scheduler(void);
/**
@brief Initialize the scheduler.
This function is called during kernel initialization.
*/
void initialize_scheduler(void);
/**
@brief Quantum (in microseconds)
This is the default quantum for each thread, in microseconds.
*/
#define QUANTUM (10000L)
/** @} */
#endif