µOS++ IIIe Reference  v6.3.15
“Perfekt ist nicht gut genug”
The third edition of µOS++, a POSIX inspired open source system, written in C++.
os-sched.h
Go to the documentation of this file.
1 /*
2  * This file is part of the µOS++ distribution.
3  * (https://github.com/micro-os-plus)
4  * Copyright (c) 2016 Liviu Ionescu.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom
12  * the Software is furnished to do so, subject to the following
13  * conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  * OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #ifndef CMSIS_PLUS_RTOS_OS_SCHED_H_
29 #define CMSIS_PLUS_RTOS_OS_SCHED_H_
30 
31 // ----------------------------------------------------------------------------
32 
33 #if defined(__cplusplus)
34 
37 
38 // ----------------------------------------------------------------------------
39 
40 namespace os
41 {
42  namespace rtos
43  {
44  namespace scheduler
45  {
46 
54  extern bool is_started_;
55 
56 #if !defined(OS_USE_RTOS_PORT_SCHEDULER)
57  extern bool is_preemptive_;
58  extern thread* volatile current_thread_;
59  extern internal::ready_threads_list ready_threads_list_;
60 #endif /* !defined(OS_USE_RTOS_PORT_SCHEDULER) */
61 
62  extern internal::terminated_threads_list terminated_threads_list_;
63 
75  result_t
76  initialize (void);
77 
85  [[noreturn]] void
86  start (void);
87 
95  bool
96  started (void);
97 
104  state_t
105  lock (void);
106 
113  state_t
114  unlock (void);
115 
121  state_t
122  locked (state_t state);
123 
131  bool
132  locked (void);
133 
141  bool
142  preemptive (void);
143 
149  bool
150  preemptive (bool state);
151 
152  // ----------------------------------------------------------------------
153 
158  void
159  internal_switch_threads (void);
160 
165  // ======================================================================
171  {
172  public:
173 
184  critical_section ();
185 
190  // The rule of five.
191  critical_section (const critical_section&) = delete;
192  critical_section (critical_section&&) = delete;
194  operator= (const critical_section&) = delete;
196  operator= (critical_section&&) = delete;
197 
206 
211  protected:
212 
225  const state_t state_;
226 
234  };
235 
236  // ======================================================================
237 
243  {
244  public:
245 
257 
262  // The rule of five.
263  uncritical_section (const uncritical_section&) = delete;
266  operator= (const uncritical_section&) = delete;
268  operator= (uncritical_section&&) = delete;
269 
277  ~uncritical_section ();
278 
283  protected:
284 
297  const state_t state_;
298 
306  };
307 
308  // ======================================================================
309 
314  class lockable
315  {
316  public:
317 
328  constexpr
329  lockable ();
330 
335  // The rule of five.
336  lockable (const lockable&) = delete;
337  lockable (lockable&&) = delete;
338  lockable&
339  operator= (const lockable&) = delete;
340  lockable&
341  operator= (lockable&&) = delete;
342 
350  ~lockable ();
351 
356  public:
357 
370  void
371  lock (void);
372 
379  bool
380  try_lock (void);
381 
389  void
390  unlock (void);
391 
396  protected:
397 
410  state_t state_ = 0;
411 
419  };
420 
421  // ----------------------------------------------------------------------
422 
426  namespace statistics
427  {
428 #if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
429 
435  context_switches (void);
436 
441  extern rtos::statistics::counter_t context_switches_;
442 
447 #endif /* defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) */
448 
449 #if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
450 
457  cpu_cycles (void);
458 
463  extern clock::timestamp_t switch_timestamp_;
464  extern rtos::statistics::duration_t cpu_cycles_;
465 
470 #endif /* defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES) */
471 
472  } /* namespace statistics */
473  } /* namespace scheduler */
474 
475  namespace interrupts
476  {
484  bool
485  in_handler_mode (void);
486 
487  // ======================================================================
488 
489  // TODO: define all levels of critical sections
490  // (kernel, real-time(level), complete)
491 
492  // TODO: make template, parameter IRQ level
493 
499  {
500  public:
501 
512  critical_section ();
513 
518  // The rule of five.
519  critical_section (const critical_section&) = delete;
520  critical_section (critical_section&&) = delete;
522  operator= (const critical_section&) = delete;
524  operator= (critical_section&&) = delete;
525 
534 
539  public:
540 
552  static state_t
553  enter (void);
554 
560  static void
561  exit (state_t state);
562 
567  protected:
568 
581  const state_t state_;
582 
590  };
591 
592  // ======================================================================
593 
599  {
600  public:
601 
613 
618  // The rule of five.
619  uncritical_section (const uncritical_section&) = delete;
622  operator= (const uncritical_section&) = delete;
624  operator= (uncritical_section&&) = delete;
625 
633  ~uncritical_section ();
634 
639  public:
640 
652  static state_t
653  enter (void);
654 
661  static void
662  exit (state_t state);
663 
668  protected:
669 
682  const state_t state_;
683 
691  };
692 
693  // ======================================================================
694 
699  class lockable
700  {
701  public:
702 
713  constexpr
714  lockable ();
715 
719  ~lockable ();
720 
725  // The rule of five.
726  lockable (const lockable&) = delete;
727  lockable (lockable&&) = delete;
728  lockable&
729  operator= (const lockable&) = delete;
730  lockable&
731  operator= (lockable&&) = delete;
732 
741  public:
742 
755  void
756  lock (void);
757 
764  bool
765  try_lock (void);
766 
774  void
775  unlock (void);
776 
781  protected:
782 
795  state_t state_;
796 
805  };
806 
807  } /* namespace interrupts */
808  } /* namespace rtos */
809 } /* namespace os */
810 
811 // ===== Inline & template implementations ====================================
812 
813 namespace os
814 {
815  namespace rtos
816  {
817  namespace scheduler
818  {
826  inline bool
827  started (void)
828  {
829  return is_started_;
830  }
831 
838  inline bool
839  preemptive (void)
840  {
841 #if !defined(OS_USE_RTOS_PORT_SCHEDULER)
842  return is_preemptive_;
843 #else
845 #endif
846  }
847 
855  inline bool
856  locked (void)
857  {
858  return port::scheduler::locked ();
859  }
860 
868  inline state_t
869  lock (void)
870  {
871  return port::scheduler::lock ();
872  }
873 
881  inline state_t
882  unlock (void)
883  {
884  return port::scheduler::unlock ();
885  }
886 
898  inline state_t
899  locked (state_t state)
900  {
901  return port::scheduler::locked (state);
902  }
903 
910  inline
912  state_ (lock ())
913  {
914 #if defined(OS_TRACE_RTOS_SCHEDULER)
915  trace::printf (" {c ");
916 #endif
917  }
918 
926  inline
928  {
929 #if defined(OS_TRACE_RTOS_SCHEDULER)
930  trace::printf (" c} ");
931 #endif
932  locked (state_);
933  }
934 
941  inline
943  state_ (unlock ())
944  {
945 #if defined(OS_TRACE_RTOS_SCHEDULER)
946  trace::printf (" {u ");
947 #endif
948  }
949 
957  inline
959  {
960 #if defined(OS_TRACE_RTOS_SCHEDULER)
961  trace::printf (" u} ");
962 #endif
963  locked (state_);
964  }
965 
971  constexpr
973  state_ (port::scheduler::state::init)
974  {
975  ;
976  }
977 
983  inline
985  {
986  ;
987  }
988 
994  inline void
996  {
997  state_ = scheduler::lock ();
998  }
999 
1007  inline bool
1009  {
1010  state_ = scheduler::lock ();
1011  return true;
1012  }
1013 
1019  inline void
1021  {
1022  scheduler::locked (state_);
1023  }
1024 
1025  namespace statistics
1026  {
1027 #if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES)
1028 
1045  {
1046  return context_switches_;
1047  }
1048 
1049 #endif /* defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CONTEXT_SWITCHES) */
1050 
1051 #if defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES)
1052 
1069  cpu_cycles (void)
1070  {
1071  return cpu_cycles_;
1072  }
1073 
1074 #endif /* defined(OS_INCLUDE_RTOS_STATISTICS_THREAD_CPU_CYCLES) */
1075 
1076  } /* namespace statistics */
1077 
1078  } /* namespace scheduler */
1079 
1080  // ========================================================================
1081 
1082  namespace interrupts
1083  {
1089  inline bool
1090  __attribute__((always_inline))
1092  {
1094  }
1095 
1101  inline
1102  __attribute__((always_inline))
1104  state_ (enter ())
1105  {
1106  ;
1107  }
1108 
1114  inline
1115  __attribute__((always_inline))
1117  {
1118  exit (state_);
1119  }
1120 
1126  inline state_t
1127  __attribute__((always_inline))
1128  critical_section::enter (void)
1129  {
1131  }
1132 
1138  inline void
1139  __attribute__((always_inline))
1141  {
1143  }
1144 
1145  // ======================================================================
1146 
1152  inline
1153  __attribute__((always_inline))
1155  state_ (enter ())
1156  {
1157  ;
1158  }
1159 
1165  inline
1166  __attribute__((always_inline))
1168  {
1169  exit (state_);
1170  }
1171 
1177  inline state_t
1178  __attribute__((always_inline))
1179  uncritical_section::enter (void)
1180  {
1182  }
1183 
1189  inline void
1190  __attribute__((always_inline))
1191  uncritical_section::exit (state_t state)
1192  {
1194  }
1195 
1196  // ======================================================================
1197 
1203  constexpr
1205  state_ (port::interrupts::state::init)
1206  {
1207  ;
1208  }
1209 
1215  inline
1216  __attribute__((always_inline))
1218  {
1219  ;
1220  }
1221 
1227  inline void
1228  __attribute__((always_inline))
1229  lockable::lock (void)
1230  {
1231  state_ = critical_section::enter ();
1232  }
1233 
1241  inline bool
1242  __attribute__((always_inline))
1243  lockable::try_lock (void)
1244  {
1245  state_ = critical_section::enter ();
1246  return true;
1247  }
1248 
1254  inline void
1255  __attribute__((always_inline))
1256  lockable::unlock (void)
1257  {
1258  critical_section::exit (state_);
1259  }
1260 
1261  // ========================================================================
1262  }
1263 
1264  } /* namespace rtos */
1265 } /* namespace os */
1266 
1267 // ----------------------------------------------------------------------------
1268 
1269 #endif /* __cplusplus */
1270 
1271 #endif /* CMSIS_PLUS_RTOS_OS_SCHED_H_ */
Scheduler standard locker.
Definition: os-sched.h:314
port::scheduler::state_t locked(port::scheduler::state_t state)
Lock/unlock the scheduler.
Definition: os-sched.h:899
port::scheduler::state_t unlock(void)
Unlock the scheduler.
Definition: os-sched.h:882
constexpr lockable()
Construct a lockable object instance.
Definition: os-sched.h:972
Scheduler uncritical section RAII helper.
Definition: os-sched.h:242
port::clock::timestamp_t timestamp_t
Type of variables holding clock time stamps.
Definition: os-clocks.h:81
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition: os-sched.h:1091
void exit(int code)
Definition: exit.c:78
uncritical_section()
Enter a critical section.
Definition: os-sched.h:942
port::scheduler::state_t lock(void)
Lock the scheduler.
Definition: os-sched.h:869
state_t locked(state_t state)
Lock/unlock the scheduler.
Definition: os-sched.h:899
void lock(void)
Lock the scheduler.
Definition: os-sched.h:995
Interrupts standard locker.
Definition: os-sched.h:699
~uncritical_section()
Exit a critical section.
Definition: os-sched.h:958
Interrupts critical section RAII helper.
Definition: os-sched.h:498
bool try_lock(void)
Try to lock the interrupts.
Definition: os-sched.h:1243
static rtos::interrupts::state_t enter(void)
System namespace.
~lockable()
Destruct the lockable object instance.
Definition: os-sched.h:984
void lock(void)
Lock the interrupts.
Definition: os-sched.h:1229
port::interrupts::state_t state_t
Type of variables holding interrupts statu codes.
Definition: os-decls.h:243
static void exit(rtos::interrupts::state_t state)
Standard thread.
Scheduler critical section RAII helper.
Definition: os-sched.h:170
void start(void)
Start the RTOS scheduler.
Definition: os-core.cpp:186
static void exit(rtos::interrupts::state_t state)
void unlock(void)
Unlock the interrupts.
Definition: os-sched.h:1256
bool started(void)
Check if the scheduler was started.
Definition: os-sched.h:827
static rtos::interrupts::state_t enter(void)
void unlock(void)
Unlock the scheduler.
Definition: os-sched.h:1020
port::scheduler::state_t state_t
Type of variables holding scheduler state codes.
Definition: os-decls.h:202
rtos::statistics::counter_t context_switches(void)
Get the total number of context switches.
Definition: os-sched.h:1044
bool preemptive(void)
Check if the scheduler is in preemptive mode.
Definition: os-sched.h:839
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition: trace.cpp:74
bool preemptive(void)
Check if the scheduler is in preemptive mode.
Definition: os-sched.h:839
static state_t enter(void)
Enter an interrupts critical section.
Definition: os-sched.h:1128
bool try_lock(void)
Try to lock the scheduler.
Definition: os-sched.h:1008
state_t lock(void)
Lock the scheduler.
Definition: os-sched.h:869
state_t unlock(void)
Unlock the scheduler.
Definition: os-sched.h:882
static void exit(state_t state)
Exit the interrupts critical section.
Definition: os-sched.h:1140
uint64_t counter_t
Type of variables holding context switches counters.
Definition: os-decls.h:217
uint32_t result_t
Type of values returned by RTOS functions.
Definition: os-decls.h:96
result_t initialize(void)
Initialise the RTOS scheduler.
Definition: os-core.cpp:157
critical_section()
Enter a critical section.
Definition: os-sched.h:911
~critical_section()
Exit a critical section.
Definition: os-sched.h:927
Interrupts critical section RAII helper.
Definition: os-sched.h:598
uint64_t duration_t
Type of variables holding durations in CPU cycles.
Definition: os-decls.h:222
bool in_handler_mode(void)
Check if the CPU is in handler mode.
Definition: os-sched.h:1091
rtos::statistics::duration_t cpu_cycles(void)
Get the total duration of all threads.
Definition: os-sched.h:1069