|
1 /* |
|
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: This is a project specific source file for building the |
|
15 * clock related functions as part of librt library. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include <time.h> |
|
21 #include <errno.h> |
|
22 #include <pthread.h> |
|
23 #include <stdlib.h> |
|
24 #include <e32std.h> |
|
25 #include <sys/_timeval.h> |
|
26 #include <sys/types.h> |
|
27 |
|
28 #include "lposix.h" |
|
29 |
|
30 #define UNIX_BASE TTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000)) // 00:00, Jan 1st 1970 |
|
31 |
|
32 #define BOUNDARY_CHECK(rqtp) ( (rqtp->tv_nsec != 0 && rqtp->tv_nsec < 1000) || \ |
|
33 rqtp->tv_nsec >= 1000000000L )\ |
|
34 |
|
35 extern "C" { |
|
36 |
|
37 //Returns the resolution (granularity) of a clock |
|
38 //This value is placed in a (non-NULL) *res |
|
39 EXPORT_C int clock_getres(clockid_t clock_id, struct timespec* res) |
|
40 { |
|
41 int retval = -1; |
|
42 //We expect the user of the library to give us a valid pointer |
|
43 if(res == NULL) |
|
44 { |
|
45 return 0; //no strict reactions please. |
|
46 } |
|
47 |
|
48 switch (clock_id) |
|
49 { |
|
50 case CLOCK_REALTIME: |
|
51 //Since Symbian OS is not realtime,we simulate the same using |
|
52 //the available wall clock whose resolution is upto microseconds |
|
53 res->tv_sec = 0; |
|
54 res->tv_nsec = 1000; |
|
55 retval = 0; |
|
56 break; |
|
57 |
|
58 default: |
|
59 //For all other clocks that cannot be supported or invalid clockids, |
|
60 //we set errno to not-supported |
|
61 retval = -1; |
|
62 errno = EINVAL; |
|
63 break; |
|
64 } |
|
65 |
|
66 return retval; |
|
67 } |
|
68 |
|
69 //Allow the calling process to retrieve the value used by a clock which |
|
70 //is specified by clock_id |
|
71 EXPORT_C int clock_gettime (clockid_t clock_id, struct timespec *tp) |
|
72 { |
|
73 int retval = -1; |
|
74 TTime t; |
|
75 TTimeIntervalSeconds iSeconds; |
|
76 TInt err; |
|
77 //We expect the user of the library to give us a valid pointer |
|
78 if(tp == NULL) |
|
79 { |
|
80 errno = EFAULT; |
|
81 return retval; |
|
82 } |
|
83 |
|
84 switch(clock_id) |
|
85 { |
|
86 case CLOCK_REALTIME: |
|
87 //Since Symbian OS is not realtime,we simulate the same using |
|
88 //the available wall clock.We use TTime::HomeTime() call to get |
|
89 //the wall clock time |
|
90 t.HomeTime(); |
|
91 err = t.SecondsFrom(UNIX_BASE, iSeconds); //TODO check for the negative tests.. |
|
92 if (!err) |
|
93 { |
|
94 t-=iSeconds;//extracting seconds info into iSeconds |
|
95 tp->tv_sec = iSeconds.Int(); |
|
96 tp->tv_nsec = t.Int64(); |
|
97 retval = 0; |
|
98 } |
|
99 break; |
|
100 |
|
101 default: |
|
102 //For all other clocks that cannot be supported or invalid clockids, |
|
103 //we set errno to invalid |
|
104 retval = -1; |
|
105 errno = EINVAL; |
|
106 break; |
|
107 } |
|
108 return retval; |
|
109 } |
|
110 |
|
111 |
|
112 //The clock_settime allow the calling process to set the value used by a |
|
113 //clock which is specified by clock_id |
|
114 EXPORT_C int clock_settime (clockid_t clock_id, const struct timespec *tp) |
|
115 { |
|
116 int retval = -1; |
|
117 TTime t(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000)) ; // 00:00, Jan 1st 1970 |
|
118 TInt err; |
|
119 TInt64 microtime; |
|
120 |
|
121 if(tp == NULL) |
|
122 { |
|
123 errno = EFAULT; |
|
124 return retval; |
|
125 } |
|
126 |
|
127 //Check for boundary values of seconds and microseconds |
|
128 if (BOUNDARY_CHECK(tp)) |
|
129 { |
|
130 errno = EINVAL; |
|
131 return retval; |
|
132 } |
|
133 |
|
134 switch(clock_id) |
|
135 { |
|
136 case CLOCK_REALTIME: |
|
137 //We support only the wall-clock,hence use the |
|
138 //User::SetHomeTime call to set the time |
|
139 t+=(TTimeIntervalSeconds)tp->tv_sec; |
|
140 microtime = (tp->tv_nsec)/1000; |
|
141 t+=(TTimeIntervalMicroSeconds)microtime; |
|
142 err = User::SetUTCTime(t); |
|
143 if(err) |
|
144 { |
|
145 MapError(err,errno); |
|
146 break; |
|
147 } |
|
148 else |
|
149 retval = 0; |
|
150 break; |
|
151 |
|
152 default: |
|
153 //For all other clocks that cannot be supported or invalid clockids, |
|
154 //we set errno to invalid |
|
155 retval = -1; |
|
156 errno = EINVAL; |
|
157 break; |
|
158 } |
|
159 |
|
160 return retval; |
|
161 } |
|
162 |
|
163 |
|
164 //Returns the clock ID of the CPU-time clock of the process specified by pid |
|
165 EXPORT_C int clock_getcpuclockid (pid_t pid, clockid_t *clock_id) |
|
166 { |
|
167 int retval = -1; |
|
168 |
|
169 if(clock_id == NULL) |
|
170 { |
|
171 errno = EFAULT; |
|
172 return retval; |
|
173 } |
|
174 |
|
175 /* We don't allow any process ID but our own. */ |
|
176 if (pid == 0) |
|
177 { |
|
178 //The only available clock is the realtime wall clock |
|
179 //Hence we set the clockid to that |
|
180 *clock_id = CLOCK_REALTIME; |
|
181 retval = 0; |
|
182 } |
|
183 else |
|
184 errno = ESRCH; |
|
185 |
|
186 return retval; |
|
187 } |
|
188 |
|
189 |
|
190 //clock_nanosleep will not be interrupted by the signal emulation. |
|
191 //hence EINTR is not valid here. |
|
192 |
|
193 EXPORT_C int clock_nanosleep(clockid_t clock_id, int flags, |
|
194 const struct timespec *rqtp, struct timespec */*rmtp*/) |
|
195 { |
|
196 int retval = -1; |
|
197 |
|
198 if(rqtp == NULL) |
|
199 { |
|
200 errno = EFAULT; |
|
201 return retval; |
|
202 } |
|
203 |
|
204 //Check for boundary values of seconds and microseconds |
|
205 if (BOUNDARY_CHECK(rqtp)) |
|
206 { |
|
207 errno = EINVAL; |
|
208 return retval; |
|
209 } |
|
210 |
|
211 switch(clock_id) |
|
212 { |
|
213 case CLOCK_REALTIME: |
|
214 { |
|
215 switch(flags) |
|
216 { |
|
217 case TIMER_ABSTIME: |
|
218 { |
|
219 TTime lSetTime(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000)) ; // 00:00, Jan 1st 1970 |
|
220 |
|
221 lSetTime+=(TTimeIntervalSeconds)rqtp->tv_sec; |
|
222 lSetTime+=(TTimeIntervalMicroSeconds)(rqtp->tv_nsec/1000); |
|
223 |
|
224 User::At(lSetTime); |
|
225 } |
|
226 break; |
|
227 |
|
228 default: |
|
229 { |
|
230 unsigned long timeout; |
|
231 timeout = (1000000 * rqtp->tv_sec) + (rqtp->tv_nsec /1000); |
|
232 User::AfterHighRes(timeout); |
|
233 } |
|
234 break; |
|
235 } |
|
236 } |
|
237 retval = 0; |
|
238 break; |
|
239 |
|
240 default: |
|
241 //For all other clocks that cannot be supported or invalid clockids, |
|
242 //we set errno to invalid |
|
243 retval = -1; |
|
244 errno = EINVAL; |
|
245 break; |
|
246 } |
|
247 |
|
248 return retval; |
|
249 } |
|
250 } // extern "C" |
|
251 |
|
252 //EOF |
|
253 |
|
254 |
|
255 |