po_hi_time.c 4.5 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

   if (pthread_mutex_init (&mutex, NULL) != 0)
   {
      return (__PO_HI_ERROR_PTHREAD_MUTEX);
   }

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

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);
}