1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2023 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "time.h"
33 #include "stdint.h"
34 #include "stdio.h"
35 #include "sys/times.h"
36 #include "time_posix.h"
37 #include "unistd.h"
38 #ifdef LOSCFG_SECURITY_CAPABILITY
39 #include "capability_api.h"
40 #endif
41 #include "los_signal.h"
42 #ifdef LOSCFG_KERNEL_VDSO
43 #include "los_vdso.h"
44 #endif
45 #ifdef LOSCFG_SECURITY_VID
46 #include "vid_api.h"
47 #endif
48 #include "user_copy.h"
49 #include "los_process_pri.h"
50 #include "los_swtmr_pri.h"
51 #include "los_sys_pri.h"
52
53 #define CPUCLOCK_PERTHREAD_MASK 4
54 #define CPUCLOCK_ID_OFFSET 3
55
56 /*
57 * Do a time package defined return. This requires the error code
58 * to be placed in errno, and if it is non-zero, -1 returned as the
59 * result of the function. This also gives us a place to put any
60 * generic tidyup handling needed for things like signal delivery and
61 * cancellation.
62 */
63 #define TIME_RETURN(err) do { \
64 INT32 retVal = 0; \
65 if ((err) != 0) { \
66 retVal = -1; \
67 errno = (err); \
68 } \
69 return retVal; \
70 } while (0)
71
72 #ifdef LOSCFG_AARCH64
73 /*
74 * This two structures originally didn't exit,
75 * they added by liteos to support 64bit interfaces on 32bit platform,
76 * in 64bit platform, timeval64 define to timeval which is platform adaptive.
77 */
78 #define timeval64 timeval
79 #define timespec64 timespec
80 #endif
81
ValidTimeval(const struct timeval * tv)82 STATIC INLINE BOOL ValidTimeval(const struct timeval *tv)
83 {
84 /* Fail a NULL pointer */
85 if (tv == NULL) {
86 return FALSE;
87 }
88
89 /* Fail illegal microseconds values */
90 if ((tv->tv_usec < 0) || (tv->tv_usec >= OS_SYS_US_PER_SECOND) || (tv->tv_sec < 0)) {
91 return FALSE;
92 }
93
94 return TRUE;
95 }
96
ValidTimeval64(const struct timeval64 * tv)97 STATIC INLINE BOOL ValidTimeval64(const struct timeval64 *tv)
98 {
99 /* Fail a NULL pointer */
100 if (tv == NULL) {
101 return FALSE;
102 }
103
104 /* Fail illegal microseconds values */
105 if ((tv->tv_usec < 0) || (tv->tv_usec >= OS_SYS_US_PER_SECOND) || (tv->tv_sec < 0)) {
106 return FALSE;
107 }
108
109 return TRUE;
110 }
111
ValidTimerID(UINT16 swtmrID)112 STATIC INLINE BOOL ValidTimerID(UINT16 swtmrID)
113 {
114 /* check timer id */
115 if (swtmrID >= OS_SWTMR_MAX_TIMERID) {
116 return FALSE;
117 }
118
119 /* check owner of this timer */
120 if (OS_SWT_FROM_SID(swtmrID)->uwOwnerPid != (UINTPTR)OsCurrProcessGet()) {
121 return FALSE;
122 }
123
124 return TRUE;
125 }
126
127 STATIC SPIN_LOCK_INIT(g_timeSpin);
128 STATIC long long g_adjTimeLeft; /* absolute value of adjtime */
129 STATIC INT32 g_adjDirection; /* 1, speed up; 0, slow down; */
130
131 /* Adjust pacement, nanoseconds per SCHED_CLOCK_INTETRVAL_TICKS ticks */
132 STATIC const long long g_adjPacement = (((LOSCFG_BASE_CORE_ADJ_PER_SECOND * SCHED_CLOCK_INTETRVAL_TICKS) /
133 LOSCFG_BASE_CORE_TICK_PER_SECOND) * OS_SYS_NS_PER_US);
134
135 /* accumulative time delta from continuous modify, such as adjtime */
136 STATIC struct timespec64 g_accDeltaFromAdj;
137 /* accumulative time delta from discontinuous modify, such as settimeofday */
138 STATIC struct timespec64 g_accDeltaFromSet;
139
OsAdjTime(VOID)140 VOID OsAdjTime(VOID)
141 {
142 UINT32 intSave;
143
144 LOS_SpinLockSave(&g_timeSpin, &intSave);
145 if (!g_adjTimeLeft) {
146 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
147 return;
148 }
149
150 if (g_adjTimeLeft > g_adjPacement) {
151 if (g_adjDirection) {
152 if ((g_accDeltaFromAdj.tv_nsec + g_adjPacement) >= OS_SYS_NS_PER_SECOND) {
153 g_accDeltaFromAdj.tv_sec++;
154 g_accDeltaFromAdj.tv_nsec = (g_accDeltaFromAdj.tv_nsec + g_adjPacement) % OS_SYS_NS_PER_SECOND;
155 } else {
156 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec + g_adjPacement;
157 }
158 } else {
159 if ((g_accDeltaFromAdj.tv_nsec - g_adjPacement) < 0) {
160 g_accDeltaFromAdj.tv_sec--;
161 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjPacement + OS_SYS_NS_PER_SECOND;
162 } else {
163 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjPacement;
164 }
165 }
166
167 g_adjTimeLeft -= g_adjPacement;
168 } else {
169 if (g_adjDirection) {
170 if ((g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft) >= OS_SYS_NS_PER_SECOND) {
171 g_accDeltaFromAdj.tv_sec++;
172 g_accDeltaFromAdj.tv_nsec = (g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft) % OS_SYS_NS_PER_SECOND;
173 } else {
174 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec + g_adjTimeLeft;
175 }
176 } else {
177 if ((g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft) < 0) {
178 g_accDeltaFromAdj.tv_sec--;
179 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft + OS_SYS_NS_PER_SECOND;
180 } else {
181 g_accDeltaFromAdj.tv_nsec = g_accDeltaFromAdj.tv_nsec - g_adjTimeLeft;
182 }
183 }
184
185 g_adjTimeLeft = 0;
186 }
187 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
188 return;
189 }
190
191 /*
192 * Function: adjtime
193 * Description: correct the time to synchronize the system clock.
194 * Input: delta - The amount of time by which the clock is to be adjusted.
195 * Output: oldDelta - the amount of time remaining from any previous adjustment that has not yet been completed.
196 * Return: On success, returns 0. On failure, -1 is returned, and errno is set to indicate the error.
197 */
adjtime(const struct timeval * delta,struct timeval * oldDelta)198 int adjtime(const struct timeval *delta, struct timeval *oldDelta)
199 {
200 UINT32 intSave;
201 LOS_SpinLockSave(&g_timeSpin, &intSave);
202 /* return the amount of time remaining from any previous adjustment that has not yet been completed. */
203 if (oldDelta != NULL) {
204 if (g_adjDirection == 1) {
205 oldDelta->tv_sec = g_adjTimeLeft / OS_SYS_NS_PER_SECOND;
206 oldDelta->tv_usec = (g_adjTimeLeft % OS_SYS_NS_PER_SECOND) / OS_SYS_NS_PER_US;
207 } else {
208 oldDelta->tv_sec = -(g_adjTimeLeft / OS_SYS_NS_PER_SECOND);
209 oldDelta->tv_usec = -((g_adjTimeLeft % OS_SYS_NS_PER_SECOND) / OS_SYS_NS_PER_US);
210 }
211 }
212
213 if ((delta == NULL) || ((delta->tv_sec == 0) && (delta->tv_usec == 0))) {
214 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
215 return 0;
216 }
217
218 if ((delta->tv_usec > OS_SYS_US_PER_SECOND) || (delta->tv_usec < -OS_SYS_US_PER_SECOND)) {
219 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
220 TIME_RETURN(EINVAL);
221 }
222
223 /*
224 * 2: in the glibc implementation, delta must be less than or equal to (INT_MAX / 1000000 - 2) and
225 * greater than or equal to (INT_MIN / 1000000 + 2)
226 */
227 if ((delta->tv_sec < (INT_MIN / OS_SYS_US_PER_SECOND + 2)) ||
228 (delta->tv_sec > (INT_MAX / OS_SYS_US_PER_SECOND + 2))) {
229 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
230 TIME_RETURN(EINVAL);
231 }
232
233 g_adjTimeLeft = (INT64)delta->tv_sec * OS_SYS_NS_PER_SECOND + delta->tv_usec * OS_SYS_NS_PER_US;
234 if (g_adjTimeLeft > 0) {
235 g_adjDirection = 1;
236 } else {
237 g_adjDirection = 0;
238 g_adjTimeLeft = -g_adjTimeLeft;
239 }
240
241 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
242 return 0;
243 }
244
OsTimeSpecAdd(const struct timespec64 t1,const struct timespec64 t2)245 STATIC INLINE struct timespec64 OsTimeSpecAdd(const struct timespec64 t1, const struct timespec64 t2)
246 {
247 struct timespec64 ret = {0};
248
249 ret.tv_sec = t1.tv_sec + t2.tv_sec;
250 ret.tv_nsec = t1.tv_nsec + t2.tv_nsec;
251 if (ret.tv_nsec >= OS_SYS_NS_PER_SECOND) {
252 ret.tv_sec += 1;
253 ret.tv_nsec -= OS_SYS_NS_PER_SECOND;
254 } else if (ret.tv_nsec < 0L) {
255 ret.tv_sec -= 1;
256 ret.tv_nsec += OS_SYS_NS_PER_SECOND;
257 }
258
259 return ret;
260 }
261
OsTimeSpecSub(const struct timespec64 t1,const struct timespec64 t2)262 STATIC INLINE struct timespec64 OsTimeSpecSub(const struct timespec64 t1, const struct timespec64 t2)
263 {
264 struct timespec64 ret = {0};
265
266 ret.tv_sec = t1.tv_sec - t2.tv_sec;
267 ret.tv_nsec = t1.tv_nsec - t2.tv_nsec;
268 if (ret.tv_nsec < 0) {
269 ret.tv_sec -= 1;
270 ret.tv_nsec += OS_SYS_NS_PER_SECOND;
271 }
272
273 return ret;
274 }
275
OsGetHwTime(struct timespec64 * hwTime)276 STATIC VOID OsGetHwTime(struct timespec64 *hwTime)
277 {
278 UINT64 nowNsec;
279
280 nowNsec = LOS_CurrNanosec();
281 hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
282 hwTime->tv_nsec = nowNsec - hwTime->tv_sec * OS_SYS_NS_PER_SECOND;
283 }
284
OsSetTimeOfDay(const struct timeval64 * tv,const struct timezone * tz)285 STATIC INT32 OsSetTimeOfDay(const struct timeval64 *tv, const struct timezone *tz)
286 {
287 UINT32 intSave;
288 struct timespec64 setTime = {0};
289 struct timespec64 hwTime = {0};
290 struct timespec64 realTime = {0};
291 struct timespec64 tmp = {0};
292
293 #ifdef LOSCFG_SECURITY_CAPABILITY
294 if (!IsCapPermit(CAP_SET_TIMEOFDAY)) {
295 TIME_RETURN(EPERM);
296 }
297 #endif
298
299 (VOID)tz;
300 OsGetHwTime(&hwTime);
301 setTime.tv_sec = tv->tv_sec;
302 setTime.tv_nsec = tv->tv_usec * OS_SYS_NS_PER_US;
303
304 LOS_SpinLockSave(&g_timeSpin, &intSave);
305 /* stop on-going continuous adjusement */
306 if (g_adjTimeLeft) {
307 g_adjTimeLeft = 0;
308 }
309 realTime = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
310 realTime = OsTimeSpecAdd(realTime, g_accDeltaFromSet);
311
312 tmp = OsTimeSpecSub(setTime, realTime);
313 g_accDeltaFromSet = OsTimeSpecAdd(g_accDeltaFromSet, tmp);
314
315 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
316
317 return 0;
318 }
319
settimeofday(const struct timeval * tv,const struct timezone * tz)320 int settimeofday(const struct timeval *tv, const struct timezone *tz)
321 {
322 struct timeval64 stTimeVal64 = {0};
323
324 if (!ValidTimeval(tv)) {
325 TIME_RETURN(EINVAL);
326 }
327
328 stTimeVal64.tv_sec = tv->tv_sec;
329 stTimeVal64.tv_usec = tv->tv_usec;
330
331 return OsSetTimeOfDay(&stTimeVal64, tz);
332 }
333
334 #ifndef LOSCFG_AARCH64
settimeofday64(const struct timeval64 * tv,const struct timezone * tz)335 int settimeofday64(const struct timeval64 *tv, const struct timezone *tz)
336 {
337 if (!ValidTimeval64(tv)) {
338 TIME_RETURN(EINVAL);
339 }
340
341 return OsSetTimeOfDay(tv, tz);
342 }
343 #endif
344
setlocalseconds(int seconds)345 int setlocalseconds(int seconds)
346 {
347 struct timeval tv = {0};
348
349 tv.tv_sec = seconds;
350 tv.tv_usec = 0;
351
352 return settimeofday(&tv, NULL);
353 }
354
OsGetTimeOfDay(struct timeval64 * tv,struct timezone * tz)355 STATIC INT32 OsGetTimeOfDay(struct timeval64 *tv, struct timezone *tz)
356 {
357 UINT32 intSave;
358
359 (VOID)tz;
360 struct timespec64 hwTime = {0};
361 struct timespec64 realTime = {0};
362
363 OsGetHwTime(&hwTime);
364
365 LOS_SpinLockSave(&g_timeSpin, &intSave);
366 realTime = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
367 realTime = OsTimeSpecAdd(realTime, g_accDeltaFromSet);
368 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
369
370 tv->tv_sec = realTime.tv_sec;
371 tv->tv_usec = realTime.tv_nsec / OS_SYS_NS_PER_US;
372
373 if (tv->tv_sec < 0) {
374 TIME_RETURN(EINVAL);
375 }
376 return 0;
377 }
378
379 #ifndef LOSCFG_AARCH64
gettimeofday64(struct timeval64 * tv,struct timezone * tz)380 int gettimeofday64(struct timeval64 *tv, struct timezone *tz)
381 {
382 if (tv == NULL) {
383 TIME_RETURN(EINVAL);
384 }
385
386 return OsGetTimeOfDay(tv, tz);
387 }
388 #endif
389
390 #ifdef LOSCFG_LIBC_NEWLIB
gettimeofday(struct timeval * tv,void * _tz)391 int gettimeofday(struct timeval *tv, void *_tz)
392 #else
393 int gettimeofday(struct timeval *tv, struct timezone *tz)
394 #endif
395 {
396 struct timeval64 stTimeVal64 = {0};
397 #ifdef LOSCFG_LIBC_NEWLIB
398 struct timezone *tz = (struct timezone *)_tz;
399 #endif
400
401 if (tv == NULL) {
402 TIME_RETURN(EINVAL);
403 }
404
405 if (OsGetTimeOfDay(&stTimeVal64, tz) == -1) {
406 return -1;
407 }
408
409 #ifdef LOSCFG_AARCH64
410 tv->tv_sec = stTimeVal64.tv_sec;
411 tv->tv_usec = stTimeVal64.tv_usec;
412 #else
413 if (stTimeVal64.tv_sec > (long long)LONG_MAX) {
414 return -1;
415 }
416 tv->tv_sec = (time_t)stTimeVal64.tv_sec;
417 tv->tv_usec = (suseconds_t)stTimeVal64.tv_usec;
418 #endif
419
420 return 0;
421 }
422
clock_settime(clockid_t clockID,const struct timespec * tp)423 int clock_settime(clockid_t clockID, const struct timespec *tp)
424 {
425 struct timeval tv = {0};
426
427 switch (clockID) {
428 case CLOCK_REALTIME:
429 /* we only support the realtime clock currently */
430 break;
431 case CLOCK_MONOTONIC_COARSE:
432 case CLOCK_REALTIME_COARSE:
433 case CLOCK_MONOTONIC_RAW:
434 case CLOCK_PROCESS_CPUTIME_ID:
435 case CLOCK_BOOTTIME:
436 case CLOCK_REALTIME_ALARM:
437 case CLOCK_BOOTTIME_ALARM:
438 case CLOCK_TAI:
439 case CLOCK_THREAD_CPUTIME_ID:
440 TIME_RETURN(ENOTSUP);
441 case CLOCK_MONOTONIC:
442 default:
443 TIME_RETURN(EINVAL);
444 }
445
446 if (!ValidTimeSpec(tp)) {
447 TIME_RETURN(EINVAL);
448 }
449
450 #ifdef LOSCFG_SECURITY_CAPABILITY
451 if (!IsCapPermit(CAP_CLOCK_SETTIME)) {
452 TIME_RETURN(EPERM);
453 }
454 #endif
455
456 tv.tv_sec = tp->tv_sec;
457 tv.tv_usec = tp->tv_nsec / OS_SYS_NS_PER_US;
458 return settimeofday(&tv, NULL);
459 }
460
461 #ifdef LOSCFG_KERNEL_CPUP
GetTidFromClockID(clockid_t clockID)462 inline UINT32 GetTidFromClockID(clockid_t clockID)
463 {
464 // In musl/src/thread/pthread_getcpuclockid.c, we know 'clockid = (-tid - 1) * 8 + 6'
465 UINT32 tid = -(clockID - 6) / 8 - 1; // 6 8 1 inverse operation from clockID to tid
466 return tid;
467 }
468
GetPidFromClockID(clockid_t clockID)469 inline const pid_t GetPidFromClockID(clockid_t clockID)
470 {
471 // In musl/src/time/clock_getcpuclockid.c, we know 'clockid = (-pid - 1) * 8 + 2'
472 const pid_t pid = -(clockID - 2) / 8 - 1; // 2 8 1 inverse operation from clockID to pid
473 return pid;
474 }
475
PthreadGetCputime(clockid_t clockID,struct timespec * ats)476 static int PthreadGetCputime(clockid_t clockID, struct timespec *ats)
477 {
478 uint64_t runtime;
479 UINT32 intSave;
480 UINT32 tid = GetTidFromClockID(clockID);
481 if (OS_TID_CHECK_INVALID(tid)) {
482 return -EINVAL;
483 }
484
485 LosTaskCB *task = OsGetTaskCB(tid);
486
487 if (OsCurrTaskGet()->processCB != task->processCB) {
488 return -EINVAL;
489 }
490
491 SCHEDULER_LOCK(intSave);
492 runtime = task->taskCpup.allTime;
493 SCHEDULER_UNLOCK(intSave);
494
495 ats->tv_sec = runtime / OS_SYS_NS_PER_SECOND;
496 ats->tv_nsec = runtime % OS_SYS_NS_PER_SECOND;
497
498 return 0;
499 }
500
ProcessGetCputime(clockid_t clockID,struct timespec * ats)501 static int ProcessGetCputime(clockid_t clockID, struct timespec *ats)
502 {
503 UINT64 runtime;
504 UINT32 intSave;
505 const pid_t pid = GetPidFromClockID(clockID);
506 LosProcessCB *spcb = NULL;
507
508 if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
509 return -EINVAL;
510 }
511
512 spcb = OS_PCB_FROM_PID(pid);
513 if (OsProcessIsUnused(spcb)) {
514 return -EINVAL;
515 }
516
517 SCHEDULER_LOCK(intSave);
518 if (spcb->processCpup == NULL) {
519 SCHEDULER_UNLOCK(intSave);
520 return -EINVAL;
521 }
522 runtime = spcb->processCpup->allTime;
523 SCHEDULER_UNLOCK(intSave);
524
525 ats->tv_sec = runtime / OS_SYS_NS_PER_SECOND;
526 ats->tv_nsec = runtime % OS_SYS_NS_PER_SECOND;
527
528 return 0;
529 }
530
GetCputime(clockid_t clockID,struct timespec * tp)531 static int GetCputime(clockid_t clockID, struct timespec *tp)
532 {
533 int ret;
534
535 if (clockID >= 0) {
536 return -EINVAL;
537 }
538
539 if ((UINT32)clockID & CPUCLOCK_PERTHREAD_MASK) {
540 ret = PthreadGetCputime(clockID, tp);
541 } else {
542 ret = ProcessGetCputime(clockID, tp);
543 }
544
545 return ret;
546 }
547
CheckClock(const clockid_t clockID)548 static int CheckClock(const clockid_t clockID)
549 {
550 int error = 0;
551 const pid_t pid = GetPidFromClockID(clockID);
552
553 if (!((UINT32)clockID & CPUCLOCK_PERTHREAD_MASK)) {
554 LosProcessCB *spcb = NULL;
555 if (OsProcessIDUserCheckInvalid(pid) || pid < 0) {
556 return -EINVAL;
557 }
558 spcb = OS_PCB_FROM_PID(pid);
559 if (OsProcessIsUnused(spcb)) {
560 error = -EINVAL;
561 }
562 } else {
563 error = -EINVAL;
564 }
565
566 return error;
567 }
568
CpuClockGetres(const clockid_t clockID,struct timespec * tp)569 static int CpuClockGetres(const clockid_t clockID, struct timespec *tp)
570 {
571 if (clockID > 0) {
572 return -EINVAL;
573 }
574
575 int error = CheckClock(clockID);
576 if (!error) {
577 error = ProcessGetCputime(clockID, tp);
578 }
579
580 return error;
581 }
582 #endif
583
clock_gettime(clockid_t clockID,struct timespec * tp)584 int clock_gettime(clockid_t clockID, struct timespec *tp)
585 {
586 UINT32 intSave;
587 struct timespec64 tmp = {0};
588 struct timespec64 hwTime = {0};
589
590 if (clockID > MAX_CLOCKS) {
591 goto ERROUT;
592 }
593
594 if (tp == NULL) {
595 goto ERROUT;
596 }
597
598 OsGetHwTime(&hwTime);
599
600 switch (clockID) {
601 case CLOCK_MONOTONIC_RAW:
602 #ifdef LOSCFG_TIME_CONTAINER
603 tmp = OsTimeSpecAdd(hwTime, CLOCK_MONOTONIC_TIME_BASE);
604 tp->tv_sec = tmp.tv_sec;
605 tp->tv_nsec = tmp.tv_nsec;
606 #else
607 tp->tv_sec = hwTime.tv_sec;
608 tp->tv_nsec = hwTime.tv_nsec;
609 #endif
610 break;
611 case CLOCK_MONOTONIC:
612 LOS_SpinLockSave(&g_timeSpin, &intSave);
613 tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
614 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
615 #ifdef LOSCFG_TIME_CONTAINER
616 tmp = OsTimeSpecAdd(tmp, CLOCK_MONOTONIC_TIME_BASE);
617 #endif
618 tp->tv_sec = tmp.tv_sec;
619 tp->tv_nsec = tmp.tv_nsec;
620 break;
621 case CLOCK_REALTIME:
622 LOS_SpinLockSave(&g_timeSpin, &intSave);
623 tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
624 tmp = OsTimeSpecAdd(tmp, g_accDeltaFromSet);
625 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
626 tp->tv_sec = tmp.tv_sec;
627 tp->tv_nsec = tmp.tv_nsec;
628 break;
629 case CLOCK_MONOTONIC_COARSE:
630 case CLOCK_REALTIME_COARSE:
631 case CLOCK_THREAD_CPUTIME_ID:
632 case CLOCK_PROCESS_CPUTIME_ID:
633 case CLOCK_BOOTTIME:
634 case CLOCK_REALTIME_ALARM:
635 case CLOCK_BOOTTIME_ALARM:
636 case CLOCK_TAI:
637 TIME_RETURN(ENOTSUP);
638 default:
639 {
640 #ifdef LOSCFG_KERNEL_CPUP
641 int ret = GetCputime(clockID, tp);
642 TIME_RETURN(-ret);
643 #else
644 TIME_RETURN(EINVAL);
645 #endif
646 }
647 }
648
649 return 0;
650
651 ERROUT:
652 TIME_RETURN(EINVAL);
653 }
654
clock_getres(clockid_t clockID,struct timespec * tp)655 int clock_getres(clockid_t clockID, struct timespec *tp)
656 {
657 if (tp == NULL) {
658 TIME_RETURN(EINVAL);
659 }
660
661 switch (clockID) {
662 case CLOCK_MONOTONIC_RAW:
663 case CLOCK_MONOTONIC:
664 case CLOCK_REALTIME:
665 /* the accessible rtc resolution */
666 tp->tv_nsec = OS_SYS_NS_PER_US; /* the precision of clock_gettime is 1us */
667 tp->tv_sec = 0;
668 break;
669 case CLOCK_MONOTONIC_COARSE:
670 case CLOCK_REALTIME_COARSE:
671 /* the clock coarse resolution, supported by vdso.
672 * the precision of clock_gettime is 1tick */
673 tp->tv_nsec = OS_SYS_NS_PER_SECOND / LOSCFG_BASE_CORE_TICK_PER_SECOND;
674 tp->tv_sec = 0;
675 break;
676 case CLOCK_THREAD_CPUTIME_ID:
677 case CLOCK_PROCESS_CPUTIME_ID:
678 case CLOCK_BOOTTIME:
679 case CLOCK_REALTIME_ALARM:
680 case CLOCK_BOOTTIME_ALARM:
681 case CLOCK_TAI:
682 TIME_RETURN(ENOTSUP);
683 default:
684 #ifdef LOSCFG_KERNEL_CPUP
685 {
686 int ret = CpuClockGetres(clockID, tp);
687 TIME_RETURN(-ret);
688 }
689 #else
690 TIME_RETURN(EINVAL);
691 #endif
692 }
693
694 TIME_RETURN(0);
695 }
696
clock_nanosleep(clockid_t clk,int flags,const struct timespec * req,struct timespec * rem)697 int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct timespec *rem)
698 {
699 switch (clk) {
700 case CLOCK_REALTIME:
701 if (flags == 0) {
702 /* we only support the realtime clock currently */
703 return nanosleep(req, rem);
704 }
705 /* fallthrough */
706 case CLOCK_MONOTONIC_COARSE:
707 case CLOCK_REALTIME_COARSE:
708 case CLOCK_MONOTONIC_RAW:
709 case CLOCK_MONOTONIC:
710 case CLOCK_PROCESS_CPUTIME_ID:
711 case CLOCK_BOOTTIME:
712 case CLOCK_REALTIME_ALARM:
713 case CLOCK_BOOTTIME_ALARM:
714 case CLOCK_TAI:
715 if (flags == 0 || flags == TIMER_ABSTIME) {
716 TIME_RETURN(ENOTSUP);
717 }
718 /* fallthrough */
719 case CLOCK_THREAD_CPUTIME_ID:
720 default:
721 TIME_RETURN(EINVAL);
722 }
723
724 TIME_RETURN(0);
725 }
726
727 typedef struct {
728 int sigev_signo;
729 pid_t pid;
730 unsigned int tid;
731 union sigval sigev_value;
732 } swtmr_proc_arg;
733
SwtmrProc(UINTPTR tmrArg)734 static VOID SwtmrProc(UINTPTR tmrArg)
735 {
736 #ifdef LOSCFG_KERNEL_VM
737 INT32 sig, ret;
738 UINT32 intSave;
739 pid_t pid;
740 siginfo_t info;
741 LosTaskCB *stcb = NULL;
742
743 swtmr_proc_arg *arg = (swtmr_proc_arg *)tmrArg;
744 OS_GOTO_EXIT_IF(arg == NULL, EINVAL);
745
746 sig = arg->sigev_signo;
747 pid = arg->pid;
748 OS_GOTO_EXIT_IF(!GOOD_SIGNO(sig), EINVAL);
749
750 /* Create the siginfo structure */
751 info.si_signo = sig;
752 info.si_code = SI_TIMER;
753 info.si_value.sival_ptr = arg->sigev_value.sival_ptr;
754
755 /* Send signals to threads or processes */
756 if (arg->tid > 0) {
757 /* Make sure that the para is valid */
758 OS_GOTO_EXIT_IF(OS_TID_CHECK_INVALID(arg->tid), EINVAL);
759 stcb = OsGetTaskCB(arg->tid);
760 ret = OsUserProcessOperatePermissionsCheck(stcb, stcb->processCB);
761 OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
762
763 /* Dispatch the signal to thread, bypassing normal task group thread
764 * dispatch rules. */
765 SCHEDULER_LOCK(intSave);
766 ret = OsTcbDispatch(stcb, &info);
767 SCHEDULER_UNLOCK(intSave);
768 OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
769 } else {
770 /* Make sure that the para is valid */
771 OS_GOTO_EXIT_IF(pid <= 0 || OS_PID_CHECK_INVALID(pid), EINVAL);
772 /* Dispatch the signal to process */
773 SCHEDULER_LOCK(intSave);
774 OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
775 SCHEDULER_UNLOCK(intSave);
776 }
777 return;
778 EXIT:
779 PRINT_ERR("Dispatch signals failed!, ret: %d\r\n", ret);
780 #endif
781 return;
782 }
783
timer_create(clockid_t clockID,struct sigevent * restrict evp,timer_t * restrict timerID)784 int timer_create(clockid_t clockID, struct sigevent *restrict evp, timer_t *restrict timerID)
785 {
786 UINT32 ret;
787 UINT16 swtmrID;
788 #ifdef LOSCFG_SECURITY_VID
789 UINT16 vid;
790 #endif
791
792 if (!timerID || (clockID != CLOCK_REALTIME) || !evp) {
793 errno = EINVAL;
794 return -1;
795 }
796
797 if ((evp->sigev_notify != SIGEV_THREAD) || evp->sigev_notify_attributes) {
798 errno = ENOTSUP;
799 return -1;
800 }
801
802 ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, (SWTMR_PROC_FUNC)evp->sigev_notify_function,
803 &swtmrID, (UINTPTR)evp->sigev_value.sival_ptr);
804 if (ret != LOS_OK) {
805 errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL;
806 return -1;
807 }
808
809 #ifdef LOSCFG_SECURITY_VID
810 vid = AddNodeByRid(swtmrID);
811 if (vid == MAX_INVALID_TIMER_VID) {
812 (VOID)LOS_SwtmrDelete(swtmrID);
813 return -1;
814 }
815 swtmrID = vid;
816 #endif
817 *timerID = (timer_t)(UINTPTR)swtmrID;
818 return 0;
819 }
820
OsTimerCreate(clockid_t clockID,struct ksigevent * evp,timer_t * timerID)821 int OsTimerCreate(clockid_t clockID, struct ksigevent *evp, timer_t *timerID)
822 {
823 UINT32 ret;
824 UINT16 swtmrID;
825 swtmr_proc_arg *arg = NULL;
826 int signo;
827 #ifdef LOSCFG_SECURITY_VID
828 UINT16 vid;
829 #endif
830
831 if ((clockID != CLOCK_REALTIME) || (timerID == NULL)) {
832 errno = EINVAL;
833 return -1;
834 }
835
836 signo = evp ? evp->sigev_signo : SIGALRM;
837 if (signo > SIGRTMAX || signo < 1) {
838 errno = EINVAL;
839 return -1;
840 }
841 if (evp && (evp->sigev_notify != SIGEV_SIGNAL && evp->sigev_notify != SIGEV_THREAD_ID)) {
842 errno = ENOTSUP;
843 return -1;
844 }
845
846 arg = (swtmr_proc_arg *)malloc(sizeof(swtmr_proc_arg));
847 if (arg == NULL) {
848 errno = ENOMEM;
849 return -1;
850 }
851
852 arg->tid = evp ? evp->sigev_tid : 0;
853 arg->sigev_signo = signo;
854 arg->pid = LOS_GetCurrProcessID();
855 arg->sigev_value.sival_ptr = evp ? evp->sigev_value.sival_ptr : NULL;
856 ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, SwtmrProc, &swtmrID, (UINTPTR)arg);
857 if (ret != LOS_OK) {
858 errno = (ret == LOS_ERRNO_SWTMR_MAXSIZE) ? EAGAIN : EINVAL;
859 free(arg);
860 return -1;
861 }
862
863 #ifdef LOSCFG_SECURITY_VID
864 vid = AddNodeByRid(swtmrID);
865 if (vid == MAX_INVALID_TIMER_VID) {
866 free(arg);
867 (VOID)LOS_SwtmrDelete(swtmrID);
868 return -1;
869 }
870 swtmrID = vid;
871 #endif
872 *timerID = (timer_t)(UINTPTR)swtmrID;
873 return 0;
874 }
875
timer_delete(timer_t timerID)876 int timer_delete(timer_t timerID)
877 {
878 UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
879 VOID *arg = NULL;
880 UINTPTR swtmrProc;
881
882 #ifdef LOSCFG_SECURITY_VID
883 swtmrID = GetRidByVid(swtmrID);
884 #endif
885 if (OS_INT_ACTIVE || !ValidTimerID(swtmrID)) {
886 goto ERROUT;
887 }
888
889 arg = (VOID *)OS_SWT_FROM_SID(swtmrID)->uwArg;
890 swtmrProc = (UINTPTR)OS_SWT_FROM_SID(swtmrID)->pfnHandler;
891 if (LOS_SwtmrDelete(swtmrID)) {
892 goto ERROUT;
893 }
894 if ((swtmrProc == (UINTPTR)SwtmrProc) && (arg != NULL)) {
895 free(arg);
896 }
897
898 #ifdef LOSCFG_SECURITY_VID
899 RemoveNodeByVid((UINT16)(UINTPTR)timerID);
900 #endif
901 return 0;
902
903 ERROUT:
904 errno = EINVAL;
905 return -1;
906 }
907
timer_settime(timer_t timerID,int flags,const struct itimerspec * value,struct itimerspec * oldValue)908 int timer_settime(timer_t timerID, int flags,
909 const struct itimerspec *value, /* new value */
910 struct itimerspec *oldValue) /* old value to return, always 0 */
911 {
912 UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
913 SWTMR_CTRL_S *swtmr = NULL;
914 UINT32 interval, expiry, ret;
915 UINT32 intSave;
916
917 if (flags != 0) {
918 /* flags not supported currently */
919 errno = ENOSYS;
920 return -1;
921 }
922
923 #ifdef LOSCFG_SECURITY_VID
924 swtmrID = GetRidByVid(swtmrID);
925 #endif
926 if ((value == NULL) || OS_INT_ACTIVE || !ValidTimerID(swtmrID)) {
927 errno = EINVAL;
928 return -1;
929 }
930
931 if (!ValidTimeSpec(&value->it_value) || !ValidTimeSpec(&value->it_interval)) {
932 errno = EINVAL;
933 return -1;
934 }
935
936 if (oldValue) {
937 (VOID)timer_gettime(timerID, oldValue);
938 }
939
940 swtmr = OS_SWT_FROM_SID(swtmrID);
941 ret = LOS_SwtmrStop(swtmr->usTimerID);
942 if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
943 errno = EINVAL;
944 return -1;
945 }
946
947 expiry = OsTimeSpec2Tick(&value->it_value);
948 interval = OsTimeSpec2Tick(&value->it_interval);
949
950 LOS_SpinLockSave(&g_swtmrSpin, &intSave);
951 swtmr->ucMode = interval ? LOS_SWTMR_MODE_OPP : LOS_SWTMR_MODE_NO_SELFDELETE;
952 swtmr->uwExpiry = expiry + !!expiry; // PS: skip the first tick because it is NOT a full tick.
953 swtmr->uwInterval = interval;
954 swtmr->uwOverrun = 0;
955 LOS_SpinUnlockRestore(&g_swtmrSpin, intSave);
956
957 if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
958 /*
959 * 1) when expiry is 0, means timer should be stopped.
960 * 2) If timer is ticking, stopping timer is already done before.
961 * 3) If timer is created but not ticking, return 0 as well.
962 */
963 return 0;
964 }
965
966 if (LOS_SwtmrStart(swtmr->usTimerID)) {
967 errno = EINVAL;
968 return -1;
969 }
970
971 return 0;
972 }
973
timer_gettime(timer_t timerID,struct itimerspec * value)974 int timer_gettime(timer_t timerID, struct itimerspec *value)
975 {
976 UINT32 tick = 0;
977 SWTMR_CTRL_S *swtmr = NULL;
978 UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
979 UINT32 ret;
980
981 #ifdef LOSCFG_SECURITY_VID
982 swtmrID = GetRidByVid(swtmrID);
983 #endif
984 if ((value == NULL) || !ValidTimerID(swtmrID)) {
985 errno = EINVAL;
986 return -1;
987 }
988
989 swtmr = OS_SWT_FROM_SID(swtmrID);
990
991 /* get expire time */
992 ret = LOS_SwtmrTimeGet(swtmr->usTimerID, &tick);
993 if ((ret != LOS_OK) && (ret != LOS_ERRNO_SWTMR_NOT_STARTED)) {
994 errno = EINVAL;
995 return -1;
996 }
997
998 OsTick2TimeSpec(&value->it_value, tick);
999 OsTick2TimeSpec(&value->it_interval, (swtmr->ucMode == LOS_SWTMR_MODE_ONCE) ? 0 : swtmr->uwInterval);
1000 return 0;
1001 }
1002
timer_getoverrun(timer_t timerID)1003 int timer_getoverrun(timer_t timerID)
1004 {
1005 UINT16 swtmrID = (UINT16)(UINTPTR)timerID;
1006 SWTMR_CTRL_S *swtmr = NULL;
1007 INT32 overRun;
1008
1009 #ifdef LOSCFG_SECURITY_VID
1010 swtmrID = GetRidByVid(swtmrID);
1011 #endif
1012 if (!ValidTimerID(swtmrID)) {
1013 errno = EINVAL;
1014 return -1;
1015 }
1016
1017 swtmr = OS_SWT_FROM_SID(swtmrID);
1018 if (swtmr->usTimerID >= OS_SWTMR_MAX_TIMERID) {
1019 errno = EINVAL;
1020 return -1;
1021 }
1022
1023 overRun = (INT32)(swtmr->uwOverrun);
1024 return (overRun > DELAYTIMER_MAX) ? DELAYTIMER_MAX : overRun;
1025 }
1026
DoNanoSleep(UINT64 nanoseconds)1027 STATIC INT32 DoNanoSleep(UINT64 nanoseconds)
1028 {
1029 UINT32 ret;
1030
1031 ret = LOS_TaskDelay(OsNS2Tick(nanoseconds));
1032 if (ret == LOS_OK || ret == LOS_ERRNO_TSK_YIELD_NOT_ENOUGH_TASK) {
1033 return 0;
1034 }
1035 return -1;
1036 }
1037
1038 #ifdef LOSCFG_LIBC_NEWLIB
usleep(unsigned long useconds)1039 int usleep(unsigned long useconds)
1040 #else
1041 int usleep(unsigned useconds)
1042 #endif
1043 {
1044 return DoNanoSleep((UINT64)useconds * OS_SYS_NS_PER_US);
1045 }
1046
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)1047 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
1048 {
1049 UINT64 nanoseconds;
1050 INT32 ret = -1;
1051
1052 (VOID)rmtp;
1053 /* expire time */
1054
1055 if (!ValidTimeSpec(rqtp)) {
1056 errno = EINVAL;
1057 return ret;
1058 }
1059
1060 nanoseconds = (UINT64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + rqtp->tv_nsec;
1061
1062 return DoNanoSleep(nanoseconds);
1063 }
1064
sleep(unsigned int seconds)1065 unsigned int sleep(unsigned int seconds)
1066 {
1067 return DoNanoSleep((UINT64)seconds * OS_SYS_NS_PER_SECOND);
1068 }
1069
difftime(time_t time2,time_t time1)1070 double difftime(time_t time2, time_t time1)
1071 {
1072 return (double)(time2 - time1);
1073 }
1074
clock(VOID)1075 clock_t clock(VOID)
1076 {
1077 clock_t clockMsec;
1078 UINT64 nowNsec;
1079
1080 nowNsec = LOS_CurrNanosec();
1081 clockMsec = (clock_t)(nowNsec / (OS_SYS_NS_PER_SECOND / CLOCKS_PER_SEC));
1082
1083 return clockMsec;
1084 }
1085
times(struct tms * buf)1086 clock_t times(struct tms *buf)
1087 {
1088 clock_t clockTick = -1;
1089
1090 (void)buf;
1091 set_errno(ENOSYS);
1092
1093 return clockTick;
1094 }
1095
setitimer(int which,const struct itimerval * value,struct itimerval * ovalue)1096 int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
1097 {
1098 UINT32 intSave;
1099 LosProcessCB *processCB = OsCurrProcessGet();
1100 timer_t timerID = 0;
1101 struct itimerspec spec;
1102 struct itimerspec ospec;
1103 int ret = LOS_OK;
1104
1105 /* we only support the realtime clock timer currently */
1106 if (which != ITIMER_REAL || !value) {
1107 set_errno(EINVAL);
1108 return -1;
1109 }
1110
1111 /* To avoid creating an invalid timer after the timer has already been create */
1112 if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
1113 ret = OsTimerCreate(CLOCK_REALTIME, NULL, &timerID);
1114 if (ret != LOS_OK) {
1115 return ret;
1116 }
1117 }
1118
1119 /* The initialization of this global timer must be in spinlock
1120 * OsTimerCreate cannot be located in spinlock.
1121 */
1122 SCHEDULER_LOCK(intSave);
1123 if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
1124 processCB->timerID = timerID;
1125 SCHEDULER_UNLOCK(intSave);
1126 } else {
1127 SCHEDULER_UNLOCK(intSave);
1128 if (timerID) {
1129 timer_delete(timerID);
1130 }
1131 }
1132
1133 if (!ValidTimeval(&value->it_value) || !ValidTimeval(&value->it_interval)) {
1134 set_errno(EINVAL);
1135 return -1;
1136 }
1137
1138 TIMEVAL_TO_TIMESPEC(&value->it_value, &spec.it_value);
1139 TIMEVAL_TO_TIMESPEC(&value->it_interval, &spec.it_interval);
1140
1141 ret = timer_settime(processCB->timerID, 0, &spec, ovalue ? &ospec : NULL);
1142 if (ret == LOS_OK && ovalue) {
1143 TIMESPEC_TO_TIMEVAL(&ovalue->it_value, &ospec.it_value);
1144 TIMESPEC_TO_TIMEVAL(&ovalue->it_interval, &ospec.it_interval);
1145 }
1146
1147 return ret;
1148 }
1149
getitimer(int which,struct itimerval * value)1150 int getitimer(int which, struct itimerval *value)
1151 {
1152 LosProcessCB *processCB = OsCurrProcessGet();
1153 struct itimerspec spec = {};
1154
1155 int ret = LOS_OK;
1156
1157 /* we only support the realtime clock timer currently */
1158 if (which != ITIMER_REAL || !value) {
1159 set_errno(EINVAL);
1160 return -1;
1161 }
1162
1163 if (processCB->timerID != (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
1164 ret = timer_gettime(processCB->timerID, &spec);
1165 }
1166
1167 if (ret == LOS_OK) {
1168 TIMESPEC_TO_TIMEVAL(&value->it_value, &spec.it_value);
1169 TIMESPEC_TO_TIMEVAL(&value->it_interval, &spec.it_interval);
1170 }
1171
1172 return ret;
1173 }
1174
1175 #ifdef LOSCFG_KERNEL_VDSO
OsVdsoTimeGet(VdsoDataPage * vdsoDataPage)1176 VOID OsVdsoTimeGet(VdsoDataPage *vdsoDataPage)
1177 {
1178 UINT32 intSave;
1179 struct timespec64 tmp = {0};
1180 struct timespec64 hwTime = {0};
1181
1182 if (vdsoDataPage == NULL) {
1183 return;
1184 }
1185
1186 OsGetHwTime(&hwTime);
1187
1188 LOS_SpinLockSave(&g_timeSpin, &intSave);
1189 tmp = OsTimeSpecAdd(hwTime, g_accDeltaFromAdj);
1190 vdsoDataPage->monoTimeSec = tmp.tv_sec;
1191 vdsoDataPage->monoTimeNsec = tmp.tv_nsec;
1192
1193 tmp = OsTimeSpecAdd(tmp, g_accDeltaFromSet);
1194 vdsoDataPage->realTimeSec = tmp.tv_sec;
1195 vdsoDataPage->realTimeNsec = tmp.tv_nsec;
1196 LOS_SpinUnlockRestore(&g_timeSpin, intSave);
1197 }
1198 #endif
1199
time(time_t * t)1200 time_t time(time_t *t)
1201 {
1202 struct timeval tp;
1203 int ret;
1204
1205 /* Get the current time from the system */
1206 ret = gettimeofday(&tp, (struct timezone *)NULL);
1207 if (ret == LOS_OK) {
1208 /* Return the seconds since the epoch */
1209 if (t) {
1210 *t = tp.tv_sec;
1211 }
1212 return tp.tv_sec;
1213 }
1214 return (time_t)OS_ERROR;
1215 }
1216