priority_pos.cpp
Go to the documentation of this file.
00001 
00008 /*****************************************************************************
00009 ** Platform Check
00010 *****************************************************************************/
00011 
00012 #include <ecl/config/ecl.hpp>
00013 #if defined(ECL_IS_POSIX)
00014 
00015 /*****************************************************************************
00016 ** Includes
00017 *****************************************************************************/
00018 
00019 #include <iostream>
00020 #include <unistd.h>
00021 #include <ecl/errors/handlers.hpp>
00022 #include "../../include/ecl/threads/priority_pos.hpp"
00023 
00024 /*****************************************************************************
00025 ** Namespaces
00026 *****************************************************************************/
00027 
00028 namespace ecl {
00029 
00030 /*****************************************************************************
00031 ** Using
00032 *****************************************************************************/
00033 
00034 using std::ostringstream;
00035 
00036 /*****************************************************************************
00037 ** Implementation [Process]
00038 *****************************************************************************/
00039 
00040 bool set_priority(Priority priority_level) ecl_throw_decl(StandardException)
00041 {
00042     /*************************************************************************
00043      * Real time priority exception. Run this with absolute priority rather
00044      * than the 'niceness' values. We use Round Robin scheduling here, the
00045      * alternative is Fifo so we can get some automatic scheduling if we
00046      * want it.
00047      *
00048      * Priority levels usually range from 1 to 99, but we map them virtually
00049      * to system built-ins just in case. The virtual map only uses a few
00050      * levels of priority as shown below.
00051      *
00052      * RealTimePriority1 = priority_min [lowest]
00053      * RealTimePriority2 = priority_min + priority_range/10
00054      * RealTimePriority3 = priority_min + 2*priority_range/10
00055      * RealTimePriority4 = priority_min + 3*priority_range/10 [highest]
00056      *
00057     *************************************************************************/
00058     if ( priority_level >= RealTimePriority1 ) {
00059         #if _POSIX_PRIORITY_SCHEDULING > 0
00060             int rr_min = sched_get_priority_min(SCHED_RR); int rr_max = sched_get_priority_max(SCHED_RR);
00061             if ( ( rr_min == -1 ) || (rr_max == -1) ) {
00062                 ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
00063                 return false;
00064             }
00065             ecl_try {
00066                 // usually exception will put it into a catch, otherwise we return false if it fails.
00067                 if ( !threads::set_real_time_priority(SCHED_RR,rr_min+(priority_level - RealTimePriority1)*(rr_max - rr_min)/10) ) {
00068                         return false;
00069                 }
00070             } ecl_catch(StandardException &e ) {
00071                 ecl_throw(StandardException(e)); // Rethrow
00072             }
00073         #else
00074             ecl_throw(StandardException(LOC,NotSupportedError,"Your version of posix does not support real time priority scheduling for process management."));
00075             return false;
00076         #endif
00077         return true;
00078     }
00079 
00080     /*************************************************************************
00081     ** Regular priority levels using 'niceness'. Lower values usually give
00082     ** the process higher importance (-20 to 20 usually). This is an
00083     ** indicator to the scheduler on how to bias the process's dynamic
00084     ** scheduling priority which can be seen when you do a 'top'.
00085     *************************************************************************/
00086     int return_value = 0;
00087 
00088     switch (priority_level) {
00089         case CriticalPriority : {
00090             return_value = setpriority(PRIO_PROCESS,0,PRIO_MIN);
00091             break;
00092         }
00093         case HighPriority : {
00094             setpriority(PRIO_PROCESS,0,PRIO_MIN + (PRIO_MAX-PRIO_MIN)/4);
00095             break;
00096         }
00097         case NormalPriority : {
00098             setpriority(PRIO_PROCESS,0,PRIO_MIN + (PRIO_MAX-PRIO_MIN)/2);
00099             break;
00100         }
00101         case LowPriority : {
00102             setpriority(PRIO_PROCESS,0,PRIO_MIN + 3*(PRIO_MAX-PRIO_MIN)/4);
00103             break;
00104         }
00105         case BackgroundPriority : {
00106             setpriority(PRIO_PROCESS,0,PRIO_MAX);
00107             break;
00108         }
00109         default : {
00110             // RealTimePriority# already handled, Default and Unknown -> do nothing.
00111             break;
00112         }
00113     }
00114     if ( return_value == -1 ) {
00115         ecl_throw(threads::throwPriorityException(LOC));
00116         return false;
00117     }
00118     return true;
00119 }
00120 
00121 Priority get_priority() ecl_throw_decl(StandardException)
00122 {
00123     /******************************************
00124     ** Check for Scheduling Policy (Trad/RT)
00125     *******************************************/
00126     #if _POSIX_PRIORITY_SCHEDULING > 0
00127         int scheduler = sched_getscheduler(0);
00128         switch ( scheduler ) {
00129             case ( -1 ) : {
00130                 ecl_throw(threads::throwPriorityException(LOC));
00131                 return UnknownPriority;
00132                 break;
00133             }
00134             case ( SCHED_OTHER ) : {
00135                 // We just want the niceness, get it outside of this switch.
00136                 break;
00137             }
00138             case ( SCHED_RR ) : { // Realtime priorities.
00139                 /******************************************
00140                 ** Check RealTime Priority Level
00141                 *******************************************/
00142                 sched_param param;
00143                 if ( sched_getparam(0,&param) != 0 ) {
00144                     ecl_throw(threads::throwPriorityException(LOC));
00145                     return UnknownPriority;
00146                 }
00147                 int rr_min = sched_get_priority_min(SCHED_RR);
00148                 int rr_max = sched_get_priority_max(SCHED_RR);
00149                 if ( ( rr_min == -1 ) || (rr_max == -1) ) {
00150                     ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
00151                     return UnknownPriority;
00152                 }
00153                 if ( param.sched_priority >= rr_min + 3*(rr_max-rr_min)/10 ) {
00154                     return RealTimePriority4;
00155                 } else if ( param.sched_priority >= rr_min + 2*(rr_max-rr_min)/10 ) {
00156                     return RealTimePriority3;
00157                 } else if ( param.sched_priority >= rr_min + (rr_max-rr_min)/10 ) {
00158                     return RealTimePriority2;
00159                 } else {
00160                     return RealTimePriority1;
00161                 }
00162                 break;
00163             }
00164             case ( SCHED_FIFO ) : { return UnknownPriority; } // We dont use this one.
00165                         #if defined(SCHED_BATCH) // Didn't turn up on an old gcc3 with an arm pax270 board.
00166                 case ( SCHED_BATCH ) : { return UnknownPriority; } // We dont use this one.
00167                         #endif
00168             default : { return UnknownPriority; } // Shouldn't ever reach here, but we might pick up new policies that we dont use here.
00169         }
00170     #endif
00171     /******************************************
00172     ** Check traditional priority niceness
00173     *******************************************/
00174     switch ( getpriority(PRIO_PROCESS,0) ) {
00175         case (PRIO_MIN) : { return CriticalPriority; }
00176         case (PRIO_MIN + (PRIO_MAX-PRIO_MIN)/4) : { return HighPriority; }
00177         case (PRIO_MIN + (PRIO_MAX-PRIO_MIN)/2) : { return NormalPriority; }
00178         case (PRIO_MIN + 3*(PRIO_MAX-PRIO_MIN)/4) : { return LowPriority; }
00179         case (PRIO_MAX) : { return BackgroundPriority; }
00180         default : return NormalPriority;
00181     }
00182 
00183 }
00184 /*****************************************************************************
00185 ** Implementation [Debugging]
00186 *****************************************************************************/
00187 
00188 std::string print_priority_diagnostics() ecl_throw_decl(StandardException) {
00189 
00190     ostringstream ostream;
00191 
00192     ostream << "\n";
00193     ostream << "***********************************************************\n";
00194     ostream << "*                  System Statistics\n";
00195     ostream << "***********************************************************\n";
00196     ostream << "\n";
00197 
00198         #if _POSIX_PRIORITY_SCHEDULING > 0
00199                 int rr_min = sched_get_priority_min(SCHED_RR);
00200                 int rr_max = sched_get_priority_max(SCHED_RR);
00201                 if ( ( rr_min == -1 ) || (rr_max == -1) ) {
00202                         ecl_throw(StandardException(LOC,NotSupportedError,"The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max]."));
00203                         return std::string("The posix SCHED_RR policy is not available on this system [sched_get_priority_min/max].");
00204                 }
00205                 ostream << "Real Time Priorities [Low,High]............[" << rr_min << "," << rr_max << "]\n";
00206         #endif
00207     ostream << "Niceness [Low,High]........................[" << PRIO_MAX << "," << PRIO_MIN << "]\n";
00208     ostream << "\n";
00209     ostream << "***********************************************************\n";
00210     ostream << "*                 Priority Statistics\n";
00211     ostream << "***********************************************************\n";
00212     ostream << "\n";
00213     #if _POSIX_PRIORITY_SCHEDULING > 0
00214                 int scheduler = sched_getscheduler(0);
00215                 switch ( scheduler ) {
00216                         case ( -1 ) : {
00217                                 ecl_throw(threads::throwPriorityException(LOC));
00218                                 return std::string("Call to sched_getscheduler failed.");
00219                         }
00220                         case ( SCHED_OTHER ) : {
00221                                 ostream << "Scheduler..................................SCHED_OTHER" << "\n";
00222                                 break;
00223                         }
00224                         case ( SCHED_RR ) : {
00225                                 ostream << "Scheduler..................................SCHED_RR [RT]" << "\n";
00226                                 break;
00227                         }
00228                         case ( SCHED_FIFO ) : {
00229                                 ostream << "Scheduler..................................SCHED_FIFO [RT]" << "\n";
00230                                 break;
00231                         }
00232 #if defined(SCHED_BATCH)
00233                         case ( SCHED_BATCH ) : {
00234                                 ostream << "Scheduler..................................SCHED_BATCH" << "\n";
00235                                 break;
00236                         }
00237 #endif
00238                         default : {
00239                                 ostream << "Scheduler..................................Unknown" << "\n";
00240                                 break;
00241                         }
00242                 }
00243     #endif
00244     switch ( get_priority() ) {
00245         case ( BackgroundPriority ) : {
00246             ostream << "Priority...................................Background\n";
00247             break;
00248         }
00249         case ( LowPriority ) : {
00250             ostream << "Priority...................................Low\n";
00251             break;
00252         }
00253         case ( NormalPriority ) : {
00254             ostream << "Priority...................................Normal\n";
00255             break;
00256         }
00257         case ( HighPriority ) : {
00258             ostream << "Priority...................................High\n";
00259             break;
00260         }
00261         case ( CriticalPriority ) : {
00262             ostream << "Priority...................................Critical\n";
00263             break;
00264         }
00265         case ( RealTimePriority4 ) : {
00266             ostream << "Priority...................................RealTime4\n";
00267             break;
00268         }
00269         case ( RealTimePriority3 ) : {
00270             ostream << "Priority...................................RealTime3\n";
00271             break;
00272         }
00273         case ( RealTimePriority2 ) : {
00274             ostream << "Priority...................................RealTime2\n";
00275             break;
00276         }
00277         case ( RealTimePriority1 ) : {
00278             ostream << "Priority...................................RealTime1\n";
00279             break;
00280         }
00281         case ( DefaultPriority ) : {
00282             ostream << "Priority...................................Default (Inherited)\n";
00283             break;
00284         }
00285         case ( UnknownPriority ) : {
00286             ostream << "Priority...................................Unknown\n";
00287             break;
00288         }
00289     }
00290     return ostream.str();
00291 }
00292 
00293 
00294 /*****************************************************************************
00295 ** Hidden Implementations
00296 *****************************************************************************/
00297 
00298 namespace threads {
00299 
00300 bool set_real_time_priority(int policy,int priority_level) ecl_throw_decl(StandardException) {
00301 
00302         #if _POSIX_PRIORITY_SCHEDULING > 0
00303                 ostringstream ostream;
00304 
00305                 /*********************
00306                 ** Exception Throwing
00307                 **********************/
00308                 if ( priority_level < sched_get_priority_min(policy) ) {
00309                         ostream << "The realtime process priority requested was smaller than the minimum value permitted[";
00310                         ostream << sched_get_priority_min(policy) << "]\n";
00311                         ecl_throw(StandardException(LOC,OutOfRangeError, ostream.str()));
00312                         return false;
00313                 } else if (priority_level > sched_get_priority_max(policy) ) {
00314                         ostream << "The realtime process priority requested was greater than the maximum value permitted[";
00315                         ostream << sched_get_priority_max(policy) << "]\n";
00316                         ecl_throw(StandardException(LOC,OutOfRangeError, ostream.str()));
00317                         return false;
00318                 }
00319 
00320                 /*********************
00321                 ** Configuration
00322                 **********************/
00323                 sched_param schedule_parameters;
00324                 schedule_parameters.sched_priority = priority_level;
00325                 if ( sched_setscheduler(0, policy, &schedule_parameters) == -1 ) {
00326                         ecl_throw(throwPriorityException(LOC));
00327                 }
00328                 return true;
00329         #else
00330         ecl_throw(StandardException(LOC,ecl::NotSupportedError,"Your version of posix does not support real time priority scheduling for process management."));
00331         return false;
00332         #endif
00333 }
00334 } // namespace threads
00335 }; // namespace ecl
00336 
00337 #endif /* ECL_IS_POSIX */


ecl_threads
Author(s): Daniel Stonier (d.stonier@gmail.com)
autogenerated on Thu Jan 2 2014 11:12:47