|
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 include file for building the |
|
15 * clock related functions as part of libc 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 #include "lposix.h" |
|
28 |
|
29 #define UNIX_BASE TTime(MAKE_TINT64(0x00dcddb3,0x0f2f8000)) // 00:00, Jan 1st 1970 |
|
30 |
|
31 extern "C" { |
|
32 |
|
33 //Returns the resolution (granularity) of a clock |
|
34 //This value is placed in a (non-NULL) *res |
|
35 EXPORT_C int clock_getres(clockid_t clock_id, struct timespec* res) |
|
36 { |
|
37 int retval = -1; |
|
38 //We expect the user of the library to give us a valid pointer |
|
39 if(res == NULL) |
|
40 { |
|
41 errno = EFAULT; |
|
42 return retval; |
|
43 } |
|
44 |
|
45 switch (clock_id) |
|
46 { |
|
47 case CLOCK_REALTIME: |
|
48 //Since Symbian OS is not realtime,we simulate the same using |
|
49 //the available wall clock whose resolution is upto microseconds |
|
50 res->tv_sec = 0; |
|
51 res->tv_nsec = 1000000; |
|
52 retval = 0; |
|
53 break; |
|
54 |
|
55 default: |
|
56 //For all other clocks that cannot be supported or invalid clockids, |
|
57 //we set errno to not-supported |
|
58 retval = -1; |
|
59 errno = EINVAL; |
|
60 break; |
|
61 } |
|
62 return retval; |
|
63 } |
|
64 |
|
65 //Allow the calling process to retrieve the value used by a clock which |
|
66 //is specified by clock_id |
|
67 EXPORT_C int clock_gettime (clockid_t clock_id, struct timespec *tp) |
|
68 { |
|
69 int retval = -1; |
|
70 TTime t; |
|
71 TTimeIntervalSeconds iSeconds; |
|
72 TInt err; |
|
73 //We expect the user of the library to give us a valid pointer |
|
74 if(tp == NULL) |
|
75 { |
|
76 errno = EFAULT; |
|
77 return retval; |
|
78 } |
|
79 |
|
80 switch(clock_id) |
|
81 { |
|
82 case CLOCK_REALTIME: |
|
83 //Since Symbian OS is not realtime,we simulate the same using |
|
84 //the available wall clock.We use TTime::HomeTime() call to get |
|
85 //the wall clock time |
|
86 t.HomeTime(); |
|
87 err = t.SecondsFrom(UNIX_BASE, iSeconds); |
|
88 t-=iSeconds;//extracting seconds info into iSeconds |
|
89 if (!err) |
|
90 { |
|
91 tp->tv_sec = iSeconds.Int(); |
|
92 tp->tv_nsec = t.Int64(); |
|
93 retval = 0; |
|
94 } |
|
95 break; |
|
96 |
|
97 default: |
|
98 //For all other clocks that cannot be supported or invalid clockids, |
|
99 //we set errno to invalid |
|
100 retval = -1; |
|
101 errno = EINVAL; |
|
102 break; |
|
103 } |
|
104 return retval; |
|
105 } |
|
106 |
|
107 |
|
108 //The clock_settime allow the calling process to set the value used by a |
|
109 //clock which is specified by clock_id |
|
110 EXPORT_C int clock_settime (clockid_t clock_id, const struct timespec *tp) |
|
111 { |
|
112 int retval = -1; |
|
113 TTime t(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000)) ; // 00:00, Jan 1st 1970 |
|
114 TInt err; |
|
115 TInt64 microtime; |
|
116 //We must get a filled structure from the user of the library |
|
117 if(tp == NULL) |
|
118 { |
|
119 errno = EFAULT; |
|
120 return retval; |
|
121 } |
|
122 //Check for boundary values of seconds and microseconds |
|
123 if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000L) |
|
124 { |
|
125 errno = ERANGE; |
|
126 return retval; |
|
127 } |
|
128 |
|
129 switch(clock_id) |
|
130 { |
|
131 case CLOCK_REALTIME: |
|
132 //We support only the wall-clock,hence use the |
|
133 //User::SetHomeTime call to set the time |
|
134 t+=(TTimeIntervalSeconds)tp->tv_sec; |
|
135 microtime = (tp->tv_nsec)/1000; |
|
136 t+=(TTimeIntervalMicroSeconds)microtime; |
|
137 err = User::SetUTCTime(t); |
|
138 if(err) |
|
139 { |
|
140 MapError(err,errno); |
|
141 break; |
|
142 } |
|
143 else |
|
144 retval = 0; |
|
145 break; |
|
146 |
|
147 default: |
|
148 //For all other clocks that cannot be supported or invalid clockids, |
|
149 //we set errno to invalid |
|
150 retval = -1; |
|
151 errno = EINVAL; |
|
152 break; |
|
153 } |
|
154 return retval; |
|
155 } |
|
156 |
|
157 |
|
158 //Returns the clock ID of the CPU-time clock of the process specified by pid |
|
159 EXPORT_C int clock_getcpuclockid (pid_t pid, clockid_t *clock_id) |
|
160 { |
|
161 int retval = -1; |
|
162 /* We don't allow any process ID but our own. */ |
|
163 if (pid == 0) |
|
164 { |
|
165 //The only available clock is the realtime wall clock |
|
166 //Hence we set the clockid to that |
|
167 *clock_id = CLOCK_REALTIME; |
|
168 retval = 0; |
|
169 } |
|
170 else |
|
171 errno = ESRCH; |
|
172 |
|
173 return retval; |
|
174 } |
|
175 |
|
176 //Makes small adjustments to the system time, |
|
177 //advancing it by the time specified by the timeval delta |
|
178 EXPORT_C int adjtime(const struct timeval *delta, struct timeval *olddelta) |
|
179 { |
|
180 //We can make only positive adjutments to the available clock |
|
181 //The synchronization to the global time server is provided to us |
|
182 //by the User::SetHomeTime api itself |
|
183 int retval = -1; |
|
184 TTime t; |
|
185 TInt err; |
|
186 TInt64 microtime; |
|
187 long secs = 0; |
|
188 suseconds_t usec = 0; |
|
189 |
|
190 //We expect the user of the library to give us a valid pointer |
|
191 if(delta == NULL) |
|
192 { |
|
193 errno = EFAULT; |
|
194 return retval; |
|
195 } |
|
196 |
|
197 if ((delta->tv_usec) > 1000000) |
|
198 { |
|
199 errno = ERANGE; |
|
200 return retval; |
|
201 } |
|
202 //Check for negative of seconds and make it positive |
|
203 if((delta->tv_sec) < 0) |
|
204 secs = -1*(delta->tv_sec); |
|
205 else |
|
206 secs = delta->tv_sec; |
|
207 |
|
208 //Check for negative of microseconds and make it positive |
|
209 if((delta->tv_usec) < 0) |
|
210 usec = -1*(delta->tv_usec); |
|
211 else |
|
212 usec = delta->tv_usec; |
|
213 |
|
214 t.HomeTime(); |
|
215 t+=(TTimeIntervalSeconds)secs; |
|
216 microtime = usec; |
|
217 t+=(TTimeIntervalMicroSeconds)microtime; |
|
218 err = User::SetHomeTime(t); |
|
219 if (!err) |
|
220 { |
|
221 retval = 0; |
|
222 //olddelta is always zero in case of success |
|
223 olddelta->tv_sec = 0; |
|
224 olddelta->tv_usec = 0; |
|
225 } |
|
226 else |
|
227 { |
|
228 MapError(err,errno); |
|
229 retval = -1; |
|
230 } |
|
231 return retval; |
|
232 } |
|
233 |
|
234 } // extern "C" |