• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3  *
4  * UniProton is licensed under Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *          http://license.coscl.org.cn/MulanPSL2
8  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11  * See the Mulan PSL v2 for more details.
12  * Create: 2022-11-15
13  * Description: time功能实现
14  */
15 #include "time.h"
16 #include "prt_posix_internal.h"
17 #include "prt_sys_external.h"
18 #include "prt_timer.h"
19 #include "prt_swtmr_external.h"
20 
21 #define OS_SYS_NS_PER_MS  (OS_SYS_NS_PER_SECOND / OS_SYS_MS_PER_SECOND)
22 
23 static struct timespec g_accDeltaFromSet;
24 
25 /* 封装超时处理函数 */
OsTimerWrapper(TimerHandle tmrHandle,U32 arg1,U32 arg2,U32 arg3,U32 arg4)26 static void OsTimerWrapper(TimerHandle tmrHandle, U32 arg1, U32 arg2, U32 arg3, U32 arg4)
27 {
28     (void)tmrHandle;
29     (void)arg3;
30     (void)arg4;
31     void *(*sigev_notify_function)(union sigval) = (void *)arg1;
32 
33     union sigval val = {
34         .sival_int = arg2
35     };
36 
37     sigev_notify_function(val);
38 }
39 
timer_create(clockid_t clockId,struct sigevent * restrict evp,timer_t * restrict timerId)40 int timer_create(clockid_t clockId, struct sigevent * restrict evp, timer_t * restrict timerId)
41 {
42     U32 ret;
43     TimerHandle swtmrId;
44     struct TimerCreatePara timer = {0};
45 
46     if ((timerId == NULL) || (evp == NULL) || (clockId != CLOCK_REALTIME)) {
47         errno = EINVAL;
48         return PTHREAD_OP_FAIL;
49     }
50 
51     if (evp->sigev_notify != SIGEV_THREAD) { // 必须有超时处理函数
52         errno = EINVAL;
53         return PTHREAD_OP_FAIL;
54     }
55 
56     timer.type = OS_TIMER_SOFTWARE;
57     timer.mode = OS_TIMER_LOOP;
58     timer.interval = 1;
59     timer.timerGroupId = 0;
60     timer.callBackFunc = OsTimerWrapper;
61     timer.arg1 = (U32)evp->sigev_notify_function;
62     timer.arg2 = (U32)evp->sigev_value.sival_int;
63     ret = PRT_TimerCreate(&timer, &swtmrId);
64     if (ret != OS_OK) {
65         errno = EINVAL;
66         return PTHREAD_OP_FAIL;
67     }
68 
69     *timerId = (timer_t)swtmrId;
70     return OS_OK;
71 }
72 
timer_delete(timer_t timerId)73 int timer_delete(timer_t timerId)
74 {
75     U32 swtmrId = (U32)timerId;
76 
77     if (PRT_TimerDelete(0, swtmrId) != OS_OK) {
78         errno = EINVAL;
79         return PTHREAD_OP_FAIL;
80     }
81 
82     return OS_OK;
83 }
84 
OsTimeGetHwTime(struct timespec * hwTime)85 void OsTimeGetHwTime(struct timespec *hwTime)
86 {
87     U64 cycle = OsCurCycleGet64();
88     U64 nowNsec = (cycle / g_systemClock) * OS_SYS_NS_PER_SECOND +
89         (cycle % g_systemClock) * OS_SYS_NS_PER_SECOND / g_systemClock;
90 
91     hwTime->tv_sec = nowNsec / OS_SYS_NS_PER_SECOND;
92     hwTime->tv_nsec = nowNsec % OS_SYS_NS_PER_SECOND;
93 }
94 
OsTimeSetRealTime(const struct timespec * realTime)95 void OsTimeSetRealTime(const struct timespec *realTime)
96 {
97     U32 intSave;
98     struct timespec hwTime = {0};
99 
100     OsTimeGetHwTime(&hwTime);
101     intSave = PRT_HwiLock();
102     g_accDeltaFromSet.tv_nsec = realTime->tv_nsec - hwTime.tv_nsec;
103     g_accDeltaFromSet.tv_sec = (realTime->tv_sec - hwTime.tv_sec) - (time_t)(g_accDeltaFromSet.tv_nsec < 0);
104     g_accDeltaFromSet.tv_nsec = (g_accDeltaFromSet.tv_nsec + OS_SYS_NS_PER_SECOND) % OS_SYS_NS_PER_SECOND;
105     PRT_HwiRestore(intSave);
106 }
107 
OsTimeGetRealTime(struct timespec * realTime)108 void OsTimeGetRealTime(struct timespec *realTime)
109 {
110     U32 intSave;
111     struct timespec hwTime = {0};
112 
113     OsTimeGetHwTime(&hwTime);
114 
115     intSave = PRT_HwiLock();
116     realTime->tv_nsec = hwTime.tv_nsec + g_accDeltaFromSet.tv_nsec;
117     realTime->tv_sec = hwTime.tv_sec + g_accDeltaFromSet.tv_sec + (time_t)(realTime->tv_nsec >= OS_SYS_NS_PER_SECOND);
118     realTime->tv_nsec %= OS_SYS_NS_PER_SECOND;
119     PRT_HwiRestore(intSave);
120 }
121 
OsTimeCheckSpec(const struct timespec * tp)122 bool OsTimeCheckSpec(const struct timespec *tp)
123 {
124     if (tp == NULL) {
125         return FALSE;
126     }
127 
128     if ((tp->tv_sec < 0) || (tp->tv_nsec < 0) || (tp->tv_nsec >= OS_SYS_NS_PER_SECOND)) {
129         return FALSE;
130     }
131 
132     return TRUE;
133 }
134 
OsTimeMs2Spec(U32 expireTime,struct timespec * tp)135 void OsTimeMs2Spec(U32 expireTime, struct timespec *tp)
136 {
137     U32 remainder;
138 
139     tp->tv_sec = expireTime / OS_SYS_MS_PER_SECOND;
140     remainder = expireTime - (U32)tp->tv_sec * OS_SYS_MS_PER_SECOND;
141     tp->tv_nsec = (long)remainder * OS_SYS_NS_PER_MS;
142 }
143 
OsTimeSpec2Ms(const struct timespec * tp,U32 * expireTime)144 void OsTimeSpec2Ms(const struct timespec *tp, U32 *expireTime)
145 {
146     U32 tickCnt;
147 
148     tickCnt = OsTimeSpec2Tick(tp);
149 
150     *expireTime = (tickCnt / g_tickModInfo.tickPerSecond) * OS_SYS_MS_PER_SECOND;
151 }
152 
OsTimeSpec2Tick(const struct timespec * tp)153 U32 OsTimeSpec2Tick(const struct timespec *tp)
154 {
155     U64 ns;
156     U64 tmp;
157     U64 tickCnt;
158     U32 nsPerTick;
159 
160     nsPerTick = OS_SYS_NS_PER_SECOND / OsSysGetTickPerSecond(); // 每个tick多少纳秒
161     ns = (U64)tp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)tp->tv_nsec;
162     tickCnt = ns / nsPerTick;
163     tmp = ns - tickCnt * nsPerTick;
164     if (tmp > 0) {
165         tickCnt++;
166     }
167 
168     if (tickCnt > U32_MAX) {
169         tickCnt = U32_MAX;
170     }
171 
172     return (U32)tickCnt;
173 }
174 
OsTimeOut2Ticks(const struct timespec * time,U32 * ticks)175 U32 OsTimeOut2Ticks(const struct timespec *time, U32 *ticks)
176 {
177     struct timespec curTime;
178     S64 timeOutNs;
179     U64 timeOut;
180 
181     if ((time->tv_nsec < 0) || (time->tv_nsec >= OS_SYS_NS_PER_SECOND) ||
182         (time->tv_sec < 0) || (time->tv_sec > S32_MAX)) {
183         return EINVAL;
184     }
185 
186     OsTimeGetRealTime(&curTime);
187 
188     timeOutNs = (time->tv_sec - curTime.tv_sec) * OS_SYS_NS_PER_SECOND + (time->tv_nsec - curTime.tv_nsec);
189     if (timeOutNs <= 0) {
190         return ETIMEDOUT;
191     }
192 
193     timeOut = (U64)(time->tv_sec - curTime.tv_sec) * OsSysGetTickPerSecond();
194     if (time->tv_nsec > curTime.tv_nsec) {
195         timeOut += ((U64)(time->tv_nsec - curTime.tv_nsec) * OsSysGetTickPerSecond() - 1) / OS_SYS_NS_PER_SECOND + 1;
196     } else {
197         timeOut -= ((U64)(curTime.tv_nsec - time->tv_nsec) * OsSysGetTickPerSecond()) / OS_SYS_NS_PER_SECOND;
198     }
199     // 因为tick误差在ms级,为了确保延时时间满足要求,向上加一
200     timeOut = timeOut + 1;
201     *ticks = timeOut >= OS_WAIT_FOREVER ? OS_WAIT_FOREVER : (U32)timeOut;
202 
203     return OS_OK;
204 }
205 
timer_gettime(timer_t timerId,struct itimerspec * value)206 int timer_gettime(timer_t timerId, struct itimerspec *value)
207 {
208     U32 ret;
209     U32 expireTime; // 剩余超时时间,单位ms
210     struct SwTmrInfo info;
211 
212     if (value == NULL) {
213         errno = EINVAL;
214         return PTHREAD_OP_FAIL;
215     }
216 
217     ret = PRT_TimerQuery(0, (TimerHandle)timerId, &expireTime);
218     if (ret != OS_OK) {
219         errno = EINVAL;
220         return PTHREAD_OP_FAIL;
221     }
222 
223     ret = PRT_SwTmrInfoGet((TimerHandle)timerId, &info);
224     if (ret != OS_OK) {
225         errno = EINVAL;
226         return PTHREAD_OP_FAIL;
227     }
228 
229     OsTimeMs2Spec(expireTime, &value->it_value);
230     OsTimeMs2Spec((info.mode == OS_TIMER_ONCE) ? 0 : info.interval, &value->it_interval);
231 
232     return OS_OK;
233 }
234 
timer_settime(timer_t timerId,int flags,const struct itimerspec * value,struct itimerspec * ovalue)235 int timer_settime(timer_t timerId, int flags, const struct itimerspec *value, struct itimerspec *ovalue)
236 {
237     U32 intSave;
238     U32 interval, expiry, ret;
239     struct TagSwTmrCtrl *swtmr;
240     (void)flags;
241 
242     if (value == NULL) {
243         errno = EINVAL;
244         return PTHREAD_OP_FAIL;
245     }
246 
247     if (!OsTimeCheckSpec(&value->it_value) || !OsTimeCheckSpec(&value->it_interval)) {
248         errno = EINVAL;
249         return PTHREAD_OP_FAIL;
250     }
251 
252     expiry = OsTimeSpec2Tick(&value->it_value);
253     interval = OsTimeSpec2Tick(&value->it_interval);
254 
255     if (interval != 0 && interval != expiry) {
256         errno = ENOTSUP;
257         return PTHREAD_OP_FAIL;
258     }
259 
260     if (ovalue) {
261         if (timer_gettime(timerId, ovalue) != OS_OK) {
262             errno = EINVAL;
263             return PTHREAD_OP_FAIL;
264         }
265     }
266 
267     ret = PRT_TimerStop(0, timerId);
268     if (ret != OS_OK && ret != OS_ERRNO_SWTMR_UNSTART) {
269         errno = EINVAL;
270         return PTHREAD_OP_FAIL;
271     }
272 
273     // 当 it_value = 0, 表示要停止定时器.
274     if ((value->it_value.tv_sec == 0) && (value->it_value.tv_nsec == 0)) {
275         return OS_OK;
276     }
277 
278     intSave = PRT_HwiLock();
279     swtmr = g_swtmrCbArray + OS_SWTMR_ID_2_INDEX(timerId);
280     swtmr->mode = (interval ? OS_TIMER_LOOP : OS_TIMER_ONCE);
281     swtmr->interval = (interval ? interval : expiry);
282     swtmr->idxRollNum = swtmr->interval;
283     PRT_HwiRestore(intSave);
284 
285     if (PRT_TimerStart(0, timerId) != OS_OK) {
286         errno = EINVAL;
287         return PTHREAD_OP_FAIL;
288     }
289 
290     return OS_OK;
291 }
292 
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)293 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
294 {
295     U64 nanosec;
296     U64 tick;
297     const U32 nsPerTick = OS_SYS_NS_PER_SECOND / g_tickModInfo.tickPerSecond;
298 
299     if (!OsTimeCheckSpec(rqtp)) {
300         errno = EINVAL;
301         return PTHREAD_OP_FAIL;
302     }
303 
304     nanosec = (U64)rqtp->tv_sec * OS_SYS_NS_PER_SECOND + (U64)rqtp->tv_nsec;
305     tick = (nanosec + nsPerTick - 1) / nsPerTick; // 睡眠时间不得小于rqtp规定的时间
306 
307     if (tick >= U32_MAX) {
308         errno = EINVAL;
309         return PTHREAD_OP_FAIL;
310     }
311 
312     if (PRT_TaskDelay((U32)tick) == OS_OK) {
313         if (rmtp != NULL) {
314             rmtp->tv_sec = rmtp->tv_nsec = 0;
315         }
316         return OS_OK;
317     }
318 
319     return PTHREAD_OP_FAIL;
320 }
321 
sleep(U32 seconds)322 U32 sleep(U32 seconds)
323 {
324     U32 ret;
325     U32 ticks;
326 
327     ticks = seconds * g_tickModInfo.tickPerSecond;
328     ret = PRT_TaskDelay(ticks ? (ticks + 1) : 0);
329     if (ret != OS_OK) {
330         return EINTR;
331     }
332 
333     return OS_OK;
334 }
335 
clock_getres(clockid_t clockId,struct timespec * tp)336 int clock_getres(clockid_t clockId, struct timespec *tp)
337 {
338     if (tp == NULL) {
339         errno = EINVAL;
340         return PTHREAD_OP_FAIL;
341     }
342 
343     switch (clockId) {
344         case CLOCK_MONOTONIC_RAW:
345         case CLOCK_MONOTONIC:
346         case CLOCK_REALTIME:
347         case CLOCK_MONOTONIC_COARSE:
348         case CLOCK_REALTIME_COARSE:
349             tp->tv_nsec = (long)((OS_SYS_NS_PER_SECOND - 1) / g_systemClock + 1); // 每个cycle多少ns
350             tp->tv_sec = 0;
351             return OS_OK;
352         case CLOCK_PROCESS_CPUTIME_ID:
353         case CLOCK_BOOTTIME:
354         case CLOCK_REALTIME_ALARM:
355         case CLOCK_BOOTTIME_ALARM:
356             errno = ENOTSUP;
357             return PTHREAD_OP_FAIL;
358         default:
359             errno = EINVAL;
360             return PTHREAD_OP_FAIL;
361     }
362 }
363 
clock_settime(clockid_t clockId,const struct timespec * tp)364 int clock_settime(clockid_t clockId, const struct timespec *tp)
365 {
366     if (!OsTimeCheckSpec(tp)) {
367         errno = EINVAL;
368         return PTHREAD_OP_FAIL;
369     }
370 
371     switch (clockId) {
372         case CLOCK_REALTIME:
373             OsTimeSetRealTime(tp);
374             return OS_OK;
375         case CLOCK_MONOTONIC_COARSE:
376         case CLOCK_REALTIME_COARSE:
377         case CLOCK_MONOTONIC_RAW:
378         case CLOCK_BOOTTIME:
379         case CLOCK_REALTIME_ALARM:
380         case CLOCK_BOOTTIME_ALARM:
381             errno = ENOTSUP;
382             return PTHREAD_OP_FAIL;
383         case CLOCK_MONOTONIC:
384         default:
385             errno = EINVAL;
386             return PTHREAD_OP_FAIL;
387     }
388 }
389 
clock_gettime(clockid_t clockId,struct timespec * tp)390 int clock_gettime(clockid_t clockId, struct timespec *tp)
391 {
392     if (tp == NULL) {
393         errno = EINVAL;
394         return PTHREAD_OP_FAIL;
395     }
396 
397     switch (clockId) {
398         case CLOCK_MONOTONIC_RAW:
399         case CLOCK_MONOTONIC:
400         case CLOCK_MONOTONIC_COARSE:
401             OsTimeGetHwTime(tp);
402             return OS_OK;
403         case CLOCK_REALTIME:
404         case CLOCK_REALTIME_COARSE:
405             OsTimeGetRealTime(tp);
406             return OS_OK;
407         case CLOCK_BOOTTIME:
408         case CLOCK_REALTIME_ALARM:
409         case CLOCK_BOOTTIME_ALARM:
410             errno = ENOTSUP;
411             return PTHREAD_OP_FAIL;
412         default:
413             errno = EINVAL;
414             return PTHREAD_OP_FAIL;
415     }
416 }
417