diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-08-14 06:19:59 -0400 |
| commit | 8d7ccaa545490cdffdfaff0842436a8dd85cf47b (patch) | |
| tree | 8129b5907161bc6ae26deb3645ce1e280c5e1f51 /kernel/posix-timers.c | |
| parent | b2139aa0eec330c711c5a279db361e5ef1178e78 (diff) | |
| parent | 30a2f3c60a84092c8084dfe788b710f8d0768cd4 (diff) | |
Merge commit 'v2.6.27-rc3' into x86/prototypes
Conflicts:
include/asm-x86/dma-mapping.h
Signed-off-by: Ingo Molnar <mingo@elte.hu>
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 | } |
