Go to the documentation of this file.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 #ifndef OS_FOSI_INTERNAL_HPP
00040 #define OS_FOSI_INTERNAL_HPP
00041 #define OROBLD_OS_LXRT_INTERNAL
00042
00043 #include <iostream>
00044 #include <sched.h>
00045 #include "os/ThreadInterface.hpp"
00046 #include "fosi.h"
00047 #include "../fosi_internal_interface.hpp"
00048 #include <sys/mman.h>
00049 #include <unistd.h>
00050 #include <sys/types.h>
00051 #include "../../rtt-config.h"
00052 #define INTERNAL_QUAL
00053
00054 #include <string.h>
00055
00056 #include "../../Logger.hpp"
00057
00058 namespace RTT
00059 {
00060 namespace os {
00061
00062 INTERNAL_QUAL int rtos_task_create_main(RTOS_TASK* main_task)
00063 {
00064 if ( geteuid() != 0 ) {
00065 std::cerr << "You are not root. This program requires that you are root." << std::endl;
00066 exit(1);
00067 }
00068
00069 #ifdef OROSEM_OS_LOCK_MEMORY
00070 int locktype = MCL_CURRENT;
00071 #ifdef OROSEM_OS_LOCK_MEMORY_FUTURE
00072 locktype |= MCL_FUTURE;
00073 #endif
00074
00075 int rv = mlockall(locktype);
00076 if ( rv != 0 ) {
00077 perror( "rtos_task_create_main: Could not lock memory using mlockall" );
00078 }
00079 #endif
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 unsigned long name = nam2num("main");
00090 while ( rt_get_adr( name ) != 0 )
00091 ++name;
00092
00093
00094 const char* tname = "main";
00095 main_task->name = strcpy( (char*)malloc( (strlen(tname) + 1) * sizeof(char)), tname);
00096
00097 if( !(main_task->rtaitask = rt_task_init(name, 10,0,0)) )
00098 {
00099 std::cerr << "Cannot rt_task_init() MainThread." << std::endl;
00100 exit(1);
00101 }
00102
00103 struct sched_param param;
00104
00105 param.sched_priority = sched_get_priority_max(SCHED_OTHER);
00106 if (param.sched_priority != -1 )
00107 sched_setscheduler( 0, SCHED_OTHER, ¶m);
00108
00109
00110 rt_task_use_fpu(main_task->rtaitask, 1);
00111
00112 #ifdef OROSEM_OS_LXRT_PERIODIC
00113 rt_set_periodic_mode();
00114 start_rt_timer( nano2count( NANO_TIME(ORODAT_OS_LXRT_PERIODIC_TICK*1000*1000*1000) ) );
00115 Logger::log() << Logger::Info << "RTAI Periodic Timer ticks at "<<ORODAT_OS_LXRT_PERIODIC_TICK<<" seconds." << Logger::endl;
00116 #else
00117
00118 rt_set_oneshot_mode();
00119
00120 #if defined(CONFIG_RTAI_VERSION_MINOR) && defined(CONFIG_RTAI_VERSION_MAJOR)
00121 # if CONFIG_RTAI_VERSION_MAJOR == 3 && CONFIG_RTAI_VERSION_MINOR == 0
00122 rt_preempt_always(1);
00123 # endif
00124 #else
00125 rt_preempt_always(1);
00126 #endif
00127 start_rt_timer(0);
00128 Logger::log() << Logger::Info << "RTAI Periodic Timer runs in preemptive 'one-shot' mode." << Logger::endl;
00129 #endif
00130 Logger::log() << Logger::Debug << "RTAI Task Created" << Logger::endl;
00131 return 0;
00132 }
00133
00134 INTERNAL_QUAL int rtos_task_delete_main(RTOS_TASK* main_task)
00135 {
00136
00137
00138 rt_task_delete(main_task->rtaitask);
00139 free(main_task->name);
00140 munlockall();
00141 return 0;
00142 }
00143
00144 struct RTAI_Thread
00145 {
00146 void *(*wrapper)(void*);
00147 void *data;
00148 RTOS_TASK* task;
00149 int priority;
00150 unsigned int tnum;
00151 };
00152
00153 INTERNAL_QUAL void* rtai_thread_wrapper( void * arg ) {
00154 RTAI_Thread* d = (RTAI_Thread*)arg;
00155 RTOS_TASK* task = d->task;
00156 void* data = d->data;
00157 int priority = d->priority;
00158 unsigned int tnum = d->tnum;
00159 void*(*wrapper)(void*) = d->wrapper;
00160 free( d );
00161
00162 if (!(task->rtaitask = rt_task_init(tnum, priority, 0, 0))) {
00163 std::cerr << "CANNOT INIT LXRT Thread " << task->name <<std::endl;
00164 std::cerr << "Exiting this thread." <<std::endl;
00165 exit(-1);
00166 }
00167
00168
00169 struct sched_param param;
00170 param.sched_priority = sched_get_priority_max(SCHED_OTHER);
00171 if (param.sched_priority != -1 )
00172 sched_setscheduler( 0, SCHED_OTHER, ¶m);
00173
00174
00175 rt_task_use_fpu(task->rtaitask, 1);
00176
00177
00178 rt_make_hard_real_time();
00179
00180 data = wrapper( data );
00181
00182
00183 rt_make_soft_real_time();
00184
00185 rt_task_delete(task->rtaitask);
00186 task->rtaitask = 0;
00187
00188 return data;
00189 }
00190
00191 INTERNAL_QUAL int rtos_task_create(RTOS_TASK* task,
00192 int priority,
00193 unsigned cpu_affinity,
00194 const char* name,
00195 int sched_type,
00196 size_t stack_size,
00197 void * (*start_routine)(void *),
00198 ThreadInterface* obj)
00199 {
00200 char taskName[7];
00201 if ( strlen(name) == 0 )
00202 name = "Thread";
00203 strncpy(taskName, name, 7);
00204 unsigned long task_num = nam2num( taskName );
00205 if ( rt_get_adr(nam2num( taskName )) != 0 ) {
00206 unsigned long nname = nam2num( taskName );
00207 while ( rt_get_adr( nname ) != 0 )
00208 ++nname;
00209 num2nam( nname, taskName);
00210 taskName[6] = 0;
00211 task_num = nname;
00212 }
00213
00214
00215 task->name = strcpy( (char*)malloc( (strlen(name)+1)*sizeof(char) ), name);
00216
00217
00218
00219 task->priority = priority;
00220
00221
00222 task->rtaitask = 0;
00223
00224 RTAI_Thread* rt = (RTAI_Thread*)malloc( sizeof(RTAI_Thread) );
00225 rt->priority = priority;
00226 rt->data = obj;
00227 rt->wrapper = start_routine;
00228 rt->task = task;
00229 rt->tnum = task_num;
00230 int retv = pthread_create(&(task->thread), 0,
00231 rtai_thread_wrapper, rt);
00232
00233 int timeout = 0;
00234 while ( task->rtaitask == 0 && ++timeout < 20)
00235 usleep(100000);
00236 return timeout < 20 ? retv : -1;
00237 }
00238
00239 INTERNAL_QUAL void rtos_task_yield(RTOS_TASK* mytask) {
00240 if (mytask->rtaitask == 0)
00241 return;
00242
00243 rt_task_yield();
00244 }
00245
00246 INTERNAL_QUAL int rtos_task_is_self(const RTOS_TASK* task) {
00247 RT_TASK* self = rt_buddy();
00248 if (self == 0)
00249 return -1;
00250 if ( self == task->rtaitask )
00251 return 1;
00252 return 0;
00253 }
00254
00255 INTERNAL_QUAL unsigned int rtos_task_get_pid(const RTOS_TASK* task)
00256 {
00257 return 0;
00258 }
00259
00260 INTERNAL_QUAL int rtos_task_check_scheduler(int* scheduler)
00261 {
00262 if (*scheduler != SCHED_LXRT_HARD && *scheduler != SCHED_LXRT_SOFT ) {
00263 log(Error) << "Unknown scheduler type." <<endlog();
00264 *scheduler = SCHED_LXRT_SOFT;
00265 return -1;
00266 }
00267 return 0;
00268 }
00269
00270 INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* t, int s) {
00271 if ( t->rtaitask == 0 || t->rtaitask != rt_buddy() ) {
00272 return -1;
00273 }
00274 if (rtos_task_check_scheduler(&s) == -1)
00275 return -1;
00276 if (s == SCHED_LXRT_HARD)
00277 rt_make_hard_real_time();
00278 else if ( s == SCHED_LXRT_SOFT)
00279 rt_make_soft_real_time();
00280 return 0;
00281 }
00282
00283 INTERNAL_QUAL int rtos_task_get_scheduler(const RTOS_TASK* t) {
00284 if ( rt_is_hard_real_time( t->rtaitask ) )
00285 return SCHED_LXRT_HARD;
00286 return SCHED_LXRT_SOFT;
00287 }
00288
00289 INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK* mytask, NANO_TIME nanosecs )
00290 {
00291 if (mytask->rtaitask == 0)
00292 return;
00293 if (rt_buddy() == mytask->rtaitask) {
00294
00295
00296 rtos_task_set_period(mytask,nanosecs);
00297 return;
00298 }
00299
00300 if (nanosecs == 0) {
00301
00302
00303 rt_task_suspend( mytask->rtaitask );
00304 rt_task_resume( mytask->rtaitask );
00305 }
00306 else {
00307
00308 rt_task_suspend( mytask->rtaitask );
00309 rt_task_make_periodic_relative_ns(mytask->rtaitask, 0, nanosecs);
00310 }
00311 }
00312
00313 INTERNAL_QUAL void rtos_task_set_period( RTOS_TASK* mytask, NANO_TIME nanosecs )
00314 {
00315 if (mytask->rtaitask == 0)
00316 return;
00317 if ( nanosecs == 0 )
00318 rt_set_period(mytask->rtaitask, 0 );
00319 else
00320 rt_set_period(mytask->rtaitask, nano2count( nanosecs ));
00321 }
00322
00323 INTERNAL_QUAL void rtos_task_set_wait_period_policy( RTOS_TASK* task, int policy )
00324 {
00325
00326 }
00327
00328 INTERNAL_QUAL int rtos_task_wait_period( RTOS_TASK* mytask )
00329 {
00330 if (mytask->rtaitask == 0)
00331 return -1;
00332
00333
00334 rt_task_wait_period();
00335 return 0;
00336 }
00337
00338 INTERNAL_QUAL void rtos_task_delete(RTOS_TASK* mytask) {
00339 if ( pthread_join((mytask->thread),0) != 0 )
00340 Logger::log() << Logger::Critical << "Failed to join "<< mytask->name <<"."<< Logger::endl;
00341
00342 free( mytask->name );
00343
00344 }
00345
00346 INTERNAL_QUAL int rtos_task_check_priority(int* scheduler, int* priority)
00347 {
00348 int ret = 0;
00349
00350 ret = rtos_task_check_scheduler(scheduler);
00351
00352
00353
00354 if (*priority < 0){
00355 log(Warning) << "Forcing priority ("<<*priority<<") of thread to 0." <<endlog();
00356 *priority = 0;
00357 ret = -1;
00358 }
00359 if (*priority > 255){
00360 log(Warning) << "Forcing priority ("<<*priority<<") of thread to 255." <<endlog();
00361 *priority = 255;
00362 ret = -1;
00363 }
00364 return ret;
00365 }
00366
00367 INTERNAL_QUAL int rtos_task_set_priority(RTOS_TASK * mytask, int priority)
00368 {
00369 int rv;
00370
00371 if (mytask->rtaitask == 0)
00372 return -1;
00373
00374
00375 rv = rt_change_prio( mytask->rtaitask, priority);
00376 if (rv == mytask->priority) {
00377 mytask->priority = priority;
00378 return 0;
00379 }
00380 return -1;
00381 }
00382
00383 INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* t)
00384 {
00385 return t->name;
00386 }
00387
00388 INTERNAL_QUAL int rtos_task_get_priority(const RTOS_TASK *t)
00389 {
00390 return t->priority;
00391 }
00392
00393 INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity)
00394 {
00395 return -1;
00396 }
00397
00398 INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task)
00399 {
00400 return ~0;
00401 }
00402 }
00403 }
00404 #undef INTERNAL_QUAL
00405 #endif