703 lines
19 KiB
C
Executable File
703 lines
19 KiB
C
Executable File
/*-----------------------------------------------------------------------------*/
|
|
/* Include Header Files */
|
|
/*-----------------------------------------------------------------------------*/
|
|
#include <linux/init.h>
|
|
#include <linux/module.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/mmzone.h>
|
|
#include <linux/memory.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/uaccess.h>
|
|
|
|
#include <kwrap/dev.h>
|
|
#include <kwrap/flag.h>
|
|
#include <kwrap/task.h>
|
|
#include <kwrap/spinlock.h>
|
|
#include <kwrap/util.h>
|
|
#include "vos_ioctl.h"
|
|
|
|
#define __MODULE__ rtos_flag
|
|
#define __DBGLVL__ 8 // 0=FATAL, 1=ERR, 2=WRN, 3=UNIT, 4=FUNC, 5=IND, 6=MSG, 7=VALUE, 8=USER
|
|
#define __DBGFLT__ "*"
|
|
#include <kwrap/debug.h>
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Types Declarations */
|
|
/*-----------------------------------------------------------------------------*/
|
|
#define RTOS_FLAG_INITED_TAG MAKEFOURCC('R', 'F', 'L', 'G') ///< a key value
|
|
#define WAIT_TASK_NUM_MAX 3
|
|
|
|
#define VOS_STRCPY(dst, src, dst_size) do { \
|
|
strncpy(dst, src, (dst_size)-1); \
|
|
dst[(dst_size)-1] = '\0'; \
|
|
} while(0)
|
|
|
|
#define loc_cpu(flags) vk_spin_lock_irqsave(&my_lock, flags)
|
|
#define unl_cpu(flags) vk_spin_unlock_irqrestore(&my_lock, flags)
|
|
|
|
#if defined(__LINUX)
|
|
#define my_alloc vmalloc
|
|
#define my_free vfree
|
|
#define cur_task_name current->comm
|
|
#define my_jiffies jiffies_64
|
|
#define my_jiff_to_ms(j) ((j) * (1000 / HZ))
|
|
|
|
#elif defined(__FREERTOS)
|
|
#define my_alloc malloc
|
|
#define my_free free
|
|
#define current xTaskGetCurrentTaskHandle()
|
|
#define cur_task_name pcTaskGetName(xTaskGetCurrentTaskHandle())
|
|
#define my_jiffies hwclock_get_longcounter()
|
|
#define my_jiff_to_ms(j) ((j) / 1000)
|
|
|
|
#ifndef unlikely
|
|
#define unlikely(x) (x)
|
|
#endif
|
|
|
|
#else
|
|
#error Not supported OS
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Types Declarations */
|
|
/*-----------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
FLGPTN waiptn;
|
|
UINT wfmode;
|
|
struct task_struct *task_hdl;
|
|
UINT64 wait_time_jiffies;
|
|
} FLAG_WAIT_TSK_INFO;
|
|
|
|
typedef struct {
|
|
T_CFLG st_flags_attr;
|
|
wait_queue_head_t st_waitq;
|
|
unsigned long st_bits;
|
|
int st_used;
|
|
CHAR name[VOS_FLAG_NAME_SIZE];
|
|
FLAG_WAIT_TSK_INFO waitsk_list[WAIT_TASK_NUM_MAX];
|
|
int waitsk_count;
|
|
} FLAG_CELL_T;
|
|
|
|
typedef struct {
|
|
FLAG_CELL_T *p_flags;
|
|
} FLAG_CTRL_T;
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Extern Global Variables */
|
|
/*-----------------------------------------------------------------------------*/
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Extern Function Prototype */
|
|
/*-----------------------------------------------------------------------------*/
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Function Protype */
|
|
/*-----------------------------------------------------------------------------*/
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Local Global Variables */
|
|
/*-----------------------------------------------------------------------------*/
|
|
unsigned int rtos_flag_debug_level = NVT_DBG_WRN;
|
|
|
|
module_param_named(rtos_flag_debug_level, rtos_flag_debug_level, int, S_IRUGO | S_IWUSR);
|
|
MODULE_PARM_DESC(rtos_flag_debug_level, "Debug message level");
|
|
|
|
static VK_DEFINE_SPINLOCK(my_lock);
|
|
|
|
static int gflgnum;
|
|
static int g_curflg_id = 1;
|
|
static FLAG_CTRL_T g_st_flag_ctrl = {0};
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Interface Functions */
|
|
/*-----------------------------------------------------------------------------*/
|
|
void rtos_flag_add_waitlist_p(FLAG_CELL_T *p_flags, struct task_struct *task_hdl, FLGPTN waiptn, UINT wfmode)
|
|
{
|
|
int i;
|
|
FLAG_WAIT_TSK_INFO *p_waitsk;
|
|
|
|
p_waitsk = p_flags->waitsk_list;
|
|
for (i = 0; i < WAIT_TASK_NUM_MAX; i++) {
|
|
if (0 == p_waitsk->task_hdl) {
|
|
p_waitsk->task_hdl = task_hdl;
|
|
p_waitsk->waiptn = waiptn;
|
|
p_waitsk->wfmode = wfmode;
|
|
p_waitsk->wait_time_jiffies = my_jiffies;
|
|
p_flags->waitsk_count++;
|
|
return;
|
|
}
|
|
p_waitsk++;
|
|
}
|
|
}
|
|
|
|
void rtos_flag_del_waitlist_p(FLAG_CELL_T *p_flags, struct task_struct *task_hdl)
|
|
{
|
|
int i;
|
|
FLAG_WAIT_TSK_INFO *p_waitsk;
|
|
|
|
p_waitsk = p_flags->waitsk_list;
|
|
for (i = 0; i < WAIT_TASK_NUM_MAX; i++) {
|
|
if (task_hdl == p_waitsk->task_hdl) {
|
|
p_waitsk->task_hdl = 0;
|
|
p_flags->waitsk_count--;
|
|
return;
|
|
}
|
|
p_waitsk++;
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Export Functions */
|
|
/*-----------------------------------------------------------------------------*/
|
|
/**
|
|
rtos_flag_init
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
void rtos_flag_init(unsigned long max_flag_num)
|
|
{
|
|
DBG_FUNC_BEGIN("\r\n");
|
|
DBG_IND("max_flag_num =%ld\r\n", max_flag_num);
|
|
|
|
// initialize value
|
|
gflgnum = max_flag_num;
|
|
g_curflg_id = 1;
|
|
|
|
g_st_flag_ctrl.p_flags = (FLAG_CELL_T *)my_alloc(sizeof(FLAG_CELL_T) * gflgnum);
|
|
if (g_st_flag_ctrl.p_flags == NULL) {
|
|
DBG_ERR(" alloc!\n");
|
|
goto END_INIT;
|
|
}
|
|
|
|
DBG_IND("pflags =0x%lx\r\n", (ULONG)g_st_flag_ctrl.p_flags);
|
|
memset(g_st_flag_ctrl.p_flags, 0x00, sizeof(FLAG_CELL_T) * gflgnum);
|
|
|
|
//spin_lock_init(&g_st_flag_ctrl.st_flag_lock);
|
|
|
|
END_INIT:
|
|
DBG_FUNC_END("\r\n");
|
|
return;
|
|
}
|
|
|
|
/**
|
|
rtos_exit_flag
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
void rtos_flag_exit(void)
|
|
{
|
|
my_free(g_st_flag_ctrl.p_flags);
|
|
g_st_flag_ctrl.p_flags = NULL;
|
|
}
|
|
|
|
ER vos_flag_get_free_id(ID *p_flgid)
|
|
{
|
|
FLAG_CELL_T *p_flagcell;
|
|
int tmpid, i;
|
|
unsigned long flags = 0;
|
|
|
|
loc_cpu(flags);
|
|
if (unlikely(g_curflg_id >= gflgnum)) {
|
|
g_curflg_id = 1;
|
|
}
|
|
tmpid = g_curflg_id;
|
|
for (i = 0; i < gflgnum; i++) {
|
|
if (unlikely(tmpid >= gflgnum)) {
|
|
tmpid = 1;
|
|
}
|
|
p_flagcell = g_st_flag_ctrl.p_flags + tmpid;
|
|
if (0 == p_flagcell->st_used) {
|
|
p_flagcell->st_used = RTOS_FLAG_INITED_TAG;
|
|
g_curflg_id = tmpid;
|
|
*p_flgid = g_curflg_id;
|
|
g_curflg_id++;
|
|
unl_cpu(flags);
|
|
DBG_IND("g_curflg_id=%d\r\n", tmpid);
|
|
return E_OK;
|
|
}
|
|
tmpid++;
|
|
}
|
|
*p_flgid = 0;
|
|
unl_cpu(flags);
|
|
DBG_ERR("exceed max flag num %d\r\n", gflgnum);
|
|
return E_ID;
|
|
}
|
|
/**
|
|
cre_flg
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
ER vos_flag_create(ID *p_flgid, T_CFLG *pk_cflg, char *name)
|
|
{
|
|
ID flgid_new;
|
|
ER st_reslut = E_OK;
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(NULL == p_flgid)) {
|
|
DBG_ERR("p_flgid is NULL\n");
|
|
return E_PAR;
|
|
}
|
|
|
|
if (unlikely(E_OK != vos_flag_get_free_id(&flgid_new))) {
|
|
DBG_ERR("flag out of id\r\n");
|
|
return E_ID;
|
|
}
|
|
|
|
if (unlikely(flgid_new == 0 || flgid_new >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid_new %d\r\n", flgid_new);
|
|
return E_ID;
|
|
}
|
|
DBG_IND("flgid_new=%d\r\n", flgid_new);
|
|
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid_new;
|
|
DBG_IND("p_flagcell=0x%lx\r\n", (ULONG)p_flagcell);
|
|
|
|
init_waitqueue_head(&p_flagcell->st_waitq);
|
|
VOS_STRCPY(p_flagcell->name, name, sizeof(p_flagcell->name));
|
|
|
|
//setup the initial value if specified
|
|
if (pk_cflg) {
|
|
memcpy(&p_flagcell->st_flags_attr, pk_cflg, sizeof(T_CFLG));
|
|
p_flagcell->st_bits |= (unsigned long)p_flagcell->st_flags_attr.iflgptn;
|
|
}
|
|
|
|
//restore the valid flag id
|
|
*p_flgid = flgid_new;
|
|
|
|
return st_reslut;
|
|
}
|
|
|
|
ER vos_flag_destroy(ID flgid)
|
|
{
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d, task [%s]\r\n", flgid, cur_task_name);
|
|
return E_ID;
|
|
}
|
|
DBG_IND("flgid=%d\r\n", flgid);
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
memset(p_flagcell, 0x00, sizeof(FLAG_CELL_T));
|
|
return E_OK;
|
|
}
|
|
|
|
/**
|
|
set_flg
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
ER vos_flag_set(ID flgid, FLGPTN setptn)
|
|
{
|
|
unsigned long flags = 0;
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d, task [%s]\r\n", flgid, cur_task_name);
|
|
return E_ID;
|
|
}
|
|
DBG_IND("flgid=%d, setptn=0x%x\r\n", flgid, setptn);
|
|
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
DBG_IND("p_flagcell=0x%lx\r\n", (ULONG)p_flagcell);
|
|
|
|
loc_cpu(flags);
|
|
p_flagcell->st_bits |= (unsigned long)setptn;
|
|
//wake_up_interruptible(&p_flagcell->st_waitq);
|
|
wake_up(&p_flagcell->st_waitq);
|
|
unl_cpu(flags);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
/**
|
|
clr_flg
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
ER vos_flag_clr(ID flgid, FLGPTN clrptn)
|
|
{
|
|
unsigned long flags = 0;
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d, task [%s]\r\n", flgid, cur_task_name);
|
|
return E_ID;
|
|
}
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
|
|
loc_cpu(flags);
|
|
p_flagcell->st_bits &= ~clrptn;
|
|
unl_cpu(flags);
|
|
|
|
return E_OK;
|
|
}
|
|
|
|
int _vos_flag_wait(PFLGPTN p_flgptn, ID flgid, FLGPTN waiptn, UINT wfmode, int timeout_tick, int interruptible)
|
|
{
|
|
int api_ret = 0;
|
|
int wait_ret = 0;
|
|
FLAG_CELL_T *p_flagcell;
|
|
unsigned long flags = 0;
|
|
unsigned int keep = 0;
|
|
FLGPTN flgwai;
|
|
|
|
DBG_IND("flgid=%d\r\n", flgid);
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d, task [%s]\r\n", flgid, cur_task_name);
|
|
return E_ID;
|
|
}
|
|
if (unlikely(waiptn == 0)) {
|
|
return E_PAR;
|
|
}
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
|
|
//printk("wai_flg b flgid = %d, waiptn = 0x%x, \r\n",flgid,waiptn);
|
|
loc_cpu(flags);
|
|
rtos_flag_add_waitlist_p(p_flagcell, current, waiptn, wfmode);
|
|
vos_task_update_info(VOS_RES_TYPE_FLAG, current, flgid, waiptn, wfmode);
|
|
unl_cpu(flags);
|
|
|
|
do {
|
|
if (interruptible) {
|
|
/*
|
|
* Ref to include/linux/wait.h
|
|
* wait_event_interruptible - sleep until a condition gets true
|
|
* The function will return -ERESTARTSYS if it was interrupted by a
|
|
* signal and 0 if @condition evaluated to true.
|
|
*/
|
|
if (wfmode & TWF_ORW) {
|
|
wait_ret = wait_event_interruptible(p_flagcell->st_waitq, p_flagcell->st_bits & waiptn);
|
|
} else {
|
|
wait_ret = wait_event_interruptible(p_flagcell->st_waitq, (p_flagcell->st_bits & waiptn) == waiptn);
|
|
}
|
|
if (0 == wait_ret) {
|
|
wait_ret = 1; //set to 1 to represent the condition is met
|
|
}
|
|
} else if (-1 == timeout_tick) {
|
|
if (wfmode & TWF_ORW) {
|
|
wait_event(p_flagcell->st_waitq, p_flagcell->st_bits & waiptn);
|
|
} else {
|
|
wait_event(p_flagcell->st_waitq, (p_flagcell->st_bits & waiptn) == waiptn);
|
|
}
|
|
wait_ret = 1; //set to 1 to represent the condition is met
|
|
} else {
|
|
/*
|
|
* Ref to include/linux/wait.h
|
|
* wait_event_timeout
|
|
* Returns:
|
|
* 0 if the @condition evaluated to %false after the @timeout elapsed,
|
|
* 1 if the @condition evaluated to %true after the @timeout elapsed,
|
|
* or the remaining jiffies (at least 1) if the @condition evaluated
|
|
* to %true before the @timeout elapsed.
|
|
*/
|
|
if (wfmode & TWF_ORW) {
|
|
wait_ret = wait_event_timeout(p_flagcell->st_waitq, p_flagcell->st_bits & waiptn, timeout_tick);
|
|
} else {
|
|
wait_ret = wait_event_timeout(p_flagcell->st_waitq, (p_flagcell->st_bits & waiptn) == waiptn, timeout_tick);
|
|
}
|
|
}
|
|
|
|
keep = 0;
|
|
loc_cpu(flags);
|
|
|
|
if (wait_ret > 0) {
|
|
flgwai = p_flagcell->st_bits & waiptn;
|
|
// if the flag has been set, return
|
|
if ((wfmode & TWF_ORW) ? flgwai != 0 : (flgwai == waiptn)) {
|
|
if (wfmode & TWF_CLR) {
|
|
p_flagcell->st_bits &= ~waiptn;
|
|
}
|
|
*p_flgptn = flgwai;
|
|
api_ret = 0;
|
|
} else {
|
|
keep = 1;
|
|
}
|
|
} else if (-ERESTARTSYS == wait_ret){
|
|
api_ret = E_RLWAI;
|
|
} else {
|
|
api_ret = E_TMOUT;
|
|
}
|
|
unl_cpu(flags);
|
|
|
|
} while (keep);
|
|
|
|
loc_cpu(flags);
|
|
rtos_flag_del_waitlist_p(p_flagcell, current);
|
|
vos_task_update_info(VOS_RES_TYPE_INVALID, current, 0, 0, 0);
|
|
unl_cpu(flags);
|
|
|
|
return api_ret;
|
|
}
|
|
|
|
ER vos_flag_wait(PFLGPTN p_flgptn, ID flgid, FLGPTN waiptn, UINT wfmode)
|
|
{
|
|
return _vos_flag_wait(p_flgptn, flgid, waiptn, wfmode, -1, 0);
|
|
}
|
|
|
|
ER vos_flag_wait_timeout(PFLGPTN p_flgptn, ID flgid, FLGPTN waiptn, UINT wfmode, int timeout_tick)
|
|
{
|
|
return _vos_flag_wait(p_flgptn, flgid, waiptn, wfmode, timeout_tick, 0);
|
|
}
|
|
|
|
ER vos_flag_wait_interruptible(PFLGPTN p_flgptn, ID flgid, FLGPTN waiptn, UINT wfmode)
|
|
{
|
|
return _vos_flag_wait(p_flgptn, flgid, waiptn, wfmode, -1, 1);
|
|
}
|
|
|
|
/**
|
|
kchk_flg
|
|
* @remarks
|
|
* @param none
|
|
* @code
|
|
|
|
* @endcode
|
|
* @return
|
|
* @see
|
|
*/
|
|
FLGPTN vos_flag_chk(ID flgid, FLGPTN chkptn)
|
|
{
|
|
FLGPTN flg_status;
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d, task [%s]\r\n", flgid, cur_task_name);
|
|
return 0;
|
|
}
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
|
|
flg_status = p_flagcell->st_bits & chkptn;
|
|
return flg_status;
|
|
}
|
|
|
|
char *vos_flag_get_name(ID flgid)
|
|
{
|
|
FLAG_CELL_T *p_flagcell;
|
|
|
|
if (unlikely(flgid == 0 || flgid >= gflgnum)) {
|
|
DBG_ERR("Invalid flgid %d\r\n", flgid);
|
|
return NULL;
|
|
}
|
|
p_flagcell = g_st_flag_ctrl.p_flags + flgid;
|
|
return p_flagcell->name;
|
|
}
|
|
|
|
#if defined __UITRON || defined __ECOS
|
|
void vos_flag_dump(void (*dump)(char *fmt, ...))
|
|
#else
|
|
void vos_flag_dump(int (*dump)(const char *fmt, ...))
|
|
#endif
|
|
{
|
|
int i, tsk_i, curlen, task_id, flag_cnt = 0;
|
|
FLAG_CELL_T *p_flagcell;
|
|
FLAG_WAIT_TSK_INFO *p_waitsk;
|
|
char buf[30];
|
|
char *p_curr;
|
|
UINT64 sleep_time_ms;
|
|
char task_name[TASK_COMM_LEN];
|
|
|
|
if (NULL == dump) {
|
|
dump = vk_printk;
|
|
}
|
|
|
|
dump("\r\n-------------------------FLAG -------------------------------------------------------\r\n");
|
|
p_flagcell = g_st_flag_ctrl.p_flags;
|
|
for (i = 0; i < gflgnum; i++) {
|
|
if (RTOS_FLAG_INITED_TAG == p_flagcell->st_used) {
|
|
flag_cnt++;
|
|
dump("Flag[%.3d, %32s] -> Flags: 0x%.8lX\r\n", i, p_flagcell->name, p_flagcell->st_bits);
|
|
if (p_flagcell->waitsk_count > 0) {
|
|
dump("Waiting Task Queue : \r\n");
|
|
p_waitsk = p_flagcell->waitsk_list;
|
|
for (tsk_i = 0; tsk_i < WAIT_TASK_NUM_MAX; tsk_i++, p_waitsk++) {
|
|
if (FALSE == vos_task_chk_hdl_valid(p_waitsk->task_hdl))
|
|
continue;
|
|
p_curr = (char *)&buf[0];
|
|
if (p_waitsk->wfmode & TWF_ORW) {
|
|
snprintf(p_curr, sizeof(buf), "%s", "OR ");
|
|
} else {
|
|
snprintf(p_curr, sizeof(buf), "%s", "AND ");
|
|
}
|
|
curlen = strlen(p_curr);
|
|
p_curr += curlen;
|
|
if (p_waitsk->wfmode & TWF_CLR) {
|
|
snprintf(p_curr, sizeof(buf)-curlen, "%s", "CLEAR ");
|
|
}
|
|
task_id = vos_task_hdl2id(p_waitsk->task_hdl);
|
|
sleep_time_ms = my_jiff_to_ms(my_jiffies - p_waitsk->wait_time_jiffies);
|
|
if (virt_addr_valid(&p_waitsk->task_hdl->comm[0])) {
|
|
VOS_STRCPY(task_name, p_waitsk->task_hdl->comm, sizeof(task_name));
|
|
} else {
|
|
VOS_STRCPY(task_name, "user_tsk", sizeof(task_name));
|
|
}
|
|
dump(" Task[%.3d, %s]\r\n Pattern: 0x%.8X, Mode = %s, sleep_time = %lld ms \r\n",
|
|
task_id, task_name, p_waitsk->waiptn, buf, sleep_time_ms);
|
|
if (task_id < 0) {
|
|
vos_task_dump_by_tskhdl(dump, p_waitsk->task_hdl);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
p_flagcell++;
|
|
}
|
|
dump("\r\n Max flag_cnt = %d , used = %d\r\n", gflgnum, flag_cnt);
|
|
}
|
|
|
|
int _IOFUNC_FLAG_IOCMD_CREATE(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
ID newid = 0;
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (E_OK != vos_flag_create(&newid, &ioarg.init_pattern, ioarg.name)) {
|
|
DBG_ERR("vos_sem_create fail\r\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ioarg.id = (unsigned long)newid;
|
|
if (copy_to_user((void *)arg, (void *)&ioarg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_to_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_FLAG_IOCMD_SET(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (E_OK != vos_flag_set((ID)ioarg.id, (FLGPTN)ioarg.bits)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_FLAG_IOCMD_CLR(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (E_OK != vos_flag_clr((ID)ioarg.id, (FLGPTN)ioarg.bits)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int _IOFUNC_FLAG_IOCMD_WAIT(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
FLGPTN st_flg_ptn = 0;
|
|
int tick = 0;
|
|
int ret;
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
tick = vos_util_msec_to_tick(ioarg.timeout_tick); //user-space tick is msec
|
|
|
|
ret = _vos_flag_wait(&st_flg_ptn, (ID)ioarg.id, (FLGPTN)ioarg.bits, (UINT)ioarg.mode, tick, ioarg.interruptible);
|
|
if (ret == E_RLWAI) {
|
|
//Note: return -ERESTARTSYS so that user-space can restart syscall or return EINTR if terminated
|
|
//And we should not destroy user arg by "copy_to_user"
|
|
return -ERESTARTSYS;
|
|
}
|
|
|
|
ioarg.bits = (unsigned long)st_flg_ptn;
|
|
if (copy_to_user((void *)arg, (void *)&ioarg, sizeof(VOS_FLAG_IOARG))) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int _IOFUNC_FLAG_IOCMD_CHK(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
ioarg.bits = vos_flag_chk((ID)ioarg.id, (FLGPTN)ioarg.bits);
|
|
if (copy_to_user((void *)arg, (void *)&ioarg, sizeof(VOS_FLAG_IOARG))) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _IOFUNC_FLAG_IOCMD_DESTROY(unsigned long arg)
|
|
{
|
|
VOS_FLAG_IOARG ioarg = {0};
|
|
|
|
if (copy_from_user((void *)&ioarg, (void *)arg, sizeof(VOS_FLAG_IOARG))) {
|
|
DBG_ERR("copy_from_user failed\n");
|
|
return -EFAULT;
|
|
}
|
|
|
|
if (E_OK != vos_flag_destroy((ID)ioarg.id)) {
|
|
return -EFAULT;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------*/
|
|
/* Kernel Mode Definiton */
|
|
/*-----------------------------------------------------------------------------*/
|
|
EXPORT_SYMBOL(vos_flag_create);
|
|
EXPORT_SYMBOL(vos_flag_destroy);
|
|
EXPORT_SYMBOL(vos_flag_set);
|
|
EXPORT_SYMBOL(vos_flag_clr);
|
|
EXPORT_SYMBOL(vos_flag_wait);
|
|
EXPORT_SYMBOL(vos_flag_wait_interruptible);
|
|
EXPORT_SYMBOL(vos_flag_wait_timeout);
|
|
EXPORT_SYMBOL(vos_flag_chk);
|
|
EXPORT_SYMBOL(vos_flag_get_name);
|
|
EXPORT_SYMBOL(vos_flag_dump);
|