00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "../ThreadInterface.hpp"
00040 #include "fosi.h"
00041 #include "../fosi_internal_interface.hpp"
00042 #include "../../Logger.hpp"
00043 #include <cassert>
00044 #include <sys/time.h>
00045 #include <sys/resource.h>
00046 #include <iostream>
00047 #include <cstdlib>
00048 using namespace std;
00049
00050 #define INTERNAL_QUAL
00051
00052 namespace RTT
00053 { namespace os {
00054
00055 INTERNAL_QUAL int rtos_task_create_main(RTOS_TASK* main_task)
00056 {
00057 const char* name = "main";
00058 main_task->wait_policy = ORO_WAIT_ABS;
00059 main_task->name = strcpy( (char*)malloc( (strlen(name) + 1) * sizeof(char)), name);
00060 main_task->thread = pthread_self();
00061 pthread_attr_init( &(main_task->attr) );
00062 struct sched_param sp;
00063 sp.sched_priority=0;
00064
00065
00066 pthread_attr_setschedparam(&(main_task->attr), &sp);
00067 main_task->priority = sp.sched_priority;
00068 return 0;
00069 }
00070
00071 INTERNAL_QUAL int rtos_task_delete_main(RTOS_TASK* main_task)
00072 {
00073 pthread_attr_destroy( &(main_task->attr) );
00074 free(main_task->name);
00075 return 0;
00076 }
00077
00078 INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task,
00079 int priority,
00080 unsigned cpu_affinity,
00081 const char * name,
00082 int sched_type,
00083 size_t stack_size,
00084 void * (*start_routine)(void *),
00085 ThreadInterface* obj)
00086 {
00087 int rv;
00088 task->wait_policy = ORO_WAIT_ABS;
00089 rtos_task_check_priority( &sched_type, &priority );
00090
00091
00092 task->priority = priority;
00093
00094
00095 if ( strlen(name) == 0 )
00096 name = "Thread";
00097 task->name = strcpy( (char*)malloc( (strlen(name) + 1) * sizeof(char)), name);
00098
00099 if ( (rv = pthread_attr_init(&(task->attr))) != 0 ){
00100 return rv;
00101 }
00102
00103 if ( (rv = pthread_attr_setschedpolicy(&(task->attr), sched_type)) != 0){
00104 return rv;
00105 }
00106
00107 if (stack_size )
00108 if ( (rv = pthread_attr_setstacksize(&(task->attr), stack_size)) != 0){
00109 return rv;
00110 }
00111 pthread_attr_getschedpolicy(&(task->attr), &rv );
00112 assert( rv == sched_type );
00113
00114
00115
00116 struct sched_param sp;
00117 if (sched_type != SCHED_OTHER){
00118 sp.sched_priority=priority;
00119
00120 if ( (rv = pthread_attr_setschedparam(&(task->attr), &sp)) != 0 ){
00121 return rv;
00122 }
00123 }
00124 rv = pthread_create(&(task->thread), &(task->attr),
00125 start_routine, obj);
00126 log(Debug) <<"Created Posix thread "<< task->thread <<endlog();
00127
00128 rtos_task_set_cpu_affinity(task, cpu_affinity);
00129
00130 return rv;
00131 }
00132
00133 INTERNAL_QUAL void rtos_task_yield(RTOS_TASK* t) {
00134 #if 0
00135
00136
00137 NANO_TIME timeRemaining = 1000;
00138 TIME_SPEC ts( ticks2timespec( timeRemaining ) );
00139 rtos_nanosleep( &ts , NULL );
00140 #else
00141 int ret = sched_yield();
00142 if ( ret != 0)
00143 perror("rtos_task_yield");
00144 #endif
00145 }
00146
00147 INTERNAL_QUAL int rtos_task_is_self(const RTOS_TASK* task) {
00148 pthread_t self = pthread_self();
00149 if ( pthread_equal(self, task->thread) == 0 )
00150 return 0;
00151 return 1;
00152 }
00153
00154 INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* task, int sched_type) {
00155 int policy = -1;
00156 struct sched_param param;
00157
00158 if ( task && task->thread != 0 && rtos_task_check_scheduler( &sched_type) == -1 )
00159 return -1;
00160
00161 if (pthread_getschedparam(task->thread, &policy, ¶m) == 0) {
00162
00163 param.sched_priority = task->priority;
00164 rtos_task_check_priority( &sched_type, ¶m.sched_priority );
00165
00166 return pthread_setschedparam( task->thread, sched_type, ¶m);
00167 }
00168 return -1;
00169 }
00170
00171 INTERNAL_QUAL int rtos_task_get_scheduler(const RTOS_TASK* task) {
00172 int policy = -1;
00173 struct sched_param param;
00174
00175 if ( task && task->thread != 0 && pthread_getschedparam(task->thread, &policy, ¶m) == 0)
00176 return policy;
00177 return -1;
00178 }
00179
00180 INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK* mytask, NANO_TIME nanosecs )
00181 {
00182
00183 mytask->period = nanosecs;
00184
00185 mytask->periodMark = ticks2timespec( nano2ticks( rtos_get_time_ns() + nanosecs ) );
00186 }
00187
00188 INTERNAL_QUAL void rtos_task_set_period( RTOS_TASK* mytask, NANO_TIME nanosecs )
00189 {
00190 rtos_task_make_periodic(mytask, nanosecs);
00191 }
00192
00193 INTERNAL_QUAL void rtos_task_set_wait_period_policy( RTOS_TASK* task, int policy )
00194 {
00195 task->wait_policy = policy;
00196 }
00197
00198 INTERNAL_QUAL int rtos_task_wait_period( RTOS_TASK* task )
00199 {
00200 if ( task->period == 0 )
00201 return 0;
00202
00203
00204 NANO_TIME now = rtos_get_time_ns();
00205 NANO_TIME wake= task->periodMark.tv_sec * 1000000000LL + task->periodMark.tv_nsec;
00206
00207
00208 while ( clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &(task->periodMark), NULL) != 0 && errno == EINTR ) {
00209 errno = 0;
00210 }
00211
00212 if (task->wait_policy == ORO_WAIT_ABS)
00213 {
00214
00215
00216 TIME_SPEC ts = ticks2timespec( nano2ticks( task->period) );
00217
00218 NANO_TIME tn = (task->periodMark.tv_nsec + ts.tv_nsec);
00219 task->periodMark.tv_nsec = tn % 1000000000LL;
00220 task->periodMark.tv_sec += ts.tv_sec + tn / 1000000000LL;
00221 }
00222 else
00223 {
00224 TIME_SPEC ts = ticks2timespec( nano2ticks( task->period) );
00225 TIME_SPEC now = ticks2timespec( rtos_get_time_ns() );
00226 NANO_TIME tn = (now.tv_nsec + ts.tv_nsec);
00227 task->periodMark.tv_nsec = tn % 1000000000LL;
00228 task->periodMark.tv_sec = ts.tv_sec + now.tv_sec + tn / 1000000000LL;
00229 }
00230
00231 return now > wake ? -1 : 0;
00232 }
00233
00234 INTERNAL_QUAL void rtos_task_delete(RTOS_TASK* mytask) {
00235 pthread_join( mytask->thread, 0);
00236 pthread_attr_destroy( &(mytask->attr) );
00237 free(mytask->name);
00238 }
00239
00240 INTERNAL_QUAL int rtos_task_check_scheduler(int* scheduler)
00241 {
00242 if (*scheduler != SCHED_OTHER && geteuid() != 0 ) {
00243
00244
00245
00246 struct rlimit r;
00247 if ((0 != getrlimit(RLIMIT_RTPRIO, &r)) || (0 == r.rlim_cur))
00248 {
00249 log(Warning) << "Lowering scheduler type to SCHED_OTHER for non-privileged users.." <<endlog();
00250 *scheduler = SCHED_OTHER;
00251 return -1;
00252 }
00253 }
00254 if (*scheduler != SCHED_OTHER && *scheduler != SCHED_FIFO && *scheduler != SCHED_RR ) {
00255 log(Error) << "Unknown scheduler type." <<endlog();
00256 *scheduler = SCHED_OTHER;
00257 return -1;
00258 }
00259 return 0;
00260 }
00261
00262 INTERNAL_QUAL int rtos_task_check_priority(int* scheduler, int* priority)
00263 {
00264 int ret = 0;
00265
00266 ret = rtos_task_check_scheduler(scheduler);
00267
00268
00269 if (*scheduler == SCHED_OTHER) {
00270 if ( *priority != 0 ) {
00271 if (*priority != LowestPriority)
00272 log(Warning) << "Forcing priority ("<<*priority<<") of thread with SCHED_OTHER policy to 0." <<endlog();
00273 *priority = 0;
00274 ret = -1;
00275 }
00276 } else {
00277
00278 if (*priority <= 0){
00279 log(Warning) << "Forcing priority ("<<*priority<<") of thread with !SCHED_OTHER policy to 1." <<endlog();
00280 *priority = 1;
00281 ret = -1;
00282 }
00283 if (*priority > 99){
00284 log(Warning) << "Forcing priority ("<<*priority<<") of thread with !SCHED_OTHER policy to 99." <<endlog();
00285 *priority = 99;
00286 ret = -1;
00287 }
00288
00289 if ( geteuid() != 0 )
00290 {
00291 struct rlimit r;
00292 if (0 == getrlimit(RLIMIT_RTPRIO, &r))
00293 {
00294 if (*priority > (int)r.rlim_cur)
00295 {
00296 log(Warning) << "Forcing priority ("<<*priority<<") of thread with !SCHED_OTHER policy to the pam_limit of " << r.rlim_cur <<endlog();
00297 *priority = r.rlim_cur;
00298 ret = -1;
00299 }
00300 }
00301 else
00302 {
00303
00304 *priority = 1;
00305 ret = -1;
00306 }
00307 }
00308 }
00309 return ret;
00310 }
00311
00312 INTERNAL_QUAL int rtos_task_set_priority(RTOS_TASK * task, int priority)
00313 {
00314 int policy = 0;
00315 struct sched_param param;
00316
00317 if( task && task->thread != 0 && pthread_getschedparam(task->thread, &policy, ¶m) == 0) {
00318 if ( rtos_task_check_priority( &policy, &priority ) != 0 )
00319 return -1;
00320 param.sched_priority = priority;
00321 task->priority = priority;
00322
00323 return pthread_setschedparam( task->thread, policy, ¶m);
00324 }
00325 return -1;
00326 }
00327
00328 INTERNAL_QUAL int rtos_task_get_priority(const RTOS_TASK *task)
00329 {
00330
00331 int policy = 0;
00332 struct sched_param param;
00333
00334 if ( task == 0 )
00335 return -1;
00336 if ( task->thread == 0 || pthread_getschedparam(task->thread, &policy, ¶m) != 0)
00337 return task->priority;
00338 return param.sched_priority;
00339 }
00340
00341 INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity)
00342 {
00343 if( task && task->thread != 0) {
00344 cpu_set_t cs;
00345 CPU_ZERO(&cs);
00346 for(unsigned i = 0; i < sizeof(cpu_affinity); i++)
00347 {
00348 if(cpu_affinity & (1 << i)) { CPU_SET(i, &cs); }
00349 }
00350 return pthread_setaffinity_np(task->thread, sizeof(cs), &cs);
00351 }
00352 return -1;
00353 }
00354
00355 INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task)
00356 {
00357 if( task && task->thread != 0) {
00358 unsigned cpu_affinity = 0;
00359 cpu_set_t cs;
00360 pthread_getaffinity_np(task->thread, sizeof(cs), &cs);
00361 for(unsigned i = 0; i < sizeof(cpu_affinity); i++)
00362 {
00363 if(CPU_ISSET(i, &cs)) { cpu_affinity |= (1 << i); }
00364 }
00365 return cpu_affinity;
00366 }
00367 return ~0;
00368 }
00369
00370 INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* task)
00371 {
00372 return task->name;
00373 }
00374
00375 }
00376 }
00377 #undef INTERNAL_QUAL