po_hi_time.c 4.74 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*
 * This is a part of PolyORB-HI-C distribution, a minimal
 * middleware written for generated code from AADL models.
 * You should use it with the Ocarina toolsuite.
 *
 * For more informations, please visit http://ocarina.enst.fr
 *
 * Copyright (C) 2007-2008, GET-Telecom Paris.
 */

#include <time.h>
#include <errno.h>

#include <po_hi_config.h>
#include <po_hi_time.h>
#include <po_hi_returns.h>
17
18
#include <po_hi_debug.h>

julien.delange's avatar
julien.delange committed
19
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
20
21
22
23
#include <pthread.h>
#elif defined (RTEMS_PURE)
#include <bsp.h>
#endif 
24

25
#if defined (POSIX) && defined (NEED_CLOCK_GETTIME)
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <sys/time.h>
int clock_gettime(int clk_id, struct timespec *tp)
{
   struct timeval now;
   int rv = gettimeofday(&now, NULL);

   if (rv != 0) 
   {
      return rv;
   }

   tp->tv_sec = now.tv_sec;
   tp->tv_nsec = now.tv_usec * 1000;

   return 0;
}
#endif


int __po_hi_get_time (__po_hi_time_t* mytime)
{
julien.delange's avatar
julien.delange committed
47
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
48
49
50
51
52
53
   struct timespec ts;

   if (clock_gettime (CLOCK_REALTIME, &ts)!=0)
   {
      return (__PO_HI_ERROR_CLOCK);
   }
54
55
56
   
   mytime->sec    = ts.tv_sec;
   mytime->nsec   = ts.tv_nsec;
57
58

   return (__PO_HI_SUCCESS);
59
60
61
62
63
64
65
66
#elif defined (RTEMS_PURE)
   rtems_time_of_day    current_time;

   if (rtems_clock_get (RTEMS_CLOCK_GET_TOD, &current_time) != RTEMS_SUCCESSFUL)
   {
      __DEBUGMSG ("Error when trying to get the clock on RTEMS\n");
   }

67
   mytime->sec  = _TOD_To_seconds (&current_time);
68
   mytime->nsec =  current_time.ticks * rtems_configuration_get_microseconds_per_tick() * 1000;
69
70
71

   return (__PO_HI_SUCCESS);
#elif defined (XENO_NATIVE)
72
73
   mytime->sec  = rt_timer_tsc2ns (rt_timer_read ()) / 1000000000;
   mytime->nsec =  rt_timer_tsc2ns (rt_timer_read ()) - (mytime->sec * 1000000000);
74
75
76
77
   return (__PO_HI_SUCCESS);
#else
   return (__PO_HI_UNAVAILABLE);
#endif
78
79
}

80
int __po_hi_add_times (__po_hi_time_t* result, const __po_hi_time_t* left, const __po_hi_time_t* right)
81
{
82
83
84
85
86
87
88
89
   result->sec    = left->sec + right->sec;
   result->nsec   = left->nsec + right->nsec;
   if (result->nsec > 1000000000)
   {
      result->sec = result->sec + 1;
      result->nsec = result->nsec - 1000000000;
   }
   return 1;
90
91
}

92
int __po_hi_seconds (__po_hi_time_t* time, const __po_hi_uint32_t seconds)
93
{
94
95
96
   time->sec    = seconds;
   time->nsec   = 0;
   return 1;
97
98
}

99
int __po_hi_milliseconds (__po_hi_time_t* time, const __po_hi_uint32_t milliseconds)
100
{
101
102
103
   time->sec    = milliseconds / 1000;
   time->nsec   = (milliseconds - (time->sec * 1000)) * 1000000;
   return 1;
104
105
}

106
int __po_hi_microseconds (__po_hi_time_t* time, const __po_hi_uint32_t microseconds)
107
{
108
109
110
   time->sec    = microseconds / 1000000;
   time->nsec   = (microseconds - (time->sec * 1000000)) * 1000;
   return 1;
111
112
}

113
int __po_hi_delay_until (const __po_hi_time_t* time)
114
{
julien.delange's avatar
julien.delange committed
115
#if defined (POSIX) || defined (RTEMS_POSIX) || defined (XENO_POSIX)
116
117
118
119
120
   pthread_mutex_t mutex;
   pthread_cond_t cond;
   struct timespec timer;
   int ret;

121
   timer.tv_sec = time->sec;
122

123
   timer.tv_nsec = time->nsec;
124
125
126

   if (pthread_mutex_init (&mutex, NULL) != 0)
   {
jdelange's avatar
jdelange committed
127
      __PO_HI_DEBUG_INFO ("[TIME] __po_hi_delay_until: cannot initialize mutex\n");
128
129
130
131
132
      return (__PO_HI_ERROR_PTHREAD_MUTEX);
   }

   if (pthread_cond_init (&cond, NULL) != 0)
   {
jdelange's avatar
jdelange committed
133
      __PO_HI_DEBUG_INFO ("[TIME] __po_hi_delay_until: cannot initialize cond\n");
134
135
136
137
138
139
140
141
142
143
      pthread_mutex_destroy (&mutex);
      return (__PO_HI_ERROR_PTHREAD_COND);
   }

   pthread_mutex_lock (&mutex);

   ret = pthread_cond_timedwait (&cond, &mutex, &timer);

   if ( (ret != 0) && (ret != ETIMEDOUT))
   {
jdelange's avatar
jdelange committed
144
      __PO_HI_DEBUG_INFO ("[TIME] __po_hi_delay_until: delay until error\n");
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
      ret = __PO_HI_ERROR_PTHREAD_COND;
   }
   else
   {
      ret = __PO_HI_SUCCESS;
   }

   pthread_mutex_unlock (&mutex);

   if (pthread_cond_destroy (&cond) != 0)
   {
      ret = __PO_HI_ERROR_PTHREAD_COND;
   }

   if (pthread_mutex_destroy (&mutex) != 0)
   {
      ret = __PO_HI_ERROR_PTHREAD_MUTEX;
   }
   return (ret);
164
165
#elif defined (RTEMS_PURE)
   return (__PO_HI_UNAVAILABLE);
166
167
#elif defined (XENO_NATIVE)
  int ret;
168
  ret =  rt_task_sleep_until (rt_timer_ns2tsc ( (time->sec * 1000000000) +  time->nsec));
169
170
  if (ret)
  {
171
      __DEBUGMSG ("[TASK] Error in rt_task_sleep_until, ret=%d\n", ret);
172
173
174
      return (__PO_HI_ERROR_PTHREAD_COND);
  }
  return (__PO_HI_SUCCESS);
175
176
177
#else
   return (__PO_HI_UNAVAILABLE);
#endif
178
}
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

int __po_hi_time_is_greater (const __po_hi_time_t* value, const __po_hi_time_t* limit)
{
   if (value->sec > limit->sec)
   {
      return 1;
   }
   if (value->sec == limit->sec)
   {
      if (value->nsec > limit->nsec)
      {
         return 1;
      }
   }
   return 0;
}

int __po_hi_time_copy (__po_hi_time_t* dst, const __po_hi_time_t* src)
{
   dst->sec = src->sec;
   dst->nsec = src->nsec;
   return (__PO_HI_SUCCESS);
}