Orocos Real-Time Toolkit  2.9.0
fosi.h
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Mon Jun 10 14:42:55 CEST 2002 fosi.h
3 
4  fosi.h - description
5  -------------------
6  begin : Mon June 10 2002
7  copyright : (C) 2002 Peter Soetens
8  email : peter.soetens@mech.kuleuven.ac.be
9 
10 ***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18 
19 
25 #ifndef __FOSI_H
26 #define __FOSI_H
27 
28 #define HAVE_FOSI_API
29 
30 #ifdef _MSC_VER
31 #include <cstdio>
32 #include <cstdlib>
33 #include <cerrno>
34 #include <cstring>
35 #include <climits>
36 #include <cfloat>
37 #include <cassert>
38 #else // MINGW32
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <limits.h>
44 #include <float.h>
45 #include <assert.h>
46 #endif
47 
48 #include "../oro_limits.h"
49 #include "../../rtt-config.h"
50 
51  // Time Related
52 #ifdef _MSC_VER
53 #include <ctime>
54 #else // MINGW32
55 #include <sys/time.h>
56 #include <time.h>
57 #include <unistd.h>
58 #endif
59 
60 #ifdef __cplusplus
61 extern "C"
62 {
63 #endif
64 
65 #include "dlfcn.h"
66 
67  RTT_API unsigned int sleep(unsigned int seconds);
68 
69 #if __GNUC__ != 4
70  RTT_API int usleep(unsigned int us);
71 #endif
72 
73  typedef long long NANO_TIME;
74  typedef long long TICK_TIME;
75 
76  // TODO
77  const TICK_TIME InfiniteTicks = LLONG_MAX;
78  const NANO_TIME InfiniteNSecs = LLONG_MAX;
79  const double InfiniteSeconds = DBL_MAX;
80 
81 #define ORO_WAIT_ABS 0
83 #define ORO_WAIT_REL 1
86  typedef struct {
87  HANDLE handle;
88  DWORD threadId;
89 
90  NANO_TIME periodMark;
91  NANO_TIME period;
92 
93  int sched_type; // currently not used
94  int wait_policy;
95 
96  char* name;
97  } RTOS_TASK;
98 
99 #define ORO_SCHED_RT 0
100 #define ORO_SCHED_OTHER 1
102  //conflicts with another struct under MSVC
103  struct oro_timespec {
104  long tv_sec;
105  long tv_nsec;
106  };
107 
108  typedef struct oro_timespec TIME_SPEC;
109 
110  // high-resolution time to timespec
111  // hrt is in ticks
113  {
114  TIME_SPEC timevl;
115  timevl.tv_sec = (long)(hrt / 1000000000LL);
116  timevl.tv_nsec = (long)(hrt % 1000000000LL);
117  return timevl;
118  }
119 
121  {
122  LARGE_INTEGER freq;
123  LARGE_INTEGER ticks;
124  QueryPerformanceFrequency(&freq);
125  QueryPerformanceCounter(&ticks);
126 
127  return(NANO_TIME)(((double)ticks.QuadPart * 1000000000LL) / (double)freq.QuadPart);
128  }
129 
135  {
136  return rtos_get_time_ns();
137  }
138 
139  inline int win32_nanosleep(long long nano)
140  {
141  NANO_TIME start = rtos_get_time_ns();
142  timeBeginPeriod(1);
143  if (nano > 3000000L) Sleep((DWORD)(nano/1000000L) - 1);
144  timeEndPeriod(1);
145  while(rtos_get_time_ns() - start < nano) Sleep(0);
146  return 0;
147  }
148 
149  inline int rtos_nanosleep( const TIME_SPEC * rqtp, TIME_SPEC * rmtp )
150  {
151  return win32_nanosleep((NANO_TIME)rqtp->tv_sec * 1000000000LL + rqtp->tv_nsec);
152  }
153 
159  inline
160  long long nano2ticks( long long nano )
161  {
162  return nano;
163  }
164 
165  inline
166  long long ticks2nano( long long count )
167  {
168  return count;
169  }
170 
171  // Semaphore functions
172 
173  typedef HANDLE rt_sem_t;
174 
175  static inline int rtos_sem_init(rt_sem_t* m, int value )
176  {
177  *m = CreateSemaphore(NULL, value, 100000, NULL);
178  return (*m != NULL) ? 0 : -1;
179  }
180 
181  static inline int rtos_sem_destroy(rt_sem_t* m )
182  {
183  CloseHandle(*m);
184  return 0;
185  }
186 
187  static inline int rtos_sem_signal(rt_sem_t* m )
188  {
189  return (ReleaseSemaphore(*m, 1, NULL) == 0) ? -1 : 0;
190  }
191 
192  static inline int rtos_sem_wait(rt_sem_t* m )
193  {
194  return (WaitForSingleObject(*m, INFINITE) == WAIT_FAILED) ? -1 : 0;
195  }
196 
197  static inline int rtos_sem_trywait(rt_sem_t* m )
198  {
199  return (WaitForSingleObject(*m, 0) == WAIT_TIMEOUT) ? -1 : 0;
200  }
201 
202  static inline int rtos_sem_wait_timed(rt_sem_t* m, NANO_TIME delay )
203  {
204  return (WaitForSingleObject(*m, (DWORD)(delay/1000000)) == WAIT_TIMEOUT) ? -1 : 0;
205  }
206 
207  static inline int rtos_sem_wait_until(rt_sem_t* m, NANO_TIME abs_time )
208  {
209  if (abs_time < rtos_get_time_ns()) return -1;
210  NANO_TIME delay = abs_time - rtos_get_time_ns();
211  return rtos_sem_wait_timed(m, delay);
212  }
213 
214  static inline int rtos_sem_value(rt_sem_t* m )
215  {
216  long previous;
217 
218  switch (WaitForSingleObject(*m, 0))
219  {
220  case WAIT_OBJECT_0:
221  if (!ReleaseSemaphore(*m, 1, &previous)) return -1;
222  return previous + 1;
223  case WAIT_TIMEOUT: return 0;
224  default:
225  return -1;
226  }
227  }
228 
229  // Mutex functions
230 
231  typedef CRITICAL_SECTION rt_mutex_t;
232  typedef CRITICAL_SECTION rt_rec_mutex_t;
233 
234  static inline int rtos_mutex_init(rt_mutex_t* m)
235  {
236  InitializeCriticalSection(m);
237  return 0;
238  }
239 
240  static inline int rtos_mutex_destroy(rt_mutex_t* m )
241  {
242  DeleteCriticalSection(m);
243  return 0;
244  }
245 
246  static inline int rtos_mutex_rec_init(rt_rec_mutex_t* m)
247  {
248  return rtos_mutex_init(m);
249  }
250 
251  static inline int rtos_mutex_rec_destroy(rt_rec_mutex_t* m )
252  {
253  return rtos_mutex_destroy(m);
254  }
255 
256  static inline int rtos_mutex_lock( rt_mutex_t* m)
257  {
258  EnterCriticalSection(m);
259  return 0;
260  }
261 
262  static inline int rtos_mutex_unlock( rt_mutex_t* m)
263  {
264  LeaveCriticalSection(m);
265  return 0;
266  }
267 
268  static inline int rtos_mutex_trylock( rt_mutex_t* m)
269  {
270  if(TryEnterCriticalSection(m) != 0) return 0;
271  return -1;
272  }
273 
274  static inline int rtos_mutex_rec_trylock( rt_rec_mutex_t* m)
275  {
276  return rtos_mutex_trylock(m);
277  }
278 
279  static inline int rtos_mutex_lock_until( rt_mutex_t* m, NANO_TIME abs_time)
280  {
281  while (ticks2nano(rtos_get_time_ticks()) < abs_time)
282  if (rtos_mutex_trylock(m) == 0) return 0;
283  return -1;
284  }
285 
286  static inline int rtos_mutex_rec_lock_until( rt_mutex_t* m, NANO_TIME abs_time)
287  {
288  return rtos_mutex_lock_until(m, abs_time);
289  }
290 
291  static inline int rtos_mutex_rec_lock( rt_rec_mutex_t* m)
292  {
293  return rtos_mutex_lock(m);
294  }
295 
296  static inline int rtos_mutex_rec_unlock( rt_rec_mutex_t* m)
297  {
298  return rtos_mutex_unlock(m);
299  }
300 
301  static inline void rtos_enable_rt_warning()
302  {
303  }
304 
305  static inline void rtos_disable_rt_warning()
306  {
307  }
308 
309  // Condition variable implementation (SetEvent solution from ACE framework)
310 
311  typedef struct
312  {
313  enum { SIGNAL = 0, BROADCAST = 1, MAX_EVENTS = 2 };
314 
315  HANDLE events_[MAX_EVENTS];
316 
317  // Count of the number of waiters.
318  unsigned int waiters_count_;
319  CRITICAL_SECTION waiters_count_lock_;
320 
321  } rt_cond_t;
322 
323  static inline int rtos_cond_init(rt_cond_t *cond)
324  {
325  // Initialize the count to 0.
326  cond->waiters_count_ = 0;
327 
328  // Create an auto-reset event.
329  cond->events_[rt_cond_t::SIGNAL] = CreateEvent (NULL, // no security
330  FALSE, // auto-reset event
331  FALSE, // non-signaled initially
332  NULL); // unnamed
333 
334  // Create a manual-reset event.
335  cond->events_[rt_cond_t::BROADCAST] = CreateEvent (NULL, // no security
336  TRUE, // manual-reset
337  FALSE, // non-signaled initially
338  NULL); // unnamed
339 
340  InitializeCriticalSection(&cond->waiters_count_lock_);
341  return 0;
342  }
343 
344  static inline int rtos_cond_destroy(rt_cond_t *cond)
345  {
346  CloseHandle(cond->events_[rt_cond_t::SIGNAL]);
347  CloseHandle(cond->events_[rt_cond_t::BROADCAST]);
348 
349  DeleteCriticalSection(&cond->waiters_count_lock_);
350 
351  return 0;
352  }
353 
354  static inline int rtos_cond_timedwait_internal(rt_cond_t *cond, rt_mutex_t *external_mutex, DWORD ms)
355  {
356  // Avoid race conditions.
357  EnterCriticalSection (&cond->waiters_count_lock_);
358  cond->waiters_count_++;
359  LeaveCriticalSection (&cond->waiters_count_lock_);
360 
361  // It's ok to release the <external_mutex> here since Win32
362  // manual-reset events maintain state when used with
363  // <SetEvent>. This avoids the "lost wakeup" bug...
364  LeaveCriticalSection (external_mutex);
365 
366  // Wait for either event to become signaled due to <pthread_cond_signal>
367  // being called or <pthread_cond_broadcast> being called.
368  timeBeginPeriod(1);
369  int result = WaitForMultipleObjects (2, cond->events_, FALSE, ms);
370  timeEndPeriod(1);
371 
372  EnterCriticalSection (&cond->waiters_count_lock_);
373  cond->waiters_count_--;
374  bool last_waiter = result == WAIT_OBJECT_0 + rt_cond_t::BROADCAST && cond->waiters_count_ == 0;
375  LeaveCriticalSection (&cond->waiters_count_lock_);
376 
377  // Some thread called <pthread_cond_broadcast>.
378  if (last_waiter)
379  // We're the last waiter to be notified or to stop waiting, so
380  // reset the manual event.
381  ResetEvent (cond->events_[rt_cond_t::BROADCAST]);
382 
383  // Reacquire the <external_mutex>.
384  EnterCriticalSection (external_mutex);
385 
386  return 0;
387  }
388 
389  static inline int rtos_cond_timedwait(rt_cond_t *cond, rt_mutex_t *mutex, NANO_TIME abs_time)
390  {
391  return rtos_cond_timedwait_internal(cond, mutex, (DWORD)(abs_time / 1000000));
392  }
393 
394  static inline int rtos_cond_wait(rt_cond_t *cond, rt_mutex_t *mutex)
395  {
396  return rtos_cond_timedwait_internal(cond, mutex, INFINITE);
397  }
398 
399  static inline int rtos_cond_broadcast(rt_cond_t *cond)
400  {
401  // Avoid race conditions.
402  EnterCriticalSection (&cond->waiters_count_lock_);
403  bool have_waiters = cond->waiters_count_ > 0;
404  LeaveCriticalSection (&cond->waiters_count_lock_);
405 
406  if (have_waiters) SetEvent (cond->events_[rt_cond_t::BROADCAST]);
407 
408  return 0;
409  }
410 
411  static inline int rtos_cond_signal (rt_cond_t *cond)
412  {
413  // Avoid race conditions.
414  EnterCriticalSection (&cond->waiters_count_lock_);
415  bool have_waiters = cond->waiters_count_ > 0;
416  LeaveCriticalSection (&cond->waiters_count_lock_);
417 
418  if (have_waiters) SetEvent (cond->events_[rt_cond_t::SIGNAL]);
419 
420  return 0;
421  }
422 
423 #define rtos_printf printf
424 
425 int setenv(const char *name, const char *value, int overwrite);
426 
427 #ifdef __cplusplus
428 }
429 
430 #endif
431 #endif
int rtos_mutex_init(rt_mutex_t *m)
long long NANO_TIME
Definition: fosi.h:55
const double InfiniteSeconds
Definition: fosi.h:60
int rtos_mutex_rec_lock(rt_rec_mutex_t *m)
const TICK_TIME InfiniteTicks
Definition: fosi.h:58
int setenv(const char *name, const char *value, int overwrite)
Definition: fosi.cpp:64
int rtos_cond_destroy(rt_cond_t *cond)
NANO_TIME rtos_get_time_ns(void)
Get "system" time in nanoseconds.
Definition: fosi.h:113
int rtos_nanosleep(const TIME_SPEC *rqtp, TIME_SPEC *rmtp)
Definition: fosi.h:180
const NANO_TIME InfiniteNSecs
Definition: fosi.h:59
#define LLONG_MAX
Definition: oro_limits.h:47
int rtos_mutex_rec_init(rt_rec_mutex_t *m)
int rtos_sem_trywait(rt_sem_t *m)
int rtos_mutex_rec_trylock(rt_rec_mutex_t *m)
int rtos_sem_signal(rt_sem_t *m)
unsigned int waiters_count_
Definition: fosi.h:318
int sched_type
Definition: fosi.h:93
int rtos_cond_timedwait(rt_cond_t *cond, rt_mutex_t *mutex, NANO_TIME abs_time)
int win32_nanosleep(long long nano)
Definition: fosi.h:139
#define RTT_API
Definition: rtt-config.h:97
int rtos_cond_wait(rt_cond_t *cond, rt_mutex_t *mutex)
TIME_SPEC ticks2timespec(TICK_TIME hrt)
Definition: fosi.h:146
cyg_tick_count_t TICK_TIME
Definition: fosi.h:56
int rtos_mutex_unlock(rt_mutex_t *m)
HANDLE handle
Definition: fosi.h:87
int rtos_mutex_rec_unlock(rt_rec_mutex_t *m)
HANDLE events_[MAX_EVENTS]
Definition: fosi.h:315
void rtos_disable_rt_warning()
Disallows the RTOS to print a warning when we violate real-time constraints.
int rtos_sem_destroy(rt_sem_t *m)
pthread_cond_t rt_cond_t
Definition: fosi.h:296
int rtos_mutex_lock_until(rt_mutex_t *m, NANO_TIME abs_time)
long tv_nsec
Definition: fosi.h:105
RTT_API unsigned int sleep(unsigned int seconds)
Definition: fosi.cpp:51
int rtos_mutex_rec_lock_until(rt_rec_mutex_t *m, NANO_TIME abs_time)
int rtos_mutex_lock(rt_mutex_t *m)
long tv_sec
Definition: fosi.h:104
TICK_TIME rtos_get_time_ticks(void)
Get "system" time in ticks FIXME see https://proj.fmtc.be/orocos-bugzilla/show_bug.cgi?id=60
Definition: fosi.h:118
RTT_API int usleep(unsigned int us)
Definition: fosi.cpp:58
int rtos_mutex_trylock(rt_mutex_t *m)
NANO_TIME ticks2nano(TICK_TIME count)
Time conversions from system ticks to nano seconds.
Definition: fosi.h:107
cyg_recursive_mutex_t rt_rec_mutex_t
Definition: fosi.h:186
int rtos_sem_init(rt_sem_t *m, int value)
All these should return zero in case of succes.
DWORD threadId
Definition: fosi.h:88
TICK_TIME nano2ticks(NANO_TIME nano)
Time conversions from nano seconds to system ticks.
Definition: fosi.h:100
int rtos_mutex_destroy(rt_mutex_t *m)
int rtos_sem_value(rt_sem_t *m)
CRITICAL_SECTION waiters_count_lock_
Definition: fosi.h:319
struct MyTask RTOS_TASK
void rtos_enable_rt_warning()
Allows the RTOS to print a warning when we violate real-time constraints.
struct timespec TIME_SPEC
Definition: fosi.h:97
int rtos_cond_init(rt_cond_t *cond)
int rtos_sem_wait(rt_sem_t *m)
int rtos_cond_broadcast(rt_cond_t *cond)
cyg_sem_t rt_sem_t
Definition: fosi.h:131
int rtos_mutex_rec_destroy(rt_rec_mutex_t *m)
cyg_mutex_t rt_mutex_t
Definition: fosi.h:185