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:
Kiita
2021-06-03 20:38:03 +08:00
parent e93c52c091
commit e5f6bf0556
11 changed files with 239 additions and 44 deletions

View File

@@ -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
}

View File

@@ -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) {