diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 08:58:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-25 08:58:50 -0700 |
commit | 19426a8f810752b4218e59b1e2187f33e255f7bc (patch) | |
tree | dd88adc38ef98a10b1eea952f16d7480411e2409 | |
parent | 0f1493a60167cf6333626456d3fc8aff4e6fa237 (diff) | |
parent | 8af088710d1eb3c980e0ef3779c8d47f3f217b48 (diff) |
Merge branch 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'timers-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
posix-timers: RCU conversion
-rw-r--r-- | include/linux/posix-timers.h | 1 | ||||
-rw-r--r-- | kernel/posix-timers.c | 25 |
2 files changed, 15 insertions, 11 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 808227d40a6..959c14132f4 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -82,6 +82,7 @@ struct k_itimer { unsigned long expires; } mmtimer; struct alarm alarmtimer; + struct rcu_head rcu; } it; }; diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index a1b5edf1bf9..4556182527f 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -491,6 +491,13 @@ static struct k_itimer * alloc_posix_timer(void) return tmr; } +static void k_itimer_rcu_free(struct rcu_head *head) +{ + struct k_itimer *tmr = container_of(head, struct k_itimer, it.rcu); + + kmem_cache_free(posix_timers_cache, tmr); +} + #define IT_ID_SET 1 #define IT_ID_NOT_SET 0 static void release_posix_timer(struct k_itimer *tmr, int it_id_set) @@ -503,7 +510,7 @@ static void release_posix_timer(struct k_itimer *tmr, int it_id_set) } put_pid(tmr->it_pid); sigqueue_free(tmr->sigq); - kmem_cache_free(posix_timers_cache, tmr); + call_rcu(&tmr->it.rcu, k_itimer_rcu_free); } static struct k_clock *clockid_to_kclock(const clockid_t id) @@ -631,22 +638,18 @@ out: static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) { struct k_itimer *timr; - /* - * Watch out here. We do a irqsave on the idr_lock and pass the - * flags part over to the timer lock. Must not let interrupts in - * while we are moving the lock. - */ - spin_lock_irqsave(&idr_lock, *flags); + + rcu_read_lock(); timr = idr_find(&posix_timers_id, (int)timer_id); if (timr) { - spin_lock(&timr->it_lock); + spin_lock_irqsave(&timr->it_lock, *flags); if (timr->it_signal == current->signal) { - spin_unlock(&idr_lock); + rcu_read_unlock(); return timr; } - spin_unlock(&timr->it_lock); + spin_unlock_irqrestore(&timr->it_lock, *flags); } - spin_unlock_irqrestore(&idr_lock, *flags); + rcu_read_unlock(); return NULL; } |