[Kernel] add sigwait implementation
This commit is contained in:
parent
ef668bc3aa
commit
38b9ed3118
|
@ -31,37 +31,37 @@
|
||||||
|
|
||||||
void (*signal(int sig, void (*func)(int))) (int)
|
void (*signal(int sig, void (*func)(int))) (int)
|
||||||
{
|
{
|
||||||
return rt_signal_install(sig, func);
|
return rt_signal_install(sig, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
|
int sigprocmask (int how, const sigset_t *set, sigset_t *oset)
|
||||||
{
|
{
|
||||||
rt_base_t level;
|
rt_base_t level;
|
||||||
rt_thread_t tid;
|
rt_thread_t tid;
|
||||||
|
|
||||||
tid = rt_thread_self();
|
tid = rt_thread_self();
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
if (oset) *oset = tid->sig_mask;
|
if (oset) *oset = tid->sig_mask;
|
||||||
|
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
switch(how)
|
switch(how)
|
||||||
{
|
{
|
||||||
case SIG_BLOCK:
|
case SIG_BLOCK:
|
||||||
tid->sig_mask |= *set;
|
tid->sig_mask |= *set;
|
||||||
break;
|
break;
|
||||||
case SIG_UNBLOCK:
|
case SIG_UNBLOCK:
|
||||||
tid->sig_mask &= ~*set;
|
tid->sig_mask &= ~*set;
|
||||||
break;
|
break;
|
||||||
case SIG_SETMASK:
|
case SIG_SETMASK:
|
||||||
tid->sig_mask = *set;
|
tid->sig_mask = *set;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -70,18 +70,18 @@ int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
|
||||||
{
|
{
|
||||||
rt_sighandler_t old = RT_NULL;
|
rt_sighandler_t old = RT_NULL;
|
||||||
|
|
||||||
if (!sig_valid(signum)) return -RT_ERROR;
|
if (!sig_valid(signum)) return -RT_ERROR;
|
||||||
|
|
||||||
if (act)
|
if (act)
|
||||||
old = rt_signal_install(signum, act->sa_handler);
|
old = rt_signal_install(signum, act->sa_handler);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
old = rt_signal_install(signum, RT_NULL);
|
old = rt_signal_install(signum, RT_NULL);
|
||||||
rt_signal_install(signum, old);
|
rt_signal_install(signum, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oldact)
|
if (oldact)
|
||||||
oldact->sa_handler = old;
|
oldact->sa_handler = old;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,22 @@ int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
|
||||||
int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
int sigtimedwait(const sigset_t *set, siginfo_t *info,
|
||||||
const struct timespec *timeout)
|
const struct timespec *timeout)
|
||||||
{
|
{
|
||||||
return 0;
|
int ret = 0;
|
||||||
|
int tick = RT_WAITING_FOREVER;
|
||||||
|
|
||||||
|
#ifdef RT_USING_PTHREADS
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
extern int clock_time_to_tick(const struct timespec *time);
|
||||||
|
tick = clock_time_to_tick(timeout);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = rt_signal_wait(set, info, tick);
|
||||||
|
if (ret == 0) return 0;
|
||||||
|
|
||||||
|
errno = ret;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sigwait(const sigset_t *set, int *sig)
|
int sigwait(const sigset_t *set, int *sig)
|
||||||
|
@ -104,12 +119,12 @@ int sigwait(const sigset_t *set, int *sig)
|
||||||
|
|
||||||
int sigwaitinfo(const sigset_t *set, siginfo_t *info)
|
int sigwaitinfo(const sigset_t *set, siginfo_t *info)
|
||||||
{
|
{
|
||||||
return sigtimedwait(set, info, NULL);
|
return sigtimedwait(set, info, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int raise(int sig)
|
int raise(int sig)
|
||||||
{
|
{
|
||||||
rt_thread_kill(rt_thread_self(), sig);
|
rt_thread_kill(rt_thread_self(), sig);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <rtthread.h>
|
#include <rtthread.h>
|
||||||
|
#include <sys/signal.h>
|
||||||
|
|
||||||
enum rt_signal_value{
|
enum rt_signal_value{
|
||||||
SIG1 = SIGHUP,
|
SIG1 = SIGHUP,
|
||||||
|
@ -68,56 +69,6 @@ enum rt_signal_value{
|
||||||
SIGMAX = NSIG,
|
SIGMAX = NSIG,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
The structure definitions on newlib:
|
|
||||||
|
|
||||||
typedef void (*_sig_func_ptr)(int);
|
|
||||||
|
|
||||||
struct sigaction
|
|
||||||
{
|
|
||||||
_sig_func_ptr sa_handler;
|
|
||||||
sigset_t sa_mask;
|
|
||||||
int sa_flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef int sig_atomic_t;
|
|
||||||
|
|
||||||
typedef _sig_func_ptr sig_t;
|
|
||||||
typedef _sig_func_ptr sighandler_t;
|
|
||||||
|
|
||||||
When enable POSIX_REALTIME_SIGNALS/POSIX_THREADS:
|
|
||||||
|
|
||||||
union sigval {
|
|
||||||
int sival_int;
|
|
||||||
void *sival_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sigevent {
|
|
||||||
int sigev_notify;
|
|
||||||
int sigev_signo;
|
|
||||||
union sigval sigev_value;
|
|
||||||
|
|
||||||
void (*sigev_notify_function)( union sigval );
|
|
||||||
|
|
||||||
pthread_attr_t *sigev_notify_attributes;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int si_signo;
|
|
||||||
int si_code;
|
|
||||||
union sigval si_value;
|
|
||||||
} siginfo_t;
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler);
|
|
||||||
void rt_signal_mask(int signo);
|
|
||||||
void rt_signal_unmask(int signo);
|
|
||||||
int rt_thread_kill(rt_thread_t tid, int sig);
|
|
||||||
|
|
||||||
int rt_system_signal_init(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_SYS_SIGNALS
|
||||||
/* Signal Generation and Delivery, P1003.1b-1993, p. 63
|
/* Signal Generation and Delivery, P1003.1b-1993, p. 63
|
||||||
NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and
|
NOTE: P1003.1c/D10, p. 34 adds sigev_notify_function and
|
||||||
sigev_notify_attributes to the sigevent structure. */
|
sigev_notify_attributes to the sigevent structure. */
|
||||||
|
@ -59,14 +60,15 @@ struct siginfo
|
||||||
union sigval si_value;
|
union sigval si_value;
|
||||||
};
|
};
|
||||||
typedef struct siginfo siginfo_t;
|
typedef struct siginfo siginfo_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SI_USER 0x01 /* Signal sent by kill(). */
|
#define SI_USER 0x01 /* Signal sent by kill(). */
|
||||||
#define SI_QUEUE 0x02 /* Signal sent by sigqueue(). */
|
#define SI_QUEUE 0x02 /* Signal sent by sigqueue(). */
|
||||||
#define SI_TIMER 0x03 /* Signal generated by expiration of a
|
#define SI_TIMER 0x03 /* Signal generated by expiration of a
|
||||||
timer set by timer_settime(). */
|
timer set by timer_settime(). */
|
||||||
#define SI_ASYNCIO 0x04 /* Signal generated by completion of an
|
#define SI_ASYNCIO 0x04 /* Signal generated by completion of an
|
||||||
asynchronous I/O request. */
|
asynchronous I/O request. */
|
||||||
#define SI_MESGQ 0x05 /* Signal generated by arrival of a
|
#define SI_MESGQ 0x05 /* Signal generated by arrival of a
|
||||||
message on an empty message queue. */
|
message on an empty message queue. */
|
||||||
|
|
||||||
#ifdef RT_USING_NEWLIB
|
#ifdef RT_USING_NEWLIB
|
||||||
|
@ -107,17 +109,17 @@ typedef unsigned long sigset_t;
|
||||||
#define SIGRTMAX 31
|
#define SIGRTMAX 31
|
||||||
#define NSIG 32
|
#define NSIG 32
|
||||||
|
|
||||||
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
|
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
|
||||||
#define SIG_BLOCK 1 /* set of signals to block */
|
#define SIG_BLOCK 1 /* set of signals to block */
|
||||||
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */
|
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */
|
||||||
|
|
||||||
typedef void (*_sig_func_ptr)(int);
|
typedef void (*_sig_func_ptr)(int);
|
||||||
|
|
||||||
struct sigaction
|
struct sigaction
|
||||||
{
|
{
|
||||||
_sig_func_ptr sa_handler;
|
_sig_func_ptr sa_handler;
|
||||||
sigset_t sa_mask;
|
sigset_t sa_mask;
|
||||||
int sa_flags;
|
int sa_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
|
#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
|
||||||
|
@ -163,17 +165,17 @@ typedef unsigned long sigset_t;
|
||||||
#define SIGRTMAX 31
|
#define SIGRTMAX 31
|
||||||
#define NSIG 32
|
#define NSIG 32
|
||||||
|
|
||||||
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
|
#define SIG_SETMASK 0 /* set mask with sigprocmask() */
|
||||||
#define SIG_BLOCK 1 /* set of signals to block */
|
#define SIG_BLOCK 1 /* set of signals to block */
|
||||||
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */
|
#define SIG_UNBLOCK 2 /* set of signals to, well, unblock */
|
||||||
|
|
||||||
typedef void (*_sig_func_ptr)(int);
|
typedef void (*_sig_func_ptr)(int);
|
||||||
|
|
||||||
struct sigaction
|
struct sigaction
|
||||||
{
|
{
|
||||||
_sig_func_ptr sa_handler;
|
_sig_func_ptr sa_handler;
|
||||||
sigset_t sa_mask;
|
sigset_t sa_mask;
|
||||||
int sa_flags;
|
int sa_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
|
#define sigaddset(what,sig) (*(what) |= (1<<(sig)), 0)
|
||||||
|
|
|
@ -451,8 +451,10 @@ typedef struct rt_timer *rt_timer_t;
|
||||||
* @addtogroup Signal
|
* @addtogroup Signal
|
||||||
*/
|
*/
|
||||||
#ifdef RT_USING_SIGNALS
|
#ifdef RT_USING_SIGNALS
|
||||||
|
#include <libc/libc_signal.h>
|
||||||
typedef unsigned long rt_sigset_t;
|
typedef unsigned long rt_sigset_t;
|
||||||
typedef void (*rt_sighandler_t)(int signo);
|
typedef void (*rt_sighandler_t)(int signo);
|
||||||
|
typedef siginfo_t rt_siginfo_t;
|
||||||
|
|
||||||
#define RT_SIG_MAX 32
|
#define RT_SIG_MAX 32
|
||||||
#endif
|
#endif
|
||||||
|
@ -481,7 +483,7 @@ typedef void (*rt_sighandler_t)(int signo);
|
||||||
|
|
||||||
#define RT_THREAD_STAT_SIGNAL 0x10
|
#define RT_THREAD_STAT_SIGNAL 0x10
|
||||||
#define RT_THREAD_STAT_SIGNAL_READY (RT_THREAD_STAT_SIGNAL | RT_THREAD_READY)
|
#define RT_THREAD_STAT_SIGNAL_READY (RT_THREAD_STAT_SIGNAL | RT_THREAD_READY)
|
||||||
#define RT_THREAD_STAT_SIGNAL_SUSPEND 0x20
|
#define RT_THREAD_STAT_SIGNAL_WAIT 0x20
|
||||||
#define RT_THREAD_STAT_SIGNAL_MASK 0xf0
|
#define RT_THREAD_STAT_SIGNAL_MASK 0xf0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -204,6 +204,7 @@ void rt_scheduler_sethook(void (*hook)(rt_thread_t from, rt_thread_t to));
|
||||||
void rt_signal_mask(int signo);
|
void rt_signal_mask(int signo);
|
||||||
void rt_signal_unmask(int signo);
|
void rt_signal_unmask(int signo);
|
||||||
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler);
|
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler);
|
||||||
|
int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout);
|
||||||
|
|
||||||
int rt_system_signal_init(void);
|
int rt_system_signal_init(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -263,7 +263,7 @@ void rt_schedule(void)
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* enable interrupt */
|
/* enable interrupt */
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
@ -293,7 +293,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
|
||||||
temp = rt_hw_interrupt_disable();
|
temp = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
/* change stat */
|
/* change stat */
|
||||||
thread->stat = RT_THREAD_READY;
|
thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||||
|
|
||||||
/* insert thread to ready list */
|
/* insert thread to ready list */
|
||||||
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
|
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
|
||||||
|
|
176
src/signal.c
176
src/signal.c
|
@ -80,6 +80,16 @@ static void _signal_entry(void *parameter)
|
||||||
rt_hw_context_switch_to((rt_uint32_t) & (tid->sp));
|
rt_hw_context_switch_to((rt_uint32_t) & (tid->sp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To deliver a signal to thread, there are cases:
|
||||||
|
* 1. When thread is suspended, function resumes thread and
|
||||||
|
* set signal stat;
|
||||||
|
* 2. When thread is ready:
|
||||||
|
* - If function delivers a signal to self thread, just handle
|
||||||
|
* it.
|
||||||
|
* - If function delivers a signal to another ready thread, OS
|
||||||
|
* should build a slice context to handle it.
|
||||||
|
*/
|
||||||
static void _signal_deliver(rt_thread_t tid)
|
static void _signal_deliver(rt_thread_t tid)
|
||||||
{
|
{
|
||||||
rt_ubase_t level;
|
rt_ubase_t level;
|
||||||
|
@ -88,7 +98,7 @@ static void _signal_deliver(rt_thread_t tid)
|
||||||
if (!(tid->sig_pending & tid->sig_mask)) return;
|
if (!(tid->sig_pending & tid->sig_mask)) return;
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
if (tid->stat == RT_THREAD_SUSPEND)
|
if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
|
||||||
{
|
{
|
||||||
/* resume thread to handle signal */
|
/* resume thread to handle signal */
|
||||||
rt_thread_resume(tid);
|
rt_thread_resume(tid);
|
||||||
|
@ -106,14 +116,17 @@ static void _signal_deliver(rt_thread_t tid)
|
||||||
{
|
{
|
||||||
/* add signal state */
|
/* add signal state */
|
||||||
tid->stat |= RT_THREAD_STAT_SIGNAL;
|
tid->stat |= RT_THREAD_STAT_SIGNAL;
|
||||||
|
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
/* do signal action in self thread context */
|
/* do signal action in self thread context */
|
||||||
rt_thread_handle_sig(RT_TRUE);
|
rt_thread_handle_sig(RT_TRUE);
|
||||||
}
|
}
|
||||||
else if (!(tid->stat & RT_THREAD_STAT_SIGNAL))
|
else if (!((tid->stat & RT_THREAD_STAT_MASK) & RT_THREAD_STAT_SIGNAL))
|
||||||
{
|
{
|
||||||
|
/* add signal state */
|
||||||
tid->stat |= RT_THREAD_STAT_SIGNAL;
|
tid->stat |= RT_THREAD_STAT_SIGNAL;
|
||||||
|
|
||||||
/* point to the signal handle entry */
|
/* point to the signal handle entry */
|
||||||
tid->sig_ret = tid->sp;
|
tid->sig_ret = tid->sp;
|
||||||
tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
|
tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
|
||||||
|
@ -191,6 +204,105 @@ void rt_signal_unmask(int signo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int rt_signal_wait(const rt_sigset_t *set, rt_siginfo_t *si, rt_int32_t timeout)
|
||||||
|
{
|
||||||
|
int ret = RT_EOK;
|
||||||
|
rt_base_t level;
|
||||||
|
rt_thread_t tid = rt_thread_self();
|
||||||
|
struct siginfo_node *si_node = RT_NULL, *si_prev = RT_NULL;
|
||||||
|
|
||||||
|
/* current context checking */
|
||||||
|
RT_DEBUG_IN_THREAD_CONTEXT;
|
||||||
|
|
||||||
|
/* parameters check */
|
||||||
|
if (set == NULL || *set == 0 || si == NULL )
|
||||||
|
{
|
||||||
|
ret = -RT_EINVAL;
|
||||||
|
goto __done_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear siginfo to avoid unknown value */
|
||||||
|
memset(si, 0x0, sizeof(rt_siginfo_t));
|
||||||
|
|
||||||
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
|
/* already pending */
|
||||||
|
if (tid->sig_pending & *set) goto __done;
|
||||||
|
|
||||||
|
if (timeout == 0)
|
||||||
|
{
|
||||||
|
ret = -RT_ETIMEOUT;
|
||||||
|
goto __done_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* suspend self thread */
|
||||||
|
rt_thread_suspend(tid);
|
||||||
|
/* set thread stat as waiting for signal */
|
||||||
|
tid->stat |= RT_THREAD_STAT_SIGNAL_WAIT;
|
||||||
|
|
||||||
|
/* start timeout timer */
|
||||||
|
if (timeout != RT_WAITING_FOREVER)
|
||||||
|
{
|
||||||
|
/* reset the timeout of thread timer and start it */
|
||||||
|
rt_timer_control(&(tid->thread_timer),
|
||||||
|
RT_TIMER_CTRL_SET_TIME,
|
||||||
|
&timeout);
|
||||||
|
rt_timer_start(&(tid->thread_timer));
|
||||||
|
}
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
/* do thread scheduling */
|
||||||
|
rt_schedule();
|
||||||
|
|
||||||
|
level = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
|
/* remove signal waiting flag */
|
||||||
|
tid->stat &= ~RT_THREAD_STAT_SIGNAL_WAIT;
|
||||||
|
|
||||||
|
/* check errno of thread */
|
||||||
|
if (tid->error == -RT_ETIMEOUT)
|
||||||
|
{
|
||||||
|
tid->error = RT_EOK;
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
/* timer timeout */
|
||||||
|
ret = -RT_ETIMEOUT;
|
||||||
|
goto __done_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__done:
|
||||||
|
/* to get the first matched pending signals */
|
||||||
|
si_node = (struct siginfo_node *)tid->si_list;
|
||||||
|
while (si_node)
|
||||||
|
{
|
||||||
|
int signo;
|
||||||
|
|
||||||
|
signo = si_node->si.si_signo;
|
||||||
|
if (sig_mask(signo) & *set)
|
||||||
|
{
|
||||||
|
*si = si_node->si;
|
||||||
|
|
||||||
|
dbg_log(DBG_LOG, "sigwait: %d sig raised!\n", signo);
|
||||||
|
if (si_prev) si_prev->list.next = si_node->list.next;
|
||||||
|
else tid->si_list = si_node->list.next;
|
||||||
|
|
||||||
|
/* clear pending */
|
||||||
|
tid->sig_pending &= ~sig_mask(signo);
|
||||||
|
rt_mp_free(si_node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
si_prev = si_node;
|
||||||
|
si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
__done_int:
|
||||||
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
|
__done_return:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void rt_thread_handle_sig(rt_bool_t clean_state)
|
void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||||
{
|
{
|
||||||
rt_base_t level;
|
rt_base_t level;
|
||||||
|
@ -199,39 +311,46 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
|
||||||
struct siginfo_node *si_node;
|
struct siginfo_node *si_node;
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
while (tid->sig_pending & tid->sig_mask)
|
if (tid->sig_pending & tid->sig_mask)
|
||||||
{
|
{
|
||||||
int signo, error;
|
/* if thread is not waiting for signal */
|
||||||
rt_sighandler_t handler;
|
if (!(tid->stat & RT_THREAD_STAT_SIGNAL_WAIT))
|
||||||
|
{
|
||||||
|
while (tid->sig_pending & tid->sig_mask)
|
||||||
|
{
|
||||||
|
int signo, error;
|
||||||
|
rt_sighandler_t handler;
|
||||||
|
|
||||||
si_node = (struct siginfo_node *)tid->si_list;
|
si_node = (struct siginfo_node *)tid->si_list;
|
||||||
if (!si_node) break;
|
if (!si_node) break;
|
||||||
|
|
||||||
/* remove this sig info node from list */
|
/* remove this sig info node from list */
|
||||||
if (si_node->list.next == RT_NULL)
|
if (si_node->list.next == RT_NULL)
|
||||||
tid->si_list = RT_NULL;
|
tid->si_list = RT_NULL;
|
||||||
else
|
else
|
||||||
tid->si_list = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
|
tid->si_list = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
|
||||||
|
|
||||||
signo = si_node->si.si_signo;
|
signo = si_node->si.si_signo;
|
||||||
handler = tid->sig_vectors[signo];
|
handler = tid->sig_vectors[signo];
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
dbg_log(DBG_LOG, "handle signal: %d, handler 0x%08x\n", signo, handler);
|
dbg_log(DBG_LOG, "handle signal: %d, handler 0x%08x\n", signo, handler);
|
||||||
if (handler) handler(signo);
|
if (handler) handler(signo);
|
||||||
|
|
||||||
level = rt_hw_interrupt_disable();
|
level = rt_hw_interrupt_disable();
|
||||||
tid->sig_pending &= ~sig_mask(signo);
|
tid->sig_pending &= ~sig_mask(signo);
|
||||||
error = si_node->si.si_errno;
|
error = si_node->si.si_errno;
|
||||||
|
|
||||||
rt_mp_free(si_node); /* release this siginfo node */
|
rt_mp_free(si_node); /* release this siginfo node */
|
||||||
/* set errno in thread tcb */
|
/* set errno in thread tcb */
|
||||||
tid->error = error;
|
tid->error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* whether clean signal status */
|
||||||
|
if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* whether clean signal status */
|
|
||||||
if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
|
|
||||||
|
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +434,7 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||||
node = (struct rt_slist_node *)tid->si_list;
|
node = (struct rt_slist_node *)tid->si_list;
|
||||||
rt_hw_interrupt_enable(level);
|
rt_hw_interrupt_enable(level);
|
||||||
|
|
||||||
/* update sig infor */
|
/* update sig info */
|
||||||
rt_enter_critical();
|
rt_enter_critical();
|
||||||
for (; (node) != RT_NULL; node = node->next)
|
for (; (node) != RT_NULL; node = node->next)
|
||||||
{
|
{
|
||||||
|
@ -358,7 +477,7 @@ int rt_thread_kill(rt_thread_t tid, int sig)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dbg_log(DBG_ERROR, "The allocation of signal infor node failed.\n");
|
dbg_log(DBG_ERROR, "The allocation of signal info node failed.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* deliver signal to this thread */
|
/* deliver signal to this thread */
|
||||||
|
@ -380,4 +499,3 @@ int rt_system_signal_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -638,7 +638,7 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||||
|
|
||||||
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
|
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
|
||||||
{
|
{
|
||||||
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, %d\n",
|
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
|
||||||
thread->stat));
|
thread->stat));
|
||||||
|
|
||||||
return -RT_ERROR;
|
return -RT_ERROR;
|
||||||
|
@ -648,7 +648,7 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
|
||||||
temp = rt_hw_interrupt_disable();
|
temp = rt_hw_interrupt_disable();
|
||||||
|
|
||||||
/* change thread stat */
|
/* change thread stat */
|
||||||
thread->stat = RT_THREAD_SUSPEND;
|
thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
|
||||||
rt_schedule_remove_thread(thread);
|
rt_schedule_remove_thread(thread);
|
||||||
|
|
||||||
/* stop thread timer anyway */
|
/* stop thread timer anyway */
|
||||||
|
|
|
@ -396,7 +396,7 @@ rt_err_t rt_timer_start(rt_timer_t timer)
|
||||||
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
|
||||||
{
|
{
|
||||||
/* check whether timer thread is ready */
|
/* check whether timer thread is ready */
|
||||||
if (timer_thread.stat != RT_THREAD_READY)
|
if ((timer_thread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
|
||||||
{
|
{
|
||||||
/* resume timer thread to check soft timer */
|
/* resume timer thread to check soft timer */
|
||||||
rt_thread_resume(&timer_thread);
|
rt_thread_resume(&timer_thread);
|
||||||
|
|
Loading…
Reference in New Issue