diff options
Diffstat (limited to 'src/framework/ipc/ps/nsfw_fd_timer.c')
-rw-r--r-- | src/framework/ipc/ps/nsfw_fd_timer.c | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/src/framework/ipc/ps/nsfw_fd_timer.c b/src/framework/ipc/ps/nsfw_fd_timer.c new file mode 100644 index 0000000..57535a3 --- /dev/null +++ b/src/framework/ipc/ps/nsfw_fd_timer.c @@ -0,0 +1,378 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at: +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include <stdlib.h> +#include <errno.h> +#include <stdio.h> +#include <sys/timerfd.h> + +#include "types.h" +#include "list.h" + +#include "nstack_securec.h" +#include "nsfw_init.h" +#include "nsfw_mgr_com_api.h" +#include "nsfw_mem_api.h" +#include "nstack_log.h" +#include "nsfw_base_linux_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" + +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C"{ +/* *INDENT-ON* */ +#endif /* __cplusplus */ + +#define NSFW_TIMER_CYCLE 1 +#define NSFW_TIMER_INFO_MAX_COUNT_DEF 8191 +#define NSFW_TIMER_INFO_MAX_COUNT (g_timer_cfg.timer_info_size) +/* *INDENT-OFF* */ +nsfw_timer_init_cfg g_timer_cfg; + +u8 g_hbt_switch = FALSE; +/* *INDENT-ON* */ + +/***************************************************************************** +* Prototype : nsfw_timer_reg_timer +* Description : reg timer with callback function when timeout +* Input : u32 timer_type +* void* data +* nsfw_timer_proc_fun fun +* struct timespec time_left +* Output : None +* Return Value : nsfw_timer_info* +* Calls : +* Called By : +* +*****************************************************************************/ +nsfw_timer_info * +nsfw_timer_reg_timer (u32 timer_type, void *data, + nsfw_timer_proc_fun fun, struct timespec time_left) +{ + nsfw_timer_info *tm_info = NULL; + if (0 == + nsfw_mem_ring_dequeue (g_timer_cfg.timer_info_pool, (void *) &tm_info)) + { + NSFW_LOGERR ("dequeue error]data=%p,fun=%p", data, fun); + return NULL; + } + + if (EOK != MEMSET_S (tm_info, sizeof (*tm_info), 0, sizeof (*tm_info))) + { + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("enqueue error]data=%p,fun=%p", data, fun); + } + NSFW_LOGERR ("mem set error]data=%p,fun=%p", data, fun); + return NULL; + } + + tm_info->fun = fun; + tm_info->argv = data; + tm_info->time_left = time_left; + //tm_info->time_left.tv_sec += NSFW_TIMER_CYCLE; + tm_info->timer_type = timer_type; + list_add_tail (&tm_info->node, &g_timer_cfg.timer_head); + tm_info->alloc_flag = TRUE; + return tm_info; +} + +/***************************************************************************** +* Prototype : nsfw_timer_rmv_timer +* Description : stop timer +* Input : nsfw_timer_info* tm_info +* Output : None +* Return Value : void +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_rmv_timer (nsfw_timer_info * tm_info) +{ + if (NULL == tm_info) + { + NSFW_LOGWAR ("tm_info nul"); + return; + } + + if (FALSE == tm_info->alloc_flag) + { + NSFW_LOGERR ("tm_info refree]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + return; + } + + tm_info->alloc_flag = FALSE; + list_del (&tm_info->node); + if (0 == nsfw_mem_ring_enqueue (g_timer_cfg.timer_info_pool, tm_info)) + { + NSFW_LOGERR ("tm_info free failed]tm_info=%p,argv=%p,fun=%p", tm_info, + tm_info->argv, tm_info->fun); + } + return; +} + +/***************************************************************************** +* Prototype : nsfw_timer_exp +* Description : timer expire +* Input : u64 count +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +void +nsfw_timer_exp (u64 count) +{ + nsfw_timer_info *tm_info = NULL; + struct list_head *tNode; + struct list_head *tPretNode; + + LINT_LIST ()list_for_each_entry (tm_info, tNode, (&g_timer_cfg.timer_head), + node) + { + tPretNode = tm_info->node.prev; + if (tm_info->time_left.tv_sec > (long) count * NSFW_TIMER_CYCLE) + { + tm_info->time_left.tv_sec -= count * NSFW_TIMER_CYCLE; + continue; + } + + list_del (&tm_info->node); + list_add_tail (&tm_info->node, &g_timer_cfg.exp_timer_head); + tNode = tPretNode; + } + + u32 i = 0; + while (!list_empty (&g_timer_cfg.exp_timer_head) + && i++ < NSFW_TIMER_INFO_MAX_COUNT) + { + tm_info = + (nsfw_timer_info *) list_get_first (&g_timer_cfg.exp_timer_head); + if (NULL != tm_info->fun) + { + (void) tm_info->fun (tm_info->timer_type, tm_info->argv); + } + nsfw_timer_rmv_timer (tm_info); + } + +} + +/***************************************************************************** +* Prototype : nsfw_get_timer_socket +* Description : get timer socket from kernel +* Input : None +* Output : None +* Return Value : i32 +* Calls : +* Called By : +*****************************************************************************/ +i32 +nsfw_get_timer_socket () +{ + i32 tfd = timerfd_create (CLOCK_MONOTONIC, TFD_NONBLOCK); + if (tfd == -1) + { + NSFW_LOGERR ("timerfd_create failed!]errno=%d\n", errno); + return -1; + } + + /* close on exe */ + if (-1 == nsfw_set_close_on_exec (tfd)) + { + (void) nsfw_base_close (tfd); + NSFW_LOGERR ("set exec err]fd=%d, errno=%d", tfd, errno); + return -1; + } + + struct itimerspec ts; + ts.it_interval.tv_sec = NSFW_TIMER_CYCLE; + ts.it_interval.tv_nsec = 0; + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = NSFW_TIMER_CYCLE; + + if (timerfd_settime (tfd, 0, &ts, NULL) < 0) + { + NSFW_LOGERR ("timerfd_settime failed] errno=%d", errno); + close (tfd); + return -1; + } + + return tfd; +} + +/***************************************************************************** +* Prototype : nsfw_timer_notify_fun +* Description : receive timer event from kernel +* Input : i32 epfd +* i32 fd +* u32 events +* Output : None +* Return Value : int +* Calls : +* Called By : +*****************************************************************************/ +int +nsfw_timer_notify_fun (i32 epfd, i32 fd, u32 events) +{ + i32 rc; + + if ((events & EPOLLERR) || (events & EPOLLHUP) || (!(events & EPOLLIN))) + { + (void) nsfw_base_close (fd); + NSFW_LOGWAR ("timer disconnect!]epfd=%d,timer=%d,event=0x%x", epfd, + fd, events); + + (void) nsfw_mgr_unreg_sock_fun (fd); + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd faied!]epfd=%d,timer_fd=%d,event=0x%x", + epfd, fd, events); + return FALSE; + } + + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; + } + + u64 data; + while (1) + { + rc = nsfw_base_read (fd, &data, sizeof (data)); + if (rc == 0) + { + NSFW_LOGERR ("timer_fd recv 0]timer_fd=%d,errno=%d", fd, errno); + break; + } + else if (rc == -1) + { + if (errno == EINTR || errno == EAGAIN) + { + break; + } + NSMON_LOGERR ("timer_fd recv]timer_fd=%d,errno=%d", fd, errno); + break; + } + + nsfw_timer_exp (data); + } + + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_start +* Description : reg the timer module to epoll thread +* Input : None +* Output : None +* Return Value : u8 +* Calls : +* Called By : +* +*****************************************************************************/ +u8 +nsfw_timer_start () +{ + i32 timer_fd = nsfw_get_timer_socket (); + if (timer_fd < 0) + { + NSFW_LOGERR ("get timer_fd failed!"); + return FALSE; + } + + NSFW_LOGINF ("start timer_fd module!]timer_fd=%d", timer_fd); + (void) nsfw_mgr_reg_sock_fun (timer_fd, nsfw_timer_notify_fun); + return TRUE; +} + +/***************************************************************************** +* Prototype : nsfw_timer_module_init +* Description : module init +* Input : void* param +* Output : None +* Return Value : int +* Calls : +* Called By : +* +*****************************************************************************/ +int +nsfw_timer_module_init (void *param) +{ + u32 proc_type = (u32) ((long long) param); + nsfw_timer_init_cfg *timer_cfg = &g_timer_cfg; + NSFW_LOGINF ("ps module init]type=%u", proc_type); + switch (proc_type) + { + case NSFW_PROC_MASTER: + case NSFW_PROC_MAIN: + (void) NSFW_REG_SOFT_INT (NSFW_DBG_MODE_PARAM, g_hbt_switch, 0, 1); + break; + case NSFW_PROC_TOOLS: + case NSFW_PROC_CTRL: + break; + default: + return 0; + } + + timer_cfg->timer_info_size = NSFW_TIMER_INFO_MAX_COUNT_DEF; + + nsfw_mem_sppool pmpinfo; + pmpinfo.enmptype = NSFW_MRING_MPMC; + pmpinfo.usnum = timer_cfg->timer_info_size; + pmpinfo.useltsize = sizeof (nsfw_timer_info); + pmpinfo.isocket_id = NSFW_SOCKET_ANY; + pmpinfo.stname.entype = NSFW_NSHMEM; + if (-1 == + SPRINTF_S (pmpinfo.stname.aname, NSFW_MEM_NAME_LENTH, "%s", + "MS_TM_INFOPOOL")) + { + NSFW_LOGERR ("SPRINTF_S failed"); + return -1; + } + timer_cfg->timer_info_pool = nsfw_mem_sp_create (&pmpinfo); + + if (!timer_cfg->timer_info_pool) + { + NSFW_LOGERR ("alloc timer info pool_err"); + return -1; + } + + MEM_STAT (NSFW_TIMER_MODULE, pmpinfo.stname.aname, NSFW_NSHMEM, + nsfw_mem_get_len (timer_cfg->timer_info_pool, NSFW_MEM_SPOOL)); + + INIT_LIST_HEAD (&(timer_cfg->timer_head)); + INIT_LIST_HEAD (&(timer_cfg->exp_timer_head)); + + (void) nsfw_timer_start (); + return 0; +} + +/* *INDENT-OFF* */ +NSFW_MODULE_NAME (NSFW_TIMER_MODULE) +NSFW_MODULE_PRIORITY (10) +NSFW_MODULE_DEPENDS (NSFW_MGR_COM_MODULE) +NSFW_MODULE_INIT (nsfw_timer_module_init) +/* *INDENT-ON* */ + +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif /* __cplusplus */ |