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; ...@@ -87,6 +87,8 @@ static spinlock_t idr_lock = SPIN_LOCK_UNLOCKED;
SIGEV_SIGNAL & \ SIGEV_SIGNAL & \
SIGEV_THREAD & \ SIGEV_THREAD & \
SIGEV_THREAD_ID) SIGEV_THREAD_ID)
#define REQUEUE_PENDING 1
/* /*
* The timer ID is turned into a timer address by idr_find(). * The timer ID is turned into a timer address by idr_find().
* Verifying a valid ID consists of: * Verifying a valid ID consists of:
...@@ -245,7 +247,7 @@ static void schedule_next_timer(struct k_itimer *timr) ...@@ -245,7 +247,7 @@ static void schedule_next_timer(struct k_itimer *timr)
timr->it_overrun_last = timr->it_overrun; timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1; timr->it_overrun = -1;
timr->it_requeue_pending = 0; ++timr->it_requeue_pending;
add_timer(&timr->it_timer); add_timer(&timr->it_timer);
} }
...@@ -286,16 +288,16 @@ void do_schedule_next_timer(struct siginfo *info) ...@@ -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 * 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... * 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. * 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 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 * 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 * 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 * the call back. The counter is local to the timer and we use odd to
* a signal is pending. The standard says we can allow that signal to * indicate a call back is pending. Note that we do allow the timer to
* be delivered, and we do. * 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) static void timer_notify_task(struct k_itimer *timr)
{ {
...@@ -310,17 +312,12 @@ 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_code = SI_TIMER;
info.si_tid = timr->it_id; info.si_tid = timr->it_id;
info.si_value = timr->it_sigev_value; info.si_value = timr->it_sigev_value;
if (timr->it_incr){ if (timr->it_incr)
/* info.si_sys_private = ++timr->it_requeue_pending;
* Don't allow a call back counter of zero...
* and avoid the test by using 2. if (timr->it_sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV)
*/
pendcount += 2;
timr->it_requeue_pending = info.si_sys_private = pendcount;
}
if( timr->it_sigev_notify & SIGEV_THREAD_ID & MIPS_SIGEV){
ret = send_sig_info(info.si_signo, &info, timr->it_process); ret = send_sig_info(info.si_signo, &info, timr->it_process);
}else else
ret = send_group_sig_info(info.si_signo, &info, ret = send_group_sig_info(info.si_signo, &info,
timr->it_process); timr->it_process);
switch (ret) { switch (ret) {
...@@ -617,7 +614,7 @@ do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting) ...@@ -617,7 +614,7 @@ do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
posix_time_before(&timr->it_timer, &now)) posix_time_before(&timr->it_timer, &now))
timr->it_timer.expires = expires = 0; timr->it_timer.expires = expires = 0;
if (expires) { if (expires) {
if (timr->it_requeue_pending || if (timr->it_requeue_pending & REQUEUE_PENDING ||
(timr->it_sigev_notify & SIGEV_NONE)) (timr->it_sigev_notify & SIGEV_NONE))
while (posix_time_before(&timr->it_timer, &now)) while (posix_time_before(&timr->it_timer, &now))
posix_bump_timer(timr); posix_bump_timer(timr);
...@@ -779,7 +776,8 @@ do_timer_settime(struct k_itimer *timr, int flags, ...@@ -779,7 +776,8 @@ do_timer_settime(struct k_itimer *timr, int flags,
#else #else
del_timer(&timr->it_timer); del_timer(&timr->it_timer);
#endif #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_last = 0;
timr->it_overrun = -1; 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