Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 copyright : (C) 2008 Klaas Gadeyne 00003 email : firstname dot lastname at gmail dot com 00004 00005 *************************************************************************** 00006 * * 00007 * This program is free software; you can redistribute it and/or modify * 00008 * it under the terms of the GNU General Public License as published by * 00009 * the Free Software Foundation; either version 2 of the License, or * 00010 * (at your option) any later version. * 00011 * * 00012 ***************************************************************************/ 00013 00014 00015 #ifndef __FOSI_H 00016 #define __FOSI_H 00017 00018 #ifndef _XOPEN_SOURCE 00019 #define _XOPEN_SOURCE 600 // use all Posix features. 00020 #endif 00021 00022 #define HAVE_FOSI_API 00023 00024 #ifdef __cplusplus 00025 extern "C" 00026 { 00027 #endif 00028 00029 00030 #include <stdio.h> 00031 #include <pthread.h> 00032 #include <mach/mach_init.h> 00033 #include <mach/task.h> 00034 00035 #include <errno.h> 00036 00037 #include <limits.h> 00038 #include <float.h> 00039 #include <assert.h> 00040 00041 typedef long long NANO_TIME; 00042 typedef long long TICK_TIME; 00043 00044 static const TICK_TIME InfiniteTicks = LLONG_MAX; 00045 static const NANO_TIME InfiniteNSecs = LLONG_MAX; 00046 static const double InfiniteSeconds = DBL_MAX; 00047 00048 #define ORO_WAIT_ABS 0 00050 #define ORO_WAIT_REL 1 00053 typedef struct { 00054 pthread_t thread; 00055 pthread_attr_t attr; 00056 00057 NANO_TIME periodMark; 00058 NANO_TIME period; 00059 00060 char* name; 00061 00062 int priority; 00063 int wait_policy; 00064 } RTOS_TASK; 00065 00066 00067 #define ORO_SCHED_RT SCHED_FIFO 00068 #define ORO_SCHED_OTHER SCHED_OTHER 00070 /* 00071 * Time Related stuff 00072 */ 00073 #include <sys/time.h> 00074 #include <time.h> 00075 #include <unistd.h> 00076 00077 typedef struct timespec TIME_SPEC; 00078 00079 /* fake clock_gettime for systems like darwin */ 00080 #define CLOCK_REALTIME 0 00081 static inline int clock_gettime(int clk_id /*ignored*/, struct timespec *tp) 00082 { 00083 struct timeval now; 00084 int rv = gettimeofday(&now, NULL); 00085 if (rv != 0){ 00086 tp->tv_sec = 0; 00087 tp->tv_nsec = 0; 00088 return rv; 00089 } 00090 tp->tv_sec = now.tv_sec; 00091 tp->tv_nsec = now.tv_usec * 1000; 00092 return 0; 00093 } 00094 00095 // high-resolution time to timespec 00096 static inline TIME_SPEC ticks2timespec(TICK_TIME hrt) 00097 { 00098 TIME_SPEC timevl; 00099 timevl.tv_sec = hrt / 1000000000LL; 00100 timevl.tv_nsec = hrt % 1000000000LL; 00101 return timevl; 00102 } 00103 00104 static inline NANO_TIME rtos_get_time_ns( void ) 00105 { 00106 TIME_SPEC tv; 00107 clock_gettime(CLOCK_REALTIME, &tv); 00108 // we can not include the C++ Time.hpp header ! 00109 #ifdef __cplusplus 00110 return NANO_TIME( tv.tv_sec ) * 1000000000LL + NANO_TIME( tv.tv_nsec ); 00111 #else 00112 return ( NANO_TIME ) ( tv.tv_sec * 1000000000LL ) + ( NANO_TIME ) ( tv.tv_nsec ); 00113 #endif 00114 } 00115 00120 static inline NANO_TIME rtos_get_time_ticks() 00121 { 00122 return rtos_get_time_ns(); 00123 } 00124 00125 static inline int rtos_nanosleep( const TIME_SPEC * rqtp, TIME_SPEC * rmtp ) 00126 { 00127 // return usleep(rqtp->tv_nsec/1000L); 00128 return nanosleep( rqtp, rmtp ); 00129 } 00130 00131 static inline long long nano2ticks( long long nano ) 00132 { 00133 return nano; 00134 } 00135 00136 static inline long long ticks2nano( long long count ) 00137 { 00138 return count; 00139 } 00140 00141 /* 00142 * Semaphore functions 00143 * See 00144 * http://developer.apple.com/documentation/Darwin/Conceptual/KernelProgramming/synchronization/chapter_15_section_2.html 00145 */ 00146 #include <mach/semaphore.h> 00147 typedef semaphore_t rt_sem_t; 00148 00149 static inline int rtos_sem_init(rt_sem_t* m, int value ) 00150 { 00151 return semaphore_create(mach_task_self(), m, SYNC_POLICY_FIFO, value); 00152 } 00153 00154 static inline int rtos_sem_destroy(rt_sem_t* m ) 00155 { 00156 return semaphore_destroy(mach_task_self(), *m); 00157 } 00158 00159 static inline int rtos_sem_signal(rt_sem_t* m ) 00160 { 00161 return semaphore_signal(*m); 00162 } 00163 00164 static inline int rtos_sem_wait(rt_sem_t* m ) 00165 { 00166 return semaphore_wait(*m); 00167 } 00168 00169 static inline int rtos_sem_wait_timed(rt_sem_t* m, NANO_TIME delay ) 00170 { 00171 TIME_SPEC delayvl = ticks2timespec(delay); 00172 mach_timespec_t mach_delayvl = { delayvl.tv_sec, delayvl.tv_nsec }; 00173 00174 return semaphore_timedwait( *m, mach_delayvl); 00175 } 00176 00177 static inline int rtos_sem_trywait(rt_sem_t* m ) 00178 { 00179 return rtos_sem_wait_timed(m,0); 00180 } 00181 00182 static inline int rtos_sem_wait_until(rt_sem_t* m, NANO_TIME abs_time ) 00183 { 00184 TIME_SPEC timevl, delayvl; 00185 TIME_SPEC arg_time = ticks2timespec( abs_time ); 00186 clock_gettime(CLOCK_REALTIME, &timevl); 00187 00189 00190 // calculate delay from abs_time 00191 delayvl.tv_sec = arg_time.tv_sec - timevl.tv_sec; 00192 delayvl.tv_nsec = arg_time.tv_nsec - timevl.tv_nsec; 00193 // tv_nsec is signed long in 10.6 (see sys/_structs.h) 00194 if ( delayvl.tv_nsec >= 1000000000) { 00195 ++delayvl.tv_sec; 00196 delayvl.tv_nsec -= 1000000000; 00197 } 00198 if ( delayvl.tv_nsec < 0) { 00199 --delayvl.tv_sec; 00200 delayvl.tv_nsec += 1000000000; 00201 } 00202 00203 assert( 0 <= delayvl.tv_sec); 00204 assert( 0 <= delayvl.tv_nsec); 00205 assert( delayvl.tv_nsec < 1000000000 ); 00206 00207 mach_timespec_t mach_delayvl = { delayvl.tv_sec, delayvl.tv_nsec }; 00208 int rc = semaphore_timedwait( *m, mach_delayvl); 00209 // map to return values from gnulinux, and expected by the calling layer 00210 return (KERN_OPERATION_TIMED_OUT == rc ? -1 : 0); 00211 } 00212 00213 // semaphore_value is not supported on darwin 00214 /* static inline int rtos_sem_value(rt_sem_t* m ) */ 00215 /* { */ 00216 /* int val = 0; */ 00217 /* if ( sem_getvalue(m, &val) == 0) */ 00218 /* return val; */ 00219 /* return -1; */ 00220 /* } */ 00221 00222 // Mutex functions - support only those needed by TLSF 00223 // opaque type 00224 typedef struct rt_mutex_impl_t rt_mutex_impl_t; 00225 // type created by tlsf.c (must work in C, not C++ code) 00226 typedef rt_mutex_impl_t* rt_mutex_t; 00227 int rtos_mutex_init(rt_mutex_t* m); 00228 int rtos_mutex_destroy(rt_mutex_t* m); 00229 int rtos_mutex_lock( rt_mutex_t* m); 00230 int rtos_mutex_unlock( rt_mutex_t* m); 00231 00232 static inline void rtos_enable_rt_warning() 00233 { 00234 } 00235 00236 static inline void rtos_disable_rt_warning() 00237 { 00238 } 00239 00240 00241 #define rtos_printf printf 00242 00243 #ifdef __cplusplus 00244 } 00245 00246 #endif 00247 #endif