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 int rtos_task_check_scheduler(int* scheduler)
00256 {
00257 if (*scheduler != SCHED_LXRT_HARD && *scheduler != SCHED_LXRT_SOFT ) {
00258 log(Error) << "Unknown scheduler type." <<endlog();
00259 *scheduler = SCHED_LXRT_SOFT;
00260 return -1;
00261 }
00262 return 0;
00263 }
00264
00265 INTERNAL_QUAL int rtos_task_set_scheduler(RTOS_TASK* t, int s) {
00266 if ( t->rtaitask == 0 || t->rtaitask != rt_buddy() ) {
00267 return -1;
00268 }
00269 if (rtos_task_check_scheduler(&s) == -1)
00270 return -1;
00271 if (s == SCHED_LXRT_HARD)
00272 rt_make_hard_real_time();
00273 else if ( s == SCHED_LXRT_SOFT)
00274 rt_make_soft_real_time();
00275 return 0;
00276 }
00277
00278 INTERNAL_QUAL int rtos_task_get_scheduler(const RTOS_TASK* t) {
00279 if ( rt_is_hard_real_time( t->rtaitask ) )
00280 return SCHED_LXRT_HARD;
00281 return SCHED_LXRT_SOFT;
00282 }
00283
00284 INTERNAL_QUAL void rtos_task_make_periodic(RTOS_TASK* mytask, NANO_TIME nanosecs )
00285 {
00286 if (mytask->rtaitask == 0)
00287 return;
00288 if (rt_buddy() == mytask->rtaitask) {
00289
00290
00291 rtos_task_set_period(mytask,nanosecs);
00292 return;
00293 }
00294
00295 if (nanosecs == 0) {
00296
00297
00298 rt_task_suspend( mytask->rtaitask );
00299 rt_task_resume( mytask->rtaitask );
00300 }
00301 else {
00302
00303 rt_task_suspend( mytask->rtaitask );
00304 rt_task_make_periodic_relative_ns(mytask->rtaitask, 0, nanosecs);
00305 }
00306 }
00307
00308 INTERNAL_QUAL void rtos_task_set_period( RTOS_TASK* mytask, NANO_TIME nanosecs )
00309 {
00310 if (mytask->rtaitask == 0)
00311 return;
00312 if ( nanosecs == 0 )
00313 rt_set_period(mytask->rtaitask, 0 );
00314 else
00315 rt_set_period(mytask->rtaitask, nano2count( nanosecs ));
00316 }
00317
00318 INTERNAL_QUAL void rtos_task_set_wait_period_policy( RTOS_TASK* task, int policy )
00319 {
00320
00321 }
00322
00323 INTERNAL_QUAL int rtos_task_wait_period( RTOS_TASK* mytask )
00324 {
00325 if (mytask->rtaitask == 0)
00326 return -1;
00327
00328
00329 rt_task_wait_period();
00330 return 0;
00331 }
00332
00333 INTERNAL_QUAL void rtos_task_delete(RTOS_TASK* mytask) {
00334 if ( pthread_join((mytask->thread),0) != 0 )
00335 Logger::log() << Logger::Critical << "Failed to join "<< mytask->name <<"."<< Logger::endl;
00336
00337 free( mytask->name );
00338
00339 }
00340
00341 INTERNAL_QUAL int rtos_task_check_priority(int* scheduler, int* priority)
00342 {
00343 int ret = 0;
00344
00345 ret = rtos_task_check_scheduler(scheduler);
00346
00347
00348
00349 if (*priority < 0){
00350 log(Warning) << "Forcing priority ("<<*priority<<") of thread to 0." <<endlog();
00351 *priority = 0;
00352 ret = -1;
00353 }
00354 if (*priority > 255){
00355 log(Warning) << "Forcing priority ("<<*priority<<") of thread to 255." <<endlog();
00356 *priority = 255;
00357 ret = -1;
00358 }
00359 return ret;
00360 }
00361
00362 INTERNAL_QUAL int rtos_task_set_priority(RTOS_TASK * mytask, int priority)
00363 {
00364 int rv;
00365
00366 if (mytask->rtaitask == 0)
00367 return -1;
00368
00369
00370 rv = rt_change_prio( mytask->rtaitask, priority);
00371 if (rv == mytask->priority) {
00372 mytask->priority = priority;
00373 return 0;
00374 }
00375 return -1;
00376 }
00377
00378 INTERNAL_QUAL const char * rtos_task_get_name(const RTOS_TASK* t)
00379 {
00380 return t->name;
00381 }
00382
00383 INTERNAL_QUAL int rtos_task_get_priority(const RTOS_TASK *t)
00384 {
00385 return t->priority;
00386 }
00387
00388 INTERNAL_QUAL int rtos_task_set_cpu_affinity(RTOS_TASK * task, unsigned cpu_affinity)
00389 {
00390 return -1;
00391 }
00392
00393 INTERNAL_QUAL unsigned rtos_task_get_cpu_affinity(const RTOS_TASK *task)
00394 {
00395 return ~0;
00396 }
00397 }
00398 }
00399 #undef INTERNAL_QUAL
00400 #endif