2 * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup tag_NSTimer
19 /// \brief Native Services Timer Interface code
23 ///////////////////////////////////////////////////////////////////////////////
29 #include <sys/epoll.h>
30 #include <sys/eventfd.h>
31 #include <sys/timerfd.h>
32 #include <sys/prctl.h>
34 #include <native_service/ns_timer_if.h>
35 #include <ns_timer_handle.h>
36 #include <native_service/ns_message_center_if.h>
37 #include <ns_timer_internal.h>
38 #include <native_service/ns_logger_if.h>
39 #include <native_service/ns_resource_controler.h>
41 #define INVALID_TIMERFD -1
43 #define RUNNING_STATE 0
44 #define DELETING_STATE 1
45 #define DELETED_STATE 2
47 #define MAX_FD_EPOLL 10
49 int epollFd; // To listen to multiple timerfd events.
50 int eventFd; // To use not complete at epoll_wait
51 pthread_t timerTh_id = 0; // Thread ID of the TimerMonitoringThread
52 pthread_mutex_t m_mtx = PTHREAD_MUTEX_INITIALIZER;
54 const UI_32 MS_IN_SEC = 1000;
55 const UI_64 NS_IN_MS = 1000000;
57 BOOL DebugFlag = FALSE;
59 static PVOID TimerMonitoringThread(PVOID args) {
60 struct epoll_event events[MAX_FD_EPOLL];
61 int nfds; // The number of events received
62 int n; // Loop counter
63 PNSTimerHandle hTimer;
68 #define NSTIMER_APPEND_NAME "_T"
69 #ifndef NSTIMER_SIZE_PROCESSNAME
70 #define NSTIMER_SIZE_PROCESSNAME 15 // Profiler analysis tool name length limitations
72 prctl(PR_GET_NAME, name);
73 name[NSTIMER_SIZE_PROCESSNAME] = '\0';
74 if (strlen(name) + strlen(NSTIMER_APPEND_NAME) > NSTIMER_SIZE_PROCESSNAME) {
75 p = name + NSTIMER_SIZE_PROCESSNAME - strlen(NSTIMER_APPEND_NAME);
77 p = name + strlen(name);
79 strcpy(p, NSTIMER_APPEND_NAME);
80 prctl(PR_SET_NAME, name);
83 nfds = epoll_wait(epollFd, events, MAX_FD_EPOLL, -1);
85 for (n = 0; n < nfds; ++n) {
86 hTimer = (PNSTimerHandle)events[n].data.ptr;
88 if (-1 == read(hTimer->timerfd, &exp, sizeof(uint64_t))) {
89 if (errno != EAGAIN) {
90 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
91 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "Failed to read in timeout : fd=%d, errno=%d",
92 hTimer->timerfd, errno);
98 if (RUNNING_STATE == hTimer->timerState) {
99 if (NULL != hTimer->tTimerInfo) {
100 EFrameworkunifiedStatus eStatus;
101 HANDLE hReceiver = NULL;
102 if (frameworkunifiedAcquireResouce(FRAMEWORKUNIFIED_RES_TIMER, hTimer->tTimerInfo->q_name, (long *)&hReceiver) < 0) {
103 if ((hReceiver = McOpenSender(hTimer->tTimerInfo->q_name)) == NULL) {
104 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
105 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : McOpenSender is Failed");
109 if (frameworkunifiedRegistResouce(FRAMEWORKUNIFIED_RES_TIMER, hTimer->tTimerInfo->q_name, (long)hReceiver, 1) < 0) {
110 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
111 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : frameworkunifiedRegistResouce is Failed : q_name=%s",
112 hTimer->tTimerInfo->q_name);
118 eStatus = McSendWithPriority(hReceiver,
120 hTimer->tTimerInfo->iCmd,
123 eFrameworkunifiedMsgPrioEmergency,
125 if (eFrameworkunifiedStatusOK != eStatus) {
126 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
127 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : McSendWithPriority to %s is Failed, eStatus=%d", hTimer->tTimerInfo->q_name,
132 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
133 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR(RUNNING_STATE) : tTimerInfo is NULL");
136 } else if (DELETED_STATE == hTimer->timerState) {
137 if (-1 == epoll_ctl(epollFd, EPOLL_CTL_DEL, hTimer->timerfd, events)) {
138 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
139 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : epoll_ctl(DEL) Failed, fd=%d, errno=%d",
140 hTimer->timerfd, errno);
144 if (-1 == close(hTimer->timerfd)) {
145 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
146 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : close(fd=%d) Failed, errno=%d", hTimer->timerfd, errno);
150 hTimer->timerfd = INVALID_TIMERFD;
152 if (NULL != hTimer->tTimerInfo) {
154 if (frameworkunifiedAcquireResouce(FRAMEWORKUNIFIED_RES_TIMER, hTimer->tTimerInfo->q_name, (long *)&hReceiver) >= 0) {
155 if (frameworkunifiedReleaseResouce(FRAMEWORKUNIFIED_RES_TIMER, hTimer->tTimerInfo->q_name) <= 0) {
156 frameworkunifiedUnregistResouce(FRAMEWORKUNIFIED_RES_TIMER, hTimer->tTimerInfo->q_name);
160 free(hTimer->tTimerInfo->q_name);
161 free(hTimer->tTimerInfo); // delete the timer info
162 hTimer->tTimerInfo = NULL;
164 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
165 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR(DELETED_STATE) : tTimerInfo is NULL");
169 free(hTimer); // delete the handle
170 events[n].data.ptr = NULL;
175 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
176 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : hTimer is NULL");
181 if (errno == EINTR) {
184 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
185 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : epoll_wait Failed, errno=%d", errno);
193 static EFrameworkunifiedStatus CreateTimerMonitoringThread() {
194 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
195 struct epoll_event ev; // Info struct to associate with multiwaiting FD
198 pthread_mutex_lock(&m_mtx);
200 // Create the TimerMonitoringThread If the thread has not been generated.
201 if (0 == timerTh_id) {
202 epollFd = epoll_create1(EPOLL_CLOEXEC);
204 eventFd = eventfd(0, EFD_CLOEXEC);
207 ev.data.fd = eventFd;
208 if (-1 != epoll_ctl(epollFd, EPOLL_CTL_ADD, eventFd, &ev)) {
209 if (0 != (ret = pthread_create(&timerTh_id, NULL, TimerMonitoringThread, NULL))) {
210 eStatus = eFrameworkunifiedStatusFail;
211 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
212 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "Failed to pthread_create : errno %d", ret);
216 eStatus = eFrameworkunifiedStatusFail;
217 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
218 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : epoll_ctl(eventFd=%d, ADD) Failed, status=%d, errno=%d", eventFd, eStatus,
223 eStatus = eFrameworkunifiedStatusFail;
224 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
225 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR :eventfd Failed, status=%d, errno=%d", eStatus, errno);
229 eStatus = eFrameworkunifiedStatusFail;
230 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
231 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : epoll_create1 Failed, status=%d, errno=%d",
238 if (TRUE == DebugFlag) { // LCOV_EXCL_BR_LINE 7: debug code
239 // LCOV_EXCL_START 7: debug code
240 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
241 FRAMEWORKUNIFIEDLOG(ZONE_NS_IMP_INFO, __FUNCTION__, "[DEBUG] sleep 3 Sec START.");
243 FRAMEWORKUNIFIEDLOG(ZONE_NS_IMP_INFO, __FUNCTION__, "[DEBUG] sleep 3 Sec END.");
246 pthread_mutex_unlock(&m_mtx);
251 HANDLE NS_TimerCreate(NSTimerInfo timer_info, eNSTimerCallbackMechanism cbMech, HANDLE sndMqHndl) {
252 PNSTimerHandle hTimer = NULL;
254 if ((NULL != sndMqHndl) && (cbMech == CALLBACK_MESSAGE)) {
255 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
257 PTimerInfo pTimerInfo = NULL;
258 struct epoll_event ev; // Info struct to associate with multiwaiting FD
259 int timerfd = INVALID_TIMERFD;
261 eStatus = CreateTimerMonitoringThread();
262 if (eFrameworkunifiedStatusOK == eStatus) {
263 hTimer = (PNSTimerHandle)malloc(sizeof(NSTimerHandle));
264 if (NULL != hTimer) { // LCOV_EXCL_BR_LINE 5: malloc's error case
265 pTimerInfo = (PTimerInfo)malloc(sizeof(TTimerInfo));
267 if (NULL != pTimerInfo) { // LCOV_EXCL_BR_LINE 5: malloc's error case
268 hTimer->timerState = RUNNING_STATE;
270 // set the timer info structure
271 PCSTR pName = McGetQueueName(sndMqHndl);
273 pTimerInfo->q_name = strdup(pName);
275 pTimerInfo->q_name = NULL;
276 eStatus = eFrameworkunifiedStatusNullPointer;
277 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
278 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : McGetQueueName(sndMqHndl) Failed, status=%d", eStatus);
282 if (eFrameworkunifiedStatusOK == eStatus) {
283 pTimerInfo->iCmd = timer_info.iCmd;
285 hTimer->tTimerInfo = pTimerInfo;
286 if (INVALID_TIMERFD != (timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC|TFD_NONBLOCK))) {
288 ev.data.ptr = hTimer;
289 if (-1 != epoll_ctl(epollFd, EPOLL_CTL_ADD, timerfd, &ev)) {
290 hTimer->timerfd = timerfd;
291 if (eFrameworkunifiedStatusOK == NS_TimerSetTime(hTimer, timer_info)) {
292 // set the interval in timer handle
293 hTimer->itime.it_value.tv_sec = (__time_t)timer_info.t_sec;
294 hTimer->itime.it_value.tv_nsec = (__syscall_slong_t)timer_info.t_nsec;
295 hTimer->itime.it_interval.tv_sec = (__time_t)timer_info.rpt_sec;
296 hTimer->itime.it_interval.tv_nsec = (__syscall_slong_t)timer_info.rpt_nsec;
299 eStatus = eFrameworkunifiedStatusErrOther;
301 // if timer interval is not set or memory is not allocated for hTimer
303 timerfd = INVALID_TIMERFD;
306 eStatus = eFrameworkunifiedStatusFail;
307 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
308 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : epoll_ctl(timerfd=%d, ADD) Failed, status=%d, errno=%d", timerfd, eStatus,
313 eStatus = eFrameworkunifiedStatusErrOther;
317 // LCOV_EXCL_START 5: malloc's error case
318 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
319 eStatus = eFrameworkunifiedStatusNullPointer;
320 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : (PTimerInfo)malloc(sizeof(TTimerInfo)) Failed, status=%d", eStatus);
324 if (eFrameworkunifiedStatusOK != eStatus) {
325 if (NULL != pTimerInfo) {
326 if (NULL != pTimerInfo->q_name) {
327 free(pTimerInfo->q_name);
328 pTimerInfo->q_name = NULL;
335 if (NULL != hTimer) {
341 // LCOV_EXCL_START 5: malloc's error case
342 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
343 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : malloc(sizeof(NSTimerHandle)) Failed");
347 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
348 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : CreateTimerMonitoringThread Failed, status=%d", eStatus);
352 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
353 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : Invalid param");
360 EFrameworkunifiedStatus NS_TimerDelete(HANDLE hTimer) {
361 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
362 if (NULL != hTimer) {
363 PNSTimerHandle tTimerHndl = (PNSTimerHandle)hTimer;
366 * Dropping by typing the service handle instead of the timer handle
368 if (DELETED_STATE != tTimerHndl->timerState) {
369 if (NULL != tTimerHndl->tTimerInfo) {
370 tTimerHndl->timerState = DELETING_STATE;
371 NSTimerInfo timer_info = {1, 0, tTimerHndl->tTimerInfo->iCmd, 0, 0};
373 if (eFrameworkunifiedStatusOK != (eStatus = NS_TimerSetTime(tTimerHndl, timer_info))) {
374 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
375 FRAMEWORKUNIFIEDLOG(ZONE_NS_WAR, __FUNCTION__, "ERROR : NS_TimerSetTime for Timer delete Failed, status=%d", eStatus);
379 tTimerHndl->timerState = DELETED_STATE;
381 eStatus = eFrameworkunifiedStatusInvldParam;
382 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
383 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : tTimerInfo is NULL, status=%d", eStatus);
387 eStatus = eFrameworkunifiedStatusFail;
388 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
389 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : Timer is not RUNNING State, timerStatus=%d, status=%d",
390 tTimerHndl->timerState, eStatus);
394 eStatus = eFrameworkunifiedStatusInvldParam;
395 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
396 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : hTimer is NULL, status=%d", eStatus);
403 EFrameworkunifiedStatus NS_TimerSetTime(HANDLE hTimer, NSTimerInfo timer_info) {
404 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
406 if (NULL != hTimer) {
407 PNSTimerHandle tTimerHndl = (PNSTimerHandle)hTimer;
408 struct itimerspec itime;
410 if (DELETED_STATE != tTimerHndl->timerState) {
411 // set periodic interval values
412 itime.it_value.tv_sec = (__time_t)timer_info.t_sec;
413 itime.it_value.tv_nsec = (__syscall_slong_t)timer_info.t_nsec;
415 // set periodic interval values
416 itime.it_interval.tv_sec = (__time_t)timer_info.rpt_sec;
417 itime.it_interval.tv_nsec = (__syscall_slong_t)timer_info.rpt_nsec;
419 if (-1 != timerfd_settime(tTimerHndl->timerfd, 0, &itime, NULL)) {
420 // updated the value of the timer values in the handler
421 tTimerHndl->itime = itime;
423 eStatus = eFrameworkunifiedStatusFail;
424 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
425 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : timerfd_settime is failed, status=%d, errno=%d", eStatus, errno);
429 eStatus = eFrameworkunifiedStatusFail;
430 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
431 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : Timer is not RUNNING State, status=%d", eStatus);
435 eStatus = eFrameworkunifiedStatusInvldHandle;
436 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
437 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : hTimer is NULL, status=%d", eStatus);
444 EFrameworkunifiedStatus NS_TimerGetTime(HANDLE hTimer, NSTimerInfo *timer_info) {
445 EFrameworkunifiedStatus eStatus = eFrameworkunifiedStatusOK;
447 if ((NULL != hTimer) && (NULL != timer_info)) {
448 PNSTimerHandle tTimerHndl = (PNSTimerHandle)hTimer;
449 struct itimerspec itime;
451 if (DELETED_STATE != tTimerHndl->timerState) {
452 if (-1 != timerfd_gettime(tTimerHndl->timerfd, &itime)) {
453 // set periodic interval values
455 // timer_info->t_sec = (UI_32)itime.it_value.tv_sec;
456 timer_info->t_sec = itime.it_value.tv_sec;
457 timer_info->t_nsec = (UI_64)itime.it_value.tv_nsec;
459 // set periodic interval values
461 // timer_info->rpt_sec = (UI_32)itime.it_interval.tv_sec;
462 timer_info->rpt_sec = itime.it_interval.tv_sec;
463 timer_info->rpt_nsec = (UI_64)itime.it_interval.tv_nsec;
465 eStatus = eFrameworkunifiedStatusFail;
466 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
467 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : timerfd_gettime is failed, status=%d, errno=%d", eStatus, errno);
471 eStatus = eFrameworkunifiedStatusFail;
472 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
473 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : Timer is not RUNNING State, status=%d", eStatus);
477 eStatus = eFrameworkunifiedStatusInvldHandle;
478 // LCOV_EXCL_BR_START 15:marco defined in "native_service/ns_logger_if.h"
479 FRAMEWORKUNIFIEDLOG(ZONE_NS_ERR, __FUNCTION__, "ERROR : Invalid param, status=%d", eStatus);
487 //UI_32 WholeSeconds(UI_32 ms) {
488 // return ms / MS_IN_SEC;
490 time_t WholeSeconds(UI_32 ms) {
491 return (time_t)(ms / MS_IN_SEC);
495 UI_32 RemainderMs(UI_32 ms) {
496 return ms % MS_IN_SEC;
499 UI_64 MSToNS(UI_32 ms) {
500 return (UI_64)ms * NS_IN_MS;
503 void NS_TimerDebugOn(BOOL FlagState) { // LCOV_EXCL_START 7: debug code
504 AGL_ASSERT_NOT_TESTED(); // LCOV_EXCL_LINE 200: test assert
505 if (DebugFlag != FlagState) {
506 DebugFlag = FlagState;
507 if (TRUE == DebugFlag) {
508 FRAMEWORKUNIFIEDLOG(ZONE_NS_IMP_INFO, __FUNCTION__, "NS_Timer debugging is enabled.");
510 FRAMEWORKUNIFIEDLOG(ZONE_NS_IMP_INFO, __FUNCTION__, "NS_Timer debugging is disabled.");