$search
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,¶m) != 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 */