feat: timer_create支持以SIGEV_THREAD方式创建定时器
【背景】当前timer_create接口不支持以SIGEV_THREAD的方式创建多个定时器 【修改方案】 1、内核timer_create接口在创建software timers相应的线程时,使用线程 taskCB所携带的信息识别各个线程的信号并依据该信息分别派发出信号。 2、关于用户任务操作许可验证的修改,现在允许同一用户线程向其自身派发信 号,软件定时器计时结束,向用户态发送相应的信号,完成用户态线程的回调。 【影响】 对现有的产品暂无影响。 re #I3SRFI Signed-off-by: yansira <yansira@hotmail.com> Change-Id: Ia23f5ef01975bf867dd7f5db797a30c264c50501
This commit is contained in:
@@ -42,6 +42,13 @@ extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
struct ksigevent {
|
||||
union sigval sigev_value;
|
||||
int sigev_signo;
|
||||
int sigev_notify;
|
||||
int sigev_tid;
|
||||
};
|
||||
|
||||
/* internal functions */
|
||||
STATIC INLINE BOOL ValidTimeSpec(const struct timespec *tp)
|
||||
{
|
||||
@@ -78,6 +85,8 @@ STATIC INLINE VOID OsTick2TimeSpec(struct timespec *tp, UINT32 tick)
|
||||
tp->tv_nsec = (long)(ns % OS_SYS_NS_PER_SECOND);
|
||||
}
|
||||
|
||||
int OsTimerCreate(clockid_t, struct ksigevent *__restrict, timer_t *__restrict);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
||||
@@ -693,45 +693,60 @@ int clock_nanosleep(clockid_t clk, int flags, const struct timespec *req, struct
|
||||
|
||||
typedef struct {
|
||||
int sigev_signo;
|
||||
UINT32 pid;
|
||||
pid_t pid;
|
||||
unsigned int tid;
|
||||
union sigval sigev_value;
|
||||
} swtmr_proc_arg;
|
||||
|
||||
static VOID SwtmrProc(UINTPTR tmrArg)
|
||||
{
|
||||
unsigned int intSave;
|
||||
int sig;
|
||||
INT32 sig, ret;
|
||||
UINT32 intSave;
|
||||
pid_t pid;
|
||||
siginfo_t info;
|
||||
swtmr_proc_arg *arg = (swtmr_proc_arg *)tmrArg;
|
||||
if (arg == NULL) {
|
||||
return;
|
||||
}
|
||||
LosTaskCB *stcb = NULL;
|
||||
|
||||
sig = arg->sigev_signo + 1;
|
||||
swtmr_proc_arg *arg = (swtmr_proc_arg *)tmrArg;
|
||||
OS_GOTO_EXIT_IF(arg == NULL, EINVAL);
|
||||
|
||||
sig = arg->sigev_signo;
|
||||
pid = arg->pid;
|
||||
/* Make sure that the para is valid */
|
||||
if (!GOOD_SIGNO(sig) || pid <= 0) {
|
||||
return;
|
||||
}
|
||||
if (OS_PID_CHECK_INVALID(pid)) {
|
||||
return;
|
||||
}
|
||||
OS_GOTO_EXIT_IF(!GOOD_SIGNO(sig), EINVAL);
|
||||
|
||||
/* Create the siginfo structure */
|
||||
info.si_signo = sig;
|
||||
info.si_code = SI_TIMER;
|
||||
info.si_value.sival_ptr = arg->sigev_value.sival_ptr;
|
||||
|
||||
/* Send the signal */
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
/* Send signals to threads or processes */
|
||||
if (arg->tid > 0) {
|
||||
/* Make sure that the para is valid */
|
||||
OS_GOTO_EXIT_IF(OS_TID_CHECK_INVALID(arg->tid), EINVAL);
|
||||
stcb = OsGetTaskCB(arg->tid);
|
||||
ret = OsUserProcessOperatePermissionsCheck(stcb, stcb->processID);
|
||||
OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
|
||||
|
||||
/* Dispatch the signal to thread, bypassing normal task group thread
|
||||
* dispatch rules. */
|
||||
SCHEDULER_LOCK(intSave);
|
||||
ret = OsTcbDispatch(stcb, &info);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
OS_GOTO_EXIT_IF(ret != LOS_OK, -ret);
|
||||
} else {
|
||||
/* Make sure that the para is valid */
|
||||
OS_GOTO_EXIT_IF(pid <= 0 || OS_PID_CHECK_INVALID(pid), EINVAL);
|
||||
/* Dispatch the signal to process */
|
||||
SCHEDULER_LOCK(intSave);
|
||||
OsDispatch(pid, &info, OS_USER_KILL_PERMISSION);
|
||||
SCHEDULER_UNLOCK(intSave);
|
||||
}
|
||||
return;
|
||||
EXIT:
|
||||
PRINT_ERR("Dsipatch signals failed!, ret: %d\r\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
int timer_create(clockid_t clockID, struct sigevent *evp, timer_t *timerID)
|
||||
int OsTimerCreate(clockid_t clockID, struct ksigevent *evp, timer_t *timerID)
|
||||
{
|
||||
UINT32 ret;
|
||||
UINT16 swtmrID;
|
||||
@@ -761,7 +776,9 @@ int timer_create(clockid_t clockID, struct sigevent *evp, timer_t *timerID)
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
arg->sigev_signo = signo - 1;
|
||||
|
||||
arg->tid = evp ? evp->sigev_tid : 0;
|
||||
arg->sigev_signo = signo;
|
||||
arg->pid = LOS_GetCurrProcessID();
|
||||
arg->sigev_value.sival_ptr = evp ? evp->sigev_value.sival_ptr : NULL;
|
||||
ret = LOS_SwtmrCreate(1, LOS_SWTMR_MODE_ONCE, SwtmrProc, &swtmrID, (UINTPTR)arg);
|
||||
@@ -1016,14 +1033,14 @@ int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue
|
||||
|
||||
/* To avoid creating an invalid timer after the timer has already been create */
|
||||
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
|
||||
ret = timer_create(CLOCK_REALTIME, NULL, &timerID);
|
||||
ret = OsTimerCreate(CLOCK_REALTIME, NULL, &timerID);
|
||||
if (ret != LOS_OK) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* The initialization of this global timer must be in spinlock
|
||||
* timer_create cannot be located in spinlock.
|
||||
* OsTimerCreate cannot be located in spinlock.
|
||||
*/
|
||||
SCHEDULER_LOCK(intSave);
|
||||
if (processCB->timerID == (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID) {
|
||||
|
||||
Reference in New Issue
Block a user