Re-organized sub-directory by category
[staging/basesystem.git] / service / native / common_library / client / src / cl_sem.c
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <semaphore.h>
21 #include <time.h>
22
23 #include <native_service/cl_sem.h>
24 #include "cl_error.h"
25
26 #define CL_MILLI_TO_NANO(time)  ((time) * 1000000U)
27 #define CL_SEC_TO_NANO(time)  ((time) * 1000000000U)
28 #define CL_NANO_TO_SEC(time)  ((time) / 1000000000U)
29
30 static void cl_TimeoutCalc(struct timespec *ts, unsigned int timeout) {
31   unsigned long long  nsec;
32
33   clock_gettime(CLOCK_REALTIME, ts);
34   nsec = (unsigned long long)ts->tv_nsec + (CL_MILLI_TO_NANO((unsigned long long)timeout));
35   ts->tv_sec = ts->tv_sec + (time_t)CL_NANO_TO_SEC(nsec);
36   ts->tv_nsec = (__syscall_slong_t)(nsec - CL_SEC_TO_NANO((unsigned long long)CL_NANO_TO_SEC(nsec)));
37 }
38
39 int CL_SemWait(sem_t *semid, unsigned int timeout) {
40   struct timespec ts, tmp;
41   int       ret;
42
43   while (1) {
44     cl_TimeoutCalc(&ts, timeout);
45     if ((ret = sem_timedwait(semid, &ts)) != 0) {  // LCOV_EXCL_BR_LINE 5: fail safe for libc
46       // LCOV_EXCL_START 5: fail safe for libc
47       AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
48       if (errno == ETIMEDOUT) {
49         /* Check the time considering the case where the time has been changed by clock_settime/settimeofday */
50         /* If the current time is much larger than the timeout specified time,
51            the system assumes that the time has changed and re-executes the command.
52            (A threshold of 100 is appropriate) */
53         clock_gettime(CLOCK_REALTIME, &tmp);
54         if (difftime(tmp.tv_sec, ts.tv_sec) > 100.0) {
55           CL_DBG_PRINT("detect clock changed\n");
56           continue;
57         }
58       }
59     }
60     // LCOV_EXCL_STOP 5: fail safe for libc
61     break;
62     AGL_ASSERT_NOT_TESTED();  // LCOV_EXCL_LINE 200: test assert
63   } // LCOV_EXCL_LINE 10: end line
64
65   return ret;
66 }
67