266 lines
6.4 KiB
C
Executable File
266 lines
6.4 KiB
C
Executable File
/**
|
|
@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 <kwrap/debug.h>
|
|
#include <kwrap/error_no.h>
|
|
#include <kwrap/semaphore.h>
|
|
#include "vos_ioctl.h"
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* 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;
|
|
}
|