Commit 18550640 authored by George Anzinger's avatar George Anzinger Committed by Steve French

[PATCH] Cleanups for posix timer hang fix

Clean up "pendcount" locking (or rather - lack there-of) by making it a
per-timer thing and thus automatically protected by the timer lock.

Fix whitespace damage.
parent a0b2fc70
......@@ -87,6 +87,8 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED;
SIGEV_SIGNAL & \
SIGEV_THREAD & \
SIGEV_THREAD_ID)
#define REQUEUE_PENDING 1
/*
* The timer ID is turned into a timer address by idr_find().
* Verifying a valid ID consists of:
......@@ -245,7 +247,7 @@ static void schedule_next_timer(struct k_itimer *timr)
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1;
timr->it_requeue_pending = 0;
++timr->it_requeue_pending;
add_timer(&timr->it_timer);
}
......@@ -286,16 +288,16 @@ void do_schedule_next_timer(struct siginfo *info)
* without an info block. In this case, we will not get a call back to
* do_schedule_next_timer() so we do it here. This should be rare...
* An interesting problem can occure if, while a signal, and thus a call
* An interesting problem can occur if, while a signal, and thus a call
* back is pending, the timer is rearmed, i.e. stopped and restarted.
* We then need to sort out the call back and do the right thing. What
* we do is to put a counter in the info block and match it with the
* timers copy on the call back. If they don't match, we just ignore
* the call back. Note that we do allow the timer to be deleted while
* a signal is pending. The standard says we can allow that signal to
* be delivered, and we do.
* the call back. The counter is local to the timer and we use odd to
* indicate a call back is pending. Note that we do allow the timer to
* be deleted while a signal is pending. The standard says we can
* allow that signal to be delivered, and we do.
*/
static int pendcount = 1;
static void timer_notify_task(struct k_itimer *timr)
{
......@@ -310,17 +312,12 @@ static void timer_notify_task(struct k_itimer *timr)
info.si_code = SI_TIMER;
info.si_tid = timr->it_id;
info.si_value = timr->it_sigev_value;
if (timr->it_incr){
/*
* Don't allow a call back counter of zero...
* and avoid the test by using 2.
*/
pendcount += 2;
timr->it_requeue_pending = info.si_sys_private = pendcount;
}
if( timr->it_sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV){
if (timr->it_incr)
info.si_sys_private = ++timr->it_requeue_pending;
if (timr->it_sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV)
ret = send_sig_info(info.si_signo, &info, timr->it_process);
}else
else
ret = send_group_sig_info(info.si_signo, &info,
timr->it_process);
switch (ret) {
......@@ -617,7 +614,7 @@ do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
posix_time_before(&timr->it_timer, &now))
timr->it_timer.expires = expires = 0;
if (expires) {
if (timr->it_requeue_pending ||
if (timr->it_requeue_pending & REQUEUE_PENDING ||
(timr->it_sigev_notify & SIGEV_NONE))
while (posix_time_before(&timr->it_timer, &now))
posix_bump_timer(timr);
......@@ -779,7 +776,8 @@ do_timer_settime(struct k_itimer *timr, int flags,
#else
del_timer(&timr->it_timer);
#endif
timr->it_requeue_pending = 0;
timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
~REQUEUE_PENDING;
timr->it_overrun_last = 0;
timr->it_overrun = -1;
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment