diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-08-15 12:15:17 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-15 12:15:17 -0400 |
commit | f3efbe582b5396d134024c03a5fa253f2a85d9a6 (patch) | |
tree | e4e15b7567b82d24cb1e7327398286a2b88df04c /kernel/posix-timers.c | |
parent | 05d3ed0a1fe3ea05ab9f3b8d32576a0bc2e19660 (diff) | |
parent | b635acec48bcaa9183fcbf4e3955616b0d4119b5 (diff) |
Merge branch 'linus' into x86/gart
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r-- | kernel/posix-timers.c | 40 |
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 | ||
299 | int posix_timer_event(struct k_itimer *timr,int si_private) | 299 | int 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 | } |