priority_pos.cpp
Go to the documentation of this file.
1 
8 /*****************************************************************************
9 ** Platform Check
10 *****************************************************************************/
11 
12 #include <ecl/config/ecl.hpp>
13 #if defined(ECL_IS_POSIX)
14 
15 /*****************************************************************************
16 ** Includes
17 *****************************************************************************/
18 
19 #include <iostream>
20 #include <unistd.h>
21 #include <ecl/errors/handlers.hpp>
22 #include "../../include/ecl/threads/priority_pos.hpp"
23 
24 /*****************************************************************************
25 ** Namespaces
26 *****************************************************************************/
27 
28 namespace ecl {
29 
30 /*****************************************************************************
31 ** Using
32 *****************************************************************************/
33 
34 using std::ostringstream;
35 
36 /*****************************************************************************
37 ** Implementation [Process]
38 *****************************************************************************/
39 
40 bool set_priority(Priority priority_level)
41 {
42  /*************************************************************************
43  * Real time priority exception. Run this with absolute priority rather
44  * than the 'niceness' values. We use Round Robin scheduling here, the
45  * alternative is Fifo so we can get some automatic scheduling if we
46  * want it.
47  *
48  * Priority levels usually range from 1 to 99, but we map them virtually
49  * to system built-ins just in case. The virtual map only uses a few
50  * levels of priority as shown below.
51  *
52  * RealTimePriority1 = priority_min [lowest]
53  * RealTimePriority2 = priority_min + priority_range/10
54  * RealTimePriority3 = priority_min + 2*priority_range/10
55  * RealTimePriority4 = priority_min + 3*priority_range/10 [highest]
56  *
57  *************************************************************************/
58  if ( priority_level >= RealTimePriority1 ) {
59  #if _POSIX_PRIORITY_SCHEDULING > 0
60  int rr_min = sched_get_priority_min(SCHED_RR); int rr_max = sched_get_priority_max(SCHED_RR);
61  if ( ( rr_min == -1 ) || (rr_max == -1) ) {
62  ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
63  return false;
64  }
65  ecl_try {
66  // usually exception will put it into a catch, otherwise we return false if it fails.
67  if ( !threads::set_real_time_priority(SCHED_RR,rr_min+(priority_level - RealTimePriority1)*(rr_max - rr_min)/10) ) {
68  return false;
69  }
70  } ecl_catch(StandardException &e ) {
71  ecl_throw(StandardException(e)); // Rethrow
72  }
73  #else
74  ecl_throw(StandardException(LOC,NotSupportedError,"Your version of posix does not support real time priority scheduling for process management."));
75  return false;
76  #endif
77  return true;
78  }
79 
80  /*************************************************************************
81  ** Regular priority levels using 'niceness'. Lower values usually give
82  ** the process higher importance (-20 to 20 usually). This is an
83  ** indicator to the scheduler on how to bias the process's dynamic
84  ** scheduling priority which can be seen when you do a 'top'.
85  *************************************************************************/
86  int return_value = 0;
87 
88  switch (priority_level) {
89  case CriticalPriority : {
90  return_value = setpriority(PRIO_PROCESS,0,PRIO_MIN);
91  break;
92  }
93  case HighPriority : {
94  setpriority(PRIO_PROCESS,0,PRIO_MIN + (PRIO_MAX-PRIO_MIN)/4);
95  break;
96  }
97  case NormalPriority : {
98  setpriority(PRIO_PROCESS,0,PRIO_MIN + (PRIO_MAX-PRIO_MIN)/2);
99  break;
100  }
101  case LowPriority : {
102  setpriority(PRIO_PROCESS,0,PRIO_MIN + 3*(PRIO_MAX-PRIO_MIN)/4);
103  break;
104  }
105  case BackgroundPriority : {
106  setpriority(PRIO_PROCESS,0,PRIO_MAX);
107  break;
108  }
109  default : {
110  // RealTimePriority# already handled, Default and Unknown -> do nothing.
111  break;
112  }
113  }
114  if ( return_value == -1 ) {
115  ecl_debug_throw(threads::throwPriorityException(LOC));
116  return false;
117  }
118  return true;
119 }
120 
121 Priority get_priority()
122 {
123  /******************************************
124  ** Check for Scheduling Policy (Trad/RT)
125  *******************************************/
126  #if _POSIX_PRIORITY_SCHEDULING > 0
127  int scheduler = sched_getscheduler(0);
128  switch ( scheduler ) {
129  case ( -1 ) : {
130  ecl_debug_throw(threads::throwPriorityException(LOC));
131  return UnknownPriority;
132  break;
133  }
134  case ( SCHED_OTHER ) : {
135  // We just want the niceness, get it outside of this switch.
136  break;
137  }
138  case ( SCHED_RR ) : { // Realtime priorities.
139  /******************************************
140  ** Check RealTime Priority Level
141  *******************************************/
142  sched_param param;
143  if ( sched_getparam(0,&param) != 0 ) {
144  ecl_debug_throw(threads::throwPriorityException(LOC));
145  return UnknownPriority;
146  }
147  int rr_min = sched_get_priority_min(SCHED_RR);
148  int rr_max = sched_get_priority_max(SCHED_RR);
149  if ( ( rr_min == -1 ) || (rr_max == -1) ) {
150  ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
151  return UnknownPriority;
152  }
153  if ( param.sched_priority >= rr_min + 3*(rr_max-rr_min)/10 ) {
154  return RealTimePriority4;
155  } else if ( param.sched_priority >= rr_min + 2*(rr_max-rr_min)/10 ) {
156  return RealTimePriority3;
157  } else if ( param.sched_priority >= rr_min + (rr_max-rr_min)/10 ) {
158  return RealTimePriority2;
159  } else {
160  return RealTimePriority1;
161  }
162  break;
163  }
164  case ( SCHED_FIFO ) : { return UnknownPriority; } // We dont use this one.
165  #if defined(SCHED_BATCH) // Didn't turn up on an old gcc3 with an arm pax270 board.
166  case ( SCHED_BATCH ) : { return UnknownPriority; } // We dont use this one.
167  #endif
168  default : { return UnknownPriority; } // Shouldn't ever reach here, but we might pick up new policies that we dont use here.
169  }
170  #endif
171  /******************************************
172  ** Check traditional priority niceness
173  *******************************************/
174  switch ( getpriority(PRIO_PROCESS,0) ) {
175  case (PRIO_MIN) : { return CriticalPriority; }
176  case (PRIO_MIN + (PRIO_MAX-PRIO_MIN)/4) : { return HighPriority; }
177  case (PRIO_MIN + (PRIO_MAX-PRIO_MIN)/2) : { return NormalPriority; }
178  case (PRIO_MIN + 3*(PRIO_MAX-PRIO_MIN)/4) : { return LowPriority; }
179  case (PRIO_MAX) : { return BackgroundPriority; }
180  default : return NormalPriority;
181  }
182 
183 }
184 /*****************************************************************************
185 ** Implementation [Debugging]
186 *****************************************************************************/
187 
188 std::string print_priority_diagnostics() {
189 
190  ostringstream ostream;
191 
192  ostream << "\n";
193  ostream << "***********************************************************\n";
194  ostream << "* System Statistics\n";
195  ostream << "***********************************************************\n";
196  ostream << "\n";
197 
198  #if _POSIX_PRIORITY_SCHEDULING > 0
199  int rr_min = sched_get_priority_min(SCHED_RR);
200  int rr_max = sched_get_priority_max(SCHED_RR);
201  if ( ( rr_min == -1 ) || (rr_max == -1) ) {
202  ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
203  return std::string("The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max].");
204  }
205  ostream << "Real Time Priorities [Low,High]............[" << rr_min << "," << rr_max << "]\n";
206  #endif
207  ostream << "Niceness [Low,High]........................[" << PRIO_MAX << "," << PRIO_MIN << "]\n";
208  ostream << "\n";
209  ostream << "***********************************************************\n";
210  ostream << "* Priority Statistics\n";
211  ostream << "***********************************************************\n";
212  ostream << "\n";
213  #if _POSIX_PRIORITY_SCHEDULING > 0
214  int scheduler = sched_getscheduler(0);
215  switch ( scheduler ) {
216  case ( -1 ) : {
217  ecl_debug_throw(threads::throwPriorityException(LOC));
218  return std::string("Call to sched_getscheduler failed.");
219  }
220  case ( SCHED_OTHER ) : {
221  ostream << "Scheduler..................................SCHED_OTHER" << "\n";
222  break;
223  }
224  case ( SCHED_RR ) : {
225  ostream << "Scheduler..................................SCHED_RR [RT]" << "\n";
226  break;
227  }
228  case ( SCHED_FIFO ) : {
229  ostream << "Scheduler..................................SCHED_FIFO [RT]" << "\n";
230  break;
231  }
232 #if defined(SCHED_BATCH)
233  case ( SCHED_BATCH ) : {
234  ostream << "Scheduler..................................SCHED_BATCH" << "\n";
235  break;
236  }
237 #endif
238  default : {
239  ostream << "Scheduler..................................Unknown" << "\n";
240  break;
241  }
242  }
243  #endif
244  switch ( get_priority() ) {
245  case ( BackgroundPriority ) : {
246  ostream << "Priority...................................Background\n";
247  break;
248  }
249  case ( LowPriority ) : {
250  ostream << "Priority...................................Low\n";
251  break;
252  }
253  case ( NormalPriority ) : {
254  ostream << "Priority...................................Normal\n";
255  break;
256  }
257  case ( HighPriority ) : {
258  ostream << "Priority...................................High\n";
259  break;
260  }
261  case ( CriticalPriority ) : {
262  ostream << "Priority...................................Critical\n";
263  break;
264  }
265  case ( RealTimePriority4 ) : {
266  ostream << "Priority...................................RealTime4\n";
267  break;
268  }
269  case ( RealTimePriority3 ) : {
270  ostream << "Priority...................................RealTime3\n";
271  break;
272  }
273  case ( RealTimePriority2 ) : {
274  ostream << "Priority...................................RealTime2\n";
275  break;
276  }
277  case ( RealTimePriority1 ) : {
278  ostream << "Priority...................................RealTime1\n";
279  break;
280  }
281  case ( DefaultPriority ) : {
282  ostream << "Priority...................................Default (Inherited)\n";
283  break;
284  }
285  case ( UnknownPriority ) : {
286  ostream << "Priority...................................Unknown\n";
287  break;
288  }
289  }
290  return ostream.str();
291 }
292 
293 
294 /*****************************************************************************
295 ** Hidden Implementations
296 *****************************************************************************/
297 
298 namespace threads {
299 
300 bool set_real_time_priority(int policy,int priority_level) {
301 
302  #if _POSIX_PRIORITY_SCHEDULING > 0
303  ostringstream ostream;
304 
305  /*********************
306  ** Exception Throwing
307  **********************/
308  if ( priority_level < sched_get_priority_min(policy) ) {
309  ostream << "The realtime process priority requested was smaller than the minimum value permitted[";
310  ostream << sched_get_priority_min(policy) << "]\n";
311  ecl_throw(StandardException(LOC,OutOfRangeError, ostream.str()));
312  return false;
313  } else if (priority_level > sched_get_priority_max(policy) ) {
314  ostream << "The realtime process priority requested was greater than the maximum value permitted[";
315  ostream << sched_get_priority_max(policy) << "]\n";
316  ecl_throw(StandardException(LOC,OutOfRangeError, ostream.str()));
317  return false;
318  }
319 
320  /*********************
321  ** Configuration
322  **********************/
323  sched_param schedule_parameters;
324  schedule_parameters.sched_priority = priority_level;
325  if ( sched_setscheduler(0, policy, &schedule_parameters) == -1 ) {
326  ecl_debug_throw(throwPriorityException(LOC));
327  return false;
328  }
329  return true;
330  #else
331  ecl_throw(StandardException(LOC,ecl::NotSupportedError,"Your version of posix does not support real time priority scheduling for process management."));
332  return false;
333  #endif
334 }
335 } // namespace threads
336 }; // namespace ecl
337 
338 #endif /* ECL_IS_POSIX */
ecl::RealTimePriority2
@ RealTimePriority2
Definition: priority_common.hpp:51
ecl_try
#define ecl_try
ecl::UnknownPriority
@ UnknownPriority
Definition: priority_common.hpp:44
ecl::HighPriority
@ HighPriority
Definition: priority_common.hpp:48
ecl::LowPriority
@ LowPriority
Definition: priority_common.hpp:46
ecl::DefaultPriority
@ DefaultPriority
Definition: priority_common.hpp:43
handlers.hpp
ecl::CriticalPriority
@ CriticalPriority
Definition: priority_common.hpp:49
ecl_catch
#define ecl_catch(exception)
ecl::NormalPriority
@ NormalPriority
Definition: priority_common.hpp:47
ecl_throw
#define ecl_throw(exception)
ecl::RealTimePriority1
@ RealTimePriority1
Definition: priority_common.hpp:50
ecl::RealTimePriority3
@ RealTimePriority3
Definition: priority_common.hpp:52
ecl::NotSupportedError
NotSupportedError
ecl::BackgroundPriority
@ BackgroundPriority
Definition: priority_common.hpp:45
ecl::OutOfRangeError
OutOfRangeError
ecl::RealTimePriority4
@ RealTimePriority4
Definition: priority_common.hpp:53
ecl
Embedded control libraries.
ecl::Priority
Priority
Shared abstraction of the scheduling priorities.
Definition: priority_common.hpp:36
ecl_debug_throw
#define ecl_debug_throw(exception)


ecl_threads
Author(s): Daniel Stonier
autogenerated on Wed Mar 2 2022 00:16:43