Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Wed Jan 18 14:11:39 CET 2006 fosi.h 00003 00004 fosi.h - description 00005 ------------------- 00006 begin : Wed January 18 2006 00007 copyright : (C) 2006 Peter Soetens 00008 email : peter.soetens@mech.kuleuven.be 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 #ifndef _XENO_FOSI_H 00040 #define _XENO_FOSI_H 00041 00042 #ifndef _XOPEN_SOURCE 00043 #define _XOPEN_SOURCE 600 // use all Posix features. 00044 #endif 00045 00046 #define HAVE_FOSI_API 00047 00048 #ifdef __cplusplus 00049 extern "C" { 00050 #endif 00051 00052 #include "../../rtt-config.h" 00053 00054 //Xenomai headers 00055 //#include <linux/types.h> 00056 // xenomai assumes presence of u_long 00057 #ifndef _GNU_SOURCE 00058 #define _GNU_SOURCE 00059 #endif 00060 #include <sys/mman.h> 00061 #include <sys/time.h> 00062 #include <unistd.h> 00063 #include <stdlib.h> 00064 #include <math.h> 00065 #include <stdio.h> 00066 #include <stdarg.h> 00067 #include <string.h> 00068 #include <signal.h> 00069 #include <getopt.h> 00070 #include <time.h> 00071 #include <limits.h> 00072 #include <float.h> 00073 #include "../oro_limits.h" 00074 00075 #include <xeno_config.h> // version number 00076 #include <native/task.h> 00077 #include <native/timer.h> 00078 #include <native/mutex.h> 00079 #include <native/sem.h> 00080 #include <native/cond.h> 00081 00082 // BC: support Xenomai < 2.3.0 00083 #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) < 2300 00084 #define rt_mutex_acquire rt_mutex_lock 00085 #define rt_mutex_release rt_mutex_unlock 00086 #endif 00087 // BC: support Xenomai < 2.5.0 00088 #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) >= 2500 00089 #define ORO_XENO_HAS_ACQUIRE_UNTIL 00090 #endif 00091 00092 00093 typedef RT_MUTEX rt_mutex_t; 00094 typedef RT_MUTEX rt_rec_mutex_t; 00095 typedef RT_SEM rt_sem_t; 00096 typedef RT_COND rt_cond_t; 00097 00098 // Time Related 00099 // 'S' -> Signed long long 00100 typedef SRTIME NANO_TIME; 00101 typedef SRTIME TICK_TIME; 00102 typedef struct timespec TIME_SPEC; 00103 typedef RT_TASK RTOS_XENO_TASK; 00104 00105 // Thread/Task related. 00106 typedef struct { 00107 char * name; 00108 RTOS_XENO_TASK xenotask; 00109 RTOS_XENO_TASK* xenoptr; 00110 int sched_type; 00111 } RTOS_TASK; 00112 00113 static const TICK_TIME InfiniteTicks = LONG_LONG_MAX; 00114 static const NANO_TIME InfiniteNSecs = LONG_LONG_MAX; 00115 static const double InfiniteSeconds = DBL_MAX; 00116 00117 #define SCHED_XENOMAI_HARD 0 00118 #define SCHED_XENOMAI_SOFT 1 00119 #define ORO_SCHED_RT 0 00120 #define ORO_SCHED_OTHER 1 00122 // hrt is in ticks 00123 static inline TIME_SPEC ticks2timespec(TICK_TIME hrt) 00124 { 00125 TIME_SPEC timevl; 00126 timevl.tv_sec = rt_timer_tsc2ns(hrt) / 1000000000LL; 00127 timevl.tv_nsec = rt_timer_tsc2ns(hrt) % 1000000000LL; 00128 return timevl; 00129 } 00130 00131 // hrt is in ticks 00132 static inline TICK_TIME timespec2ticks(const TIME_SPEC* ts) 00133 { 00134 return rt_timer_ns2tsc(ts->tv_nsec + ts->tv_sec*1000000000LL); 00135 } 00136 00137 // turn this on to have maximum detection of valid system calls. 00138 #ifdef OROSEM_OS_XENO_CHECK 00139 #define CHK_XENO_CALL() do { if(rt_task_self() == 0) { \ 00140 printf("RTT: XENO NOT INITIALISED IN THIS THREAD pid=%d,\n\ 00141 BUT TRIES TO INVOKE XENO FUNCTION >>%s<< ANYWAY\n", getpid(), __FUNCTION__ );\ 00142 assert( rt_task_self() != 0 ); }\ 00143 } while(0) 00144 #define CHK_XENO_PTR(ptr) do { if(ptr == 0) { \ 00145 printf("RTT: TRIED TO PASS NULL POINTER TO XENO IN THREAD pid=%d,\n\ 00146 IN TRYING TO INVOKE XENO FUNCTION >>%s<<\n", getpid(), __FUNCTION__ );\ 00147 assert( ptr != 0 ); }\ 00148 } while(0) 00149 #else 00150 #define CHK_XENO_CALL() 00151 #define CHK_XENO_PTR( a ) 00152 #endif 00153 00154 static inline NANO_TIME rtos_get_time_ns(void) { return rt_timer_ticks2ns(rt_timer_read()); } 00155 00156 static inline TICK_TIME rtos_get_time_ticks(void) { return rt_timer_tsc(); } 00157 00158 static inline TICK_TIME ticksPerSec(void) { return rt_timer_ns2tsc( 1000 * 1000 * 1000 ); } 00159 00160 // WARNING: Orocos 'ticks' are 'Xenomai tsc' and Xenomai `ticks' are not 00161 // used in the Orocos API. Thus Orocos uses `Xenomai tsc' and `Xenomai ns', 00162 // yet Xenomai requires `Xenomai ticks' at the interface 00163 // ==> do not use nano2ticks to convert to `Xenomai ticks' because it 00164 // converts to `Xenomai tsc'. 00165 static inline TICK_TIME nano2ticks(NANO_TIME t) { return rt_timer_ns2tsc(t); } 00166 static inline NANO_TIME ticks2nano(TICK_TIME t) { return rt_timer_tsc2ns(t); } 00167 00168 static inline int rtos_nanosleep(const TIME_SPEC *rqtp, TIME_SPEC *rmtp) 00169 { 00170 CHK_XENO_CALL(); 00171 RTIME ticks = rqtp->tv_sec * 1000000000LL + rqtp->tv_nsec; 00172 rt_task_sleep( rt_timer_ns2ticks(ticks) ); 00173 return 0; 00174 } 00175 00176 static inline int rtos_sem_init(rt_sem_t* m, int value ) 00177 { 00178 CHK_XENO_CALL(); 00179 return rt_sem_create( m, 0, value, S_PRIO); 00180 } 00181 00182 static inline int rtos_sem_destroy(rt_sem_t* m ) 00183 { 00184 CHK_XENO_CALL(); 00185 return rt_sem_delete( m ); 00186 } 00187 00188 static inline int rtos_sem_signal(rt_sem_t* m ) 00189 { 00190 CHK_XENO_CALL(); 00191 return rt_sem_v( m ); 00192 } 00193 00194 static inline int rtos_sem_wait(rt_sem_t* m ) 00195 { 00196 CHK_XENO_CALL(); 00197 return rt_sem_p( m, TM_INFINITE ); 00198 } 00199 00200 static inline int rtos_sem_trywait(rt_sem_t* m ) 00201 { 00202 CHK_XENO_CALL(); 00203 return rt_sem_p( m, TM_NONBLOCK); 00204 } 00205 00206 static inline int rtos_sem_value(rt_sem_t* m ) 00207 { 00208 CHK_XENO_CALL(); 00209 RT_SEM_INFO sinfo; 00210 if (rt_sem_inquire(m, &sinfo) == 0 ) { 00211 return sinfo.count; 00212 } 00213 return -1; 00214 } 00215 00216 static inline int rtos_sem_wait_timed(rt_sem_t* m, NANO_TIME delay ) 00217 { 00218 CHK_XENO_CALL(); 00219 return rt_sem_p(m, rt_timer_ns2ticks(delay) ) == 0 ? 0 : -1; 00220 } 00221 00222 static inline int rtos_sem_wait_until(rt_sem_t* m, NANO_TIME when ) 00223 { 00224 CHK_XENO_CALL(); 00225 return rt_sem_p(m, rt_timer_ns2ticks(when) - rt_timer_read() ) == 0 ? 0 : -1; 00226 } 00227 00228 static inline int rtos_mutex_init(rt_mutex_t* m) 00229 { 00230 CHK_XENO_CALL(); 00231 // a Xenomai mutex is always recursive 00232 return rt_mutex_create(m, 0); 00233 } 00234 00235 static inline int rtos_mutex_destroy(rt_mutex_t* m ) 00236 { 00237 CHK_XENO_CALL(); 00238 return rt_mutex_delete(m); 00239 } 00240 00241 static inline int rtos_mutex_rec_init(rt_mutex_t* m) 00242 { 00243 CHK_XENO_CALL(); 00244 // a Xenomai mutex is always recursive 00245 return rt_mutex_create(m, 0); 00246 } 00247 00248 static inline int rtos_mutex_rec_destroy(rt_mutex_t* m ) 00249 { 00250 CHK_XENO_CALL(); 00251 return rt_mutex_delete(m); 00252 } 00253 00254 static inline int rtos_mutex_lock( rt_mutex_t* m) 00255 { 00256 CHK_XENO_CALL(); 00257 return rt_mutex_acquire(m, TM_INFINITE ); 00258 } 00259 00260 static inline int rtos_mutex_trylock( rt_mutex_t* m) 00261 { 00262 CHK_XENO_CALL(); 00263 struct rt_mutex_info info; 00264 rt_mutex_inquire(m, &info ); 00265 #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) >= 2500 00266 if (info.locked) 00267 return 0; 00268 #else 00269 if (info.lockcnt) 00270 return 0; 00271 #endif 00272 // from here on: we're sure our thread didn't lock it 00273 // now check if any other thread locked it: 00274 return rt_mutex_acquire(m, TM_NONBLOCK); 00275 } 00276 00277 static inline int rtos_mutex_lock_until( rt_mutex_t* m, NANO_TIME abs_time) 00278 { 00279 CHK_XENO_CALL(); 00280 #if !defined(ORO_XENO_HAS_ACQUIRE_UNTIL) // see top of this file 00281 // calling the old style API 00282 return rt_mutex_acquire(m, rt_timer_ns2ticks(abs_time) - rt_timer_read() ); 00283 #else 00284 // new style API > 2.5.0 00285 return rt_mutex_acquire_until(m, rt_timer_ns2ticks(abs_time) ); 00286 #endif 00287 } 00288 00289 static inline int rtos_mutex_unlock( rt_mutex_t* m) 00290 { 00291 CHK_XENO_CALL(); 00292 return rt_mutex_release(m); 00293 } 00294 00295 static inline int rtos_mutex_rec_lock( rt_rec_mutex_t* m) 00296 { 00297 CHK_XENO_CALL(); 00298 return rt_mutex_acquire(m, TM_INFINITE ); 00299 } 00300 00301 static inline int rtos_mutex_rec_trylock( rt_rec_mutex_t* m) 00302 { 00303 CHK_XENO_CALL(); 00304 return rtos_mutex_trylock(m); 00305 } 00306 00307 static inline int rtos_mutex_rec_lock_until( rt_rec_mutex_t* m, NANO_TIME abs_time) 00308 { 00309 CHK_XENO_CALL(); 00310 return rtos_mutex_lock_until(m, abs_time); 00311 } 00312 00313 static inline int rtos_mutex_rec_unlock( rt_rec_mutex_t* m) 00314 { 00315 CHK_XENO_CALL(); 00316 return rt_mutex_release(m); 00317 } 00318 00319 static inline void rtos_enable_rt_warning() 00320 { 00321 CHK_XENO_CALL(); 00322 rt_task_set_mode(0, T_WARNSW, NULL); 00323 } 00324 00325 static inline void rtos_disable_rt_warning() 00326 { 00327 CHK_XENO_CALL(); 00328 rt_task_set_mode(T_WARNSW, 0, NULL); 00329 } 00330 00331 static inline int rtos_cond_init(rt_cond_t *cond) 00332 { 00333 CHK_XENO_CALL(); 00334 return rt_cond_create(cond, 0); 00335 } 00336 00337 static inline int rtos_cond_destroy(rt_cond_t *cond) 00338 { 00339 CHK_XENO_CALL(); 00340 return rt_cond_delete(cond); 00341 } 00342 00343 static inline int rtos_cond_wait(rt_cond_t *cond, rt_mutex_t *mutex) 00344 { 00345 CHK_XENO_CALL(); 00346 int ret = rt_cond_wait(cond, mutex, TM_INFINITE); 00347 if (ret == 0) 00348 return 0; 00349 return -1; 00350 } 00351 00352 static inline int rtos_cond_timedwait(rt_cond_t *cond, rt_mutex_t *mutex, NANO_TIME abs_time) 00353 { 00354 CHK_XENO_CALL(); 00355 // BC: support Xenomai < 2.5.0 00356 #if ((CONFIG_XENO_VERSION_MAJOR*1000)+(CONFIG_XENO_VERSION_MINOR*100)+CONFIG_XENO_REVISION_LEVEL) < 2500 00357 return rt_cond_wait(cond, mutex, rt_timer_ns2ticks(abs_time) - rt_timer_read() ); 00358 #else 00359 return rt_cond_wait_until(cond, mutex, rt_timer_ns2ticks(abs_time) ); 00360 #endif 00361 } 00362 00363 static inline int rtos_cond_broadcast(rt_cond_t *cond) 00364 { 00365 CHK_XENO_CALL(); 00366 return rt_cond_broadcast(cond); 00367 } 00368 00369 00370 #define rtos_printf printf 00371 00372 #ifdef __cplusplus 00373 } 00374 #endif 00375 00376 #endif