diff options
Diffstat (limited to 'kernel/posix-timers.c')
-rw-r--r-- | kernel/posix-timers.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index a140e44eebba..887c63787de6 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -116,7 +116,7 @@ static DEFINE_SPINLOCK(idr_lock); | |||
116 | * must supply functions here, even if the function just returns | 116 | * must supply functions here, even if the function just returns |
117 | * ENOSYS. The standard POSIX timer management code assumes the | 117 | * ENOSYS. The standard POSIX timer management code assumes the |
118 | * following: 1.) The k_itimer struct (sched.h) is used for the | 118 | * following: 1.) The k_itimer struct (sched.h) is used for the |
119 | * timer. 2.) The list, it_lock, it_clock, it_id and it_process | 119 | * timer. 2.) The list, it_lock, it_clock, it_id and it_pid |
120 | * fields are not modified by timer code. | 120 | * fields are not modified by timer code. |
121 | * | 121 | * |
122 | * At this time all functions EXCEPT clock_nanosleep can be | 122 | * At this time all functions EXCEPT clock_nanosleep can be |
@@ -319,7 +319,8 @@ void do_schedule_next_timer(struct siginfo *info) | |||
319 | 319 | ||
320 | int posix_timer_event(struct k_itimer *timr, int si_private) | 320 | int posix_timer_event(struct k_itimer *timr, int si_private) |
321 | { | 321 | { |
322 | int shared, ret; | 322 | struct task_struct *task; |
323 | int shared, ret = -1; | ||
323 | /* | 324 | /* |
324 | * FIXME: if ->sigq is queued we can race with | 325 | * FIXME: if ->sigq is queued we can race with |
325 | * dequeue_signal()->do_schedule_next_timer(). | 326 | * dequeue_signal()->do_schedule_next_timer(). |
@@ -333,8 +334,13 @@ int posix_timer_event(struct k_itimer *timr, int si_private) | |||
333 | */ | 334 | */ |
334 | timr->sigq->info.si_sys_private = si_private; | 335 | timr->sigq->info.si_sys_private = si_private; |
335 | 336 | ||
336 | shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID); | 337 | rcu_read_lock(); |
337 | ret = send_sigqueue(timr->sigq, timr->it_process, shared); | 338 | task = pid_task(timr->it_pid, PIDTYPE_PID); |
339 | if (task) { | ||
340 | shared = !(timr->it_sigev_notify & SIGEV_THREAD_ID); | ||
341 | ret = send_sigqueue(timr->sigq, task, shared); | ||
342 | } | ||
343 | rcu_read_unlock(); | ||
338 | /* If we failed to send the signal the timer stops. */ | 344 | /* If we failed to send the signal the timer stops. */ |
339 | return ret > 0; | 345 | return ret > 0; |
340 | } | 346 | } |
@@ -411,7 +417,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer) | |||
411 | return ret; | 417 | return ret; |
412 | } | 418 | } |
413 | 419 | ||
414 | static struct task_struct * good_sigevent(sigevent_t * event) | 420 | static struct pid *good_sigevent(sigevent_t * event) |
415 | { | 421 | { |
416 | struct task_struct *rtn = current->group_leader; | 422 | struct task_struct *rtn = current->group_leader; |
417 | 423 | ||
@@ -425,7 +431,7 @@ static struct task_struct * good_sigevent(sigevent_t * event) | |||
425 | ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) | 431 | ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX))) |
426 | return NULL; | 432 | return NULL; |
427 | 433 | ||
428 | return rtn; | 434 | return task_pid(rtn); |
429 | } | 435 | } |
430 | 436 | ||
431 | void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock) | 437 | void register_posix_clock(const clockid_t clock_id, struct k_clock *new_clock) |
@@ -464,6 +470,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) | |||
464 | idr_remove(&posix_timers_id, tmr->it_id); | 470 | idr_remove(&posix_timers_id, tmr->it_id); |
465 | spin_unlock_irqrestore(&idr_lock, flags); | 471 | spin_unlock_irqrestore(&idr_lock, flags); |
466 | } | 472 | } |
473 | put_pid(tmr->it_pid); | ||
467 | sigqueue_free(tmr->sigq); | 474 | sigqueue_free(tmr->sigq); |
468 | kmem_cache_free(posix_timers_cache, tmr); | 475 | kmem_cache_free(posix_timers_cache, tmr); |
469 | } | 476 | } |
@@ -477,7 +484,6 @@ sys_timer_create(const clockid_t which_clock, | |||
477 | { | 484 | { |
478 | struct k_itimer *new_timer; | 485 | struct k_itimer *new_timer; |
479 | int error, new_timer_id; | 486 | int error, new_timer_id; |
480 | struct task_struct *process; | ||
481 | sigevent_t event; | 487 | sigevent_t event; |
482 | int it_id_set = IT_ID_NOT_SET; | 488 | int it_id_set = IT_ID_NOT_SET; |
483 | 489 | ||
@@ -531,11 +537,9 @@ sys_timer_create(const clockid_t which_clock, | |||
531 | goto out; | 537 | goto out; |
532 | } | 538 | } |
533 | rcu_read_lock(); | 539 | rcu_read_lock(); |
534 | process = good_sigevent(&event); | 540 | new_timer->it_pid = get_pid(good_sigevent(&event)); |
535 | if (process) | ||
536 | get_task_struct(process); | ||
537 | rcu_read_unlock(); | 541 | rcu_read_unlock(); |
538 | if (!process) { | 542 | if (!new_timer->it_pid) { |
539 | error = -EINVAL; | 543 | error = -EINVAL; |
540 | goto out; | 544 | goto out; |
541 | } | 545 | } |
@@ -543,8 +547,7 @@ sys_timer_create(const clockid_t which_clock, | |||
543 | event.sigev_notify = SIGEV_SIGNAL; | 547 | event.sigev_notify = SIGEV_SIGNAL; |
544 | event.sigev_signo = SIGALRM; | 548 | event.sigev_signo = SIGALRM; |
545 | event.sigev_value.sival_int = new_timer->it_id; | 549 | event.sigev_value.sival_int = new_timer->it_id; |
546 | process = current->group_leader; | 550 | new_timer->it_pid = get_pid(task_tgid(current)); |
547 | get_task_struct(process); | ||
548 | } | 551 | } |
549 | 552 | ||
550 | new_timer->it_sigev_notify = event.sigev_notify; | 553 | new_timer->it_sigev_notify = event.sigev_notify; |
@@ -554,7 +557,7 @@ sys_timer_create(const clockid_t which_clock, | |||
554 | new_timer->sigq->info.si_code = SI_TIMER; | 557 | new_timer->sigq->info.si_code = SI_TIMER; |
555 | 558 | ||
556 | spin_lock_irq(¤t->sighand->siglock); | 559 | spin_lock_irq(¤t->sighand->siglock); |
557 | new_timer->it_process = process; | 560 | new_timer->it_signal = current->signal; |
558 | list_add(&new_timer->list, ¤t->signal->posix_timers); | 561 | list_add(&new_timer->list, ¤t->signal->posix_timers); |
559 | spin_unlock_irq(¤t->sighand->siglock); | 562 | spin_unlock_irq(¤t->sighand->siglock); |
560 | 563 | ||
@@ -589,8 +592,7 @@ static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags) | |||
589 | timr = idr_find(&posix_timers_id, (int)timer_id); | 592 | timr = idr_find(&posix_timers_id, (int)timer_id); |
590 | if (timr) { | 593 | if (timr) { |
591 | spin_lock(&timr->it_lock); | 594 | spin_lock(&timr->it_lock); |
592 | if (timr->it_process && | 595 | if (timr->it_signal == current->signal) { |
593 | same_thread_group(timr->it_process, current)) { | ||
594 | spin_unlock(&idr_lock); | 596 | spin_unlock(&idr_lock); |
595 | return timr; | 597 | return timr; |
596 | } | 598 | } |
@@ -837,8 +839,7 @@ retry_delete: | |||
837 | * This keeps any tasks waiting on the spin lock from thinking | 839 | * This keeps any tasks waiting on the spin lock from thinking |
838 | * they got something (see the lock code above). | 840 | * they got something (see the lock code above). |
839 | */ | 841 | */ |
840 | put_task_struct(timer->it_process); | 842 | timer->it_signal = NULL; |
841 | timer->it_process = NULL; | ||
842 | 843 | ||
843 | unlock_timer(timer, flags); | 844 | unlock_timer(timer, flags); |
844 | release_posix_timer(timer, IT_ID_SET); | 845 | release_posix_timer(timer, IT_ID_SET); |
@@ -864,8 +865,7 @@ retry_delete: | |||
864 | * This keeps any tasks waiting on the spin lock from thinking | 865 | * This keeps any tasks waiting on the spin lock from thinking |
865 | * they got something (see the lock code above). | 866 | * they got something (see the lock code above). |
866 | */ | 867 | */ |
867 | put_task_struct(timer->it_process); | 868 | timer->it_signal = NULL; |
868 | timer->it_process = NULL; | ||
869 | 869 | ||
870 | unlock_timer(timer, flags); | 870 | unlock_timer(timer, flags); |
871 | release_posix_timer(timer, IT_ID_SET); | 871 | release_posix_timer(timer, IT_ID_SET); |