/** @brief vos semaphore (virtual-os user-space) @file vos_user_semaphore.c @ingroup vos_user @note Nothing. Copyright Novatek Microelectronics Corp. 2019. All rights reserved. */ /*-----------------------------------------------------------------------------*/ /* Include Header Files */ /*-----------------------------------------------------------------------------*/ #define __MODULE__ vos_user_semaphore #define __DBGLVL__ 2 #include #include #include #include "vos_ioctl.h" #include #include #include #include #include #include #include /*-----------------------------------------------------------------------------*/ /* Local Types Declarations */ /*-----------------------------------------------------------------------------*/ #define VOS_STRCPY(dst, src, dst_size) do { \ strncpy(dst, src, (dst_size)-1); \ dst[(dst_size)-1] = '\0'; \ } while(0) /*-----------------------------------------------------------------------------*/ /* Local Constant Definitions */ /*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/ /* Extern Global Variables */ /*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/ /* Extern Function Prototype */ /*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/ /* Local Function Protype */ /*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/ /* Local Types Declarations */ /*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/ /* Local Global Variables */ /*-----------------------------------------------------------------------------*/ static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; static int g_ioctl_fd = -1; /*-----------------------------------------------------------------------------*/ /* Interface Functions */ /*-----------------------------------------------------------------------------*/ static int vos_sem_get_fd(void) { pthread_mutex_lock(&g_mutex); if (g_ioctl_fd < 0) { g_ioctl_fd = open("/dev/"VOS_IOCTL_DEV_NAME, O_RDWR); if (g_ioctl_fd < 0) { DBG_ERR("open %s failed", "/dev/"VOS_IOCTL_DEV_NAME); pthread_mutex_unlock(&g_mutex); return -1; } } pthread_mutex_unlock(&g_mutex); return g_ioctl_fd; } int vos_sem_create(ID *p_semid, int init_cnt, char *name) { VOS_SEM_IOARG ioarg = {0}; int fd; if (NULL == p_semid) { DBG_ERR("p_semid is NULL\r\n"); return -1; } if (NULL == name) { DBG_ERR("p_name is NULL\r\n"); return -1; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return -1; } ioarg.init_cnt = init_cnt; VOS_STRCPY(ioarg.name, name, sizeof(ioarg.name)); if (-1 == ioctl(fd, VOS_SEM_IOCMD_CREATE, &ioarg)) { DBG_ERR("ioctl fails, error = %d\r\n", errno); return -1; } *p_semid = (ID)ioarg.semid; return 0; } void vos_sem_destroy(ID semid) { VOS_SEM_IOARG ioarg = {0}; int fd; if (0 == semid) { DBG_ERR("Invalid semid %d\r\n", semid); return; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return; } ioarg.semid = semid; if (-1 == ioctl(fd, VOS_SEM_IOCMD_DESTROY, &ioarg)) { DBG_ERR("ioctl fails, error = %d\r\n", errno); return; } } void vos_sem_sig(ID semid) { VOS_SEM_IOARG ioarg = {0}; int fd; if (0 == semid) { DBG_ERR("Invalid semid %d\r\n", semid); return; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return; } ioarg.semid = semid; if (-1 == ioctl(fd, VOS_SEM_IOCMD_SIG, &ioarg)) { DBG_ERR("ioctl fails, error = %d\r\n", errno); return; } } //vos_sem_wait is identical to vos_sem_wait_interruptible, //because we don't want Ctrl+C fails to terminate a process int vos_sem_wait(ID semid) { VOS_SEM_IOARG ioarg = {0}; int fd; int ret_ioctl; if (0 == semid) { DBG_ERR("Invalid semid %d\r\n", semid); return -1; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return -1; } ioarg.semid = semid; ioarg.timeout_tick = -1; ioarg.interruptible = 1; //NOTE: for user-space, set interruptible by default ret_ioctl = ioctl(fd, VOS_SEM_IOCMD_WAIT, &ioarg); if (-1 == ret_ioctl) { if (errno == -E_RLWAI) { return E_RLWAI; //interrupted } else { DBG_ERR("ioctl fails, error = %d\r\n", errno); return -1; } } return 0; } int vos_sem_wait_timeout(ID semid, int timeout_tick) { VOS_SEM_IOARG ioarg = {0}; int fd; int ret_ioctl = 0; if (0 == semid) { DBG_ERR("Invalid semid %d\r\n", semid); return -1; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return -1; } ioarg.semid = semid; ioarg.timeout_tick = timeout_tick; //For Linux user-space, use timeout_tick as msec. ioarg.interruptible = 0; ret_ioctl = ioctl(fd, VOS_SEM_IOCMD_WAIT, &ioarg); if (-1 == ret_ioctl) { if (errno == -E_TMOUT) { return E_TMOUT; //timeout } else { DBG_ERR("ioctl fails, error = %d\r\n", errno); return -1; } } return 0; } int vos_sem_wait_interruptible(ID semid) { VOS_SEM_IOARG ioarg = {0}; int fd; int ret_ioctl; if (0 == semid) { DBG_ERR("Invalid semid %d\r\n", semid); return -1; } fd = vos_sem_get_fd(); if (fd < 0) { DBG_ERR("get fd failed\r\n"); return -1; } ioarg.semid = semid; ioarg.timeout_tick = -1; ioarg.interruptible = 1; ret_ioctl = ioctl(fd, VOS_SEM_IOCMD_WAIT, &ioarg); if (-1 == ret_ioctl) { if (errno == -E_RLWAI) { return E_RLWAI; //interrupted } else { DBG_ERR("ioctl fails, error = %d\r\n", errno); return -1; } } return 0; }