Blame view

RIOT/core/include/sched.h 5.75 KB
a752c7ab   elopes   add first test an...
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
  /*
   * Copyright (C) 2014 Freie Universitรคt Berlin
   *
   * This file is subject to the terms and conditions of the GNU Lesser
   * General Public License v2.1. See the file LICENSE in the top level
   * directory for more details.
   */
  
  /**
   * @defgroup    core_sched Scheduler
   * @ingroup     core
   * @brief       The RIOT scheduler
   * @details
   *
   * RIOT features a tickless, preemptive, priority based scheduler.
   * Context switches can occur either preemptively (i.e. on interrupts),
   * voluntarily, or when a blocking operation (like `msg_receive()`) is
   * executed.
   * Being tickless means it does not have a timer that fires
   * periodically in order to emulate concurrent execution by switching
   * threads continuously.
   *
   * ## Priorities:
   *
   * Every thread is given a priority on creation. The priority values
   * are "order" or "nice" values, i.e. a higher value means a lower
   * priority.
   *
   * ### Example:
   *
   * Given threads with priorities A=6, B=1, and C=3, B has the highest
   * priority.
   *
   * A higher priority means that the scheduler will run this thread
   * whenever it becomes runnable instead of a thread with a lower
   * priority.
   * In case of equal priorities, the threads are scheduled in a
   * semi-cooperative fashion. That means that unless an interrupt
   * happens, threads with the same priority will only switch due to
   * voluntary or implicit context switches.
   *
   * ## Interrupts:
   *
   * When an interrupt occurs, e.g. because a timer fired or a network
   * packet was received, the active context is saved and an interrupt
   * service routine (ISR) that handles the interrupt is executed in
   * another context.
   * When the ISR is finished, the `::sched_context_switch_request` flag
   * can be checked. In case it is set, the `sched_run()` function is
   * called to determine the next active thread. (In the special case
   * that the ISR knows that it can not enable a thread switch, this
   * check can of course be omitted.)
   * If the flag is not set, the original context is being restored and
   * the thread resumes immediately.
   *
   * ## Voluntary Context Switches:
   *
   * There are two function calls that can lead to a voluntary context
   * switch: `thread_yield()` and `thread_sleep()`.
   * While the latter disables (think blocks) the thread until it is
   * woken (think unblocked) again via `thread_wakeup()`, the former only
   * leads to a context switch in case there is another runnable thread
   * with at least the same priority.
   *
   * ## Implicit Context Switches:
   *
   * Some functions that unblock another thread, e.g. `msg_send()` or
   * `mutex_unlock()`, can cause a thread switch, if the target had a
   * higher priority.
   *
   *
   * @{
   *
   * @file
   * @brief       Scheduler API definition
   *
   * @author      Kaspar Schleiser <kaspar@schleiser.de>
   */
  
  #ifndef SCHED_H
  #define SCHED_H
  
  #include <stddef.h>
  #include "kernel_defines.h"
  #include "bitarithm.h"
  #include "kernel_types.h"
  #include "native_sched.h"
  #include "clist.h"
  
  #ifdef __cplusplus
   extern "C" {
  #endif
  
  /**
   * @brief forward declaration for thread_t, defined in thread.h
   */
  typedef struct _thread thread_t;
  
  /**
   * @def SCHED_PRIO_LEVELS
   * @brief The number of thread priority levels
   */
  #ifndef SCHED_PRIO_LEVELS
  #define SCHED_PRIO_LEVELS 16
  #endif
  
  /**
   * @brief   Triggers the scheduler to schedule the next thread
   * @returns 1 if sched_active_thread/sched_active_pid was changed, 0 otherwise.
   */
  int sched_run(void);
  
  /**
   * @brief   Set the status of the specified process
   *
   * @param[in]   process     Pointer to the thread control block of the
   *                          targeted process
   * @param[in]   status      The new status of this thread
   */
  void sched_set_status(thread_t *process, unsigned int status);
  
  /**
   * @brief       Yield if approriate.
   *
   * @details     Either yield if other_prio is higher than the current priority,
   *              or if the current thread is not on the runqueue.
   *
   *              Depending on whether the current execution is in an ISR (irq_is_in()),
   *              thread_yield_higher() is called or @ref sched_context_switch_request is set,
   *              respectively.
   *
   * @param[in]   other_prio      The priority of the target thread.
   */
  void sched_switch(uint16_t other_prio);
  
  /**
   * @brief   Call context switching at thread exit
   */
  NORETURN void cpu_switch_context_exit(void);
  
  /**
   * Flag indicating whether a context switch is necessary after handling an
   * interrupt. Supposed to be set in an ISR.
   */
  extern volatile unsigned int sched_context_switch_request;
  
  /**
   *  Thread table
   */
  extern volatile thread_t *sched_threads[KERNEL_PID_LAST + 1];
  
  /**
   *  Currently active thread
   */
  extern volatile thread_t *sched_active_thread;
  
  /**
   *  Number of running (non-terminated) threads
   */
  extern volatile int sched_num_threads;
  
  /**
   *  Process ID of active thread
   */
  extern volatile kernel_pid_t sched_active_pid;
  
  /**
   * List of runqueues per priority level
   */
  extern clist_node_t sched_runqueues[SCHED_PRIO_LEVELS];
  
  /**
   * @brief  Removes thread from scheduler and set status to #STATUS_STOPPED
   */
  NORETURN void sched_task_exit(void);
  
  #ifdef MODULE_SCHEDSTATISTICS
  /**
   *  Scheduler statistics
   */
  typedef struct {
      uint32_t laststart;      /**< Time stamp of the last time this thread was
                                    scheduled to run */
      unsigned int schedules;  /**< How often the thread was scheduled to run */
      uint64_t runtime_ticks;  /**< The total runtime of this thread in ticks */
  } schedstat;
  
  /**
   *  Thread statistics table
   */
  extern schedstat sched_pidlist[KERNEL_PID_LAST + 1];
  
  /**
   *  @brief  Register a callback that will be called on every scheduler run
   *
   *  @param[in] callback The callback functions the will be called
   */
  void sched_register_cb(void (*callback)(uint32_t, uint32_t));
  #endif /* MODULE_SCHEDSTATISTICS */
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif /* SCHED_H */
  /** @} */