aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/posix-timers.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-08-15 12:15:17 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-15 12:15:17 -0400
commitf3efbe582b5396d134024c03a5fa253f2a85d9a6 (patch)
treee4e15b7567b82d24cb1e7327398286a2b88df04c /kernel/posix-timers.c
parent05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 (diff)
parentb635acec48bcaa9183fcbf4e3955616b0d4119b5 (diff)
Merge branch 'linus' into x86/gart
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r--kernel/posix-timers.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index dbd8398ddb0b..e36d5798cbff 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -289,21 +289,29 @@ void do_schedule_next_timer(struct siginfo *info)
289 else 289 else
290 schedule_next_timer(timr); 290 schedule_next_timer(timr);
291 291
292 info->si_overrun = timr->it_overrun_last; 292 info->si_overrun += timr->it_overrun_last;
293 } 293 }
294 294
295 if (timr) 295 if (timr)
296 unlock_timer(timr, flags); 296 unlock_timer(timr, flags);
297} 297}
298 298
299int posix_timer_event(struct k_itimer *timr,int si_private) 299int posix_timer_event(struct k_itimer *timr, int si_private)
300{ 300{
301 memset(&timr->sigq->info, 0, sizeof(siginfo_t)); 301 /*
302 * FIXME: if ->sigq is queued we can race with
303 * dequeue_signal()->do_schedule_next_timer().
304 *
305 * If dequeue_signal() sees the "right" value of
306 * si_sys_private it calls do_schedule_next_timer().
307 * We re-queue ->sigq and drop ->it_lock().
308 * do_schedule_next_timer() locks the timer
309 * and re-schedules it while ->sigq is pending.
310 * Not really bad, but not that we want.
311 */
302 timr->sigq->info.si_sys_private = si_private; 312 timr->sigq->info.si_sys_private = si_private;
303 /* Send signal to the process that owns this timer.*/
304 313
305 timr->sigq->info.si_signo = timr->it_sigev_signo; 314 timr->sigq->info.si_signo = timr->it_sigev_signo;
306 timr->sigq->info.si_errno = 0;
307 timr->sigq->info.si_code = SI_TIMER; 315 timr->sigq->info.si_code = SI_TIMER;
308 timr->sigq->info.si_tid = timr->it_id; 316 timr->sigq->info.si_tid = timr->it_id;
309 timr->sigq->info.si_value = timr->it_sigev_value; 317 timr->sigq->info.si_value = timr->it_sigev_value;
@@ -435,6 +443,7 @@ static struct k_itimer * alloc_posix_timer(void)
435 kmem_cache_free(posix_timers_cache, tmr); 443 kmem_cache_free(posix_timers_cache, tmr);
436 tmr = NULL; 444 tmr = NULL;
437 } 445 }
446 memset(&tmr->sigq->info, 0, sizeof(siginfo_t));
438 return tmr; 447 return tmr;
439} 448}
440 449
@@ -449,9 +458,6 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set)
449 spin_unlock_irqrestore(&idr_lock, flags); 458 spin_unlock_irqrestore(&idr_lock, flags);
450 } 459 }
451 sigqueue_free(tmr->sigq); 460 sigqueue_free(tmr->sigq);
452 if (unlikely(tmr->it_process) &&
453 tmr->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
454 put_task_struct(tmr->it_process);
455 kmem_cache_free(posix_timers_cache, tmr); 461 kmem_cache_free(posix_timers_cache, tmr);
456} 462}
457 463
@@ -856,11 +862,10 @@ retry_delete:
856 * This keeps any tasks waiting on the spin lock from thinking 862 * This keeps any tasks waiting on the spin lock from thinking
857 * they got something (see the lock code above). 863 * they got something (see the lock code above).
858 */ 864 */
859 if (timer->it_process) { 865 if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
860 if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) 866 put_task_struct(timer->it_process);
861 put_task_struct(timer->it_process); 867 timer->it_process = NULL;
862 timer->it_process = NULL; 868
863 }
864 unlock_timer(timer, flags); 869 unlock_timer(timer, flags);
865 release_posix_timer(timer, IT_ID_SET); 870 release_posix_timer(timer, IT_ID_SET);
866 return 0; 871 return 0;
@@ -885,11 +890,10 @@ retry_delete:
885 * This keeps any tasks waiting on the spin lock from thinking 890 * This keeps any tasks waiting on the spin lock from thinking
886 * they got something (see the lock code above). 891 * they got something (see the lock code above).
887 */ 892 */
888 if (timer->it_process) { 893 if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID))
889 if (timer->it_sigev_notify == (SIGEV_SIGNAL|SIGEV_THREAD_ID)) 894 put_task_struct(timer->it_process);
890 put_task_struct(timer->it_process); 895 timer->it_process = NULL;
891 timer->it_process = NULL; 896
892 }
893 unlock_timer(timer, flags); 897 unlock_timer(timer, flags);
894 release_posix_timer(timer, IT_ID_SET); 898 release_posix_timer(timer, IT_ID_SET);
895} 899}