[PATCH] more SPIN_LOCK_UNLOCKED -> DEFINE_SPINLOCK conversions
[pandora-kernel.git] / kernel / posix-timers.c
index cabb63f..b7b532a 100644 (file)
@@ -88,23 +88,6 @@ static kmem_cache_t *posix_timers_cache;
 static struct idr posix_timers_id;
 static DEFINE_SPINLOCK(idr_lock);
 
-/*
- * Just because the timer is not in the timer list does NOT mean it is
- * inactive.  It could be in the "fire" routine getting a new expire time.
- */
-#define TIMER_INACTIVE 1
-
-#ifdef CONFIG_SMP
-# define timer_active(tmr) \
-               ((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
-# define set_timer_inactive(tmr) \
-               do { \
-                       (tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
-               } while (0)
-#else
-# define timer_active(tmr) BARFY       // error to use outside of SMP
-# define set_timer_inactive(tmr) do { } while (0)
-#endif
 /*
  * we assume that the new SIGEV_THREAD_ID shares no bits with the other
  * SIGEV values.  Here we put out an error if this assumption fails.
@@ -226,7 +209,6 @@ static inline int common_timer_create(struct k_itimer *new_timer)
        init_timer(&new_timer->it.real.timer);
        new_timer->it.real.timer.data = (unsigned long) new_timer;
        new_timer->it.real.timer.function = posix_timer_fn;
-       set_timer_inactive(new_timer);
        return 0;
 }
 
@@ -445,21 +427,23 @@ int posix_timer_event(struct k_itimer *timr,int si_private)
        timr->sigq->info.si_code = SI_TIMER;
        timr->sigq->info.si_tid = timr->it_id;
        timr->sigq->info.si_value = timr->it_sigev_value;
+
        if (timr->it_sigev_notify & SIGEV_THREAD_ID) {
-               if (unlikely(timr->it_process->flags & PF_EXITING)) {
-                       timr->it_sigev_notify = SIGEV_SIGNAL;
-                       put_task_struct(timr->it_process);
-                       timr->it_process = timr->it_process->group_leader;
-                       goto group;
-               }
-               return send_sigqueue(timr->it_sigev_signo, timr->sigq,
-                       timr->it_process);
-       }
-       else {
-       group:
-               return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
-                       timr->it_process);
+               struct task_struct *leader;
+               int ret = send_sigqueue(timr->it_sigev_signo, timr->sigq,
+                                       timr->it_process);
+
+               if (likely(ret >= 0))
+                       return ret;
+
+               timr->it_sigev_notify = SIGEV_SIGNAL;
+               leader = timr->it_process->group_leader;
+               put_task_struct(timr->it_process);
+               timr->it_process = leader;
        }
+
+       return send_group_sigqueue(timr->it_sigev_signo, timr->sigq,
+                                  timr->it_process);
 }
 EXPORT_SYMBOL_GPL(posix_timer_event);
 
@@ -480,7 +464,6 @@ static void posix_timer_fn(unsigned long __data)
        int do_notify = 1;
 
        spin_lock_irqsave(&timr->it_lock, flags);
-       set_timer_inactive(timr);
        if (!list_empty(&timr->it.real.abs_timer_entry)) {
                spin_lock(&abs_list.lock);
                do {
@@ -915,21 +898,10 @@ static int adjust_abs_time(struct k_clock *clock, struct timespec *tp,
                        jiffies_64_f = get_jiffies_64();
                }
                /*
-                * Take away now to get delta
+                * Take away now to get delta and normalize
                 */
-               oc.tv_sec -= now.tv_sec;
-               oc.tv_nsec -= now.tv_nsec;
-               /*
-                * Normalize...
-                */
-               while ((oc.tv_nsec - NSEC_PER_SEC) >= 0) {
-                       oc.tv_nsec -= NSEC_PER_SEC;
-                       oc.tv_sec++;
-               }
-               while ((oc.tv_nsec) < 0) {
-                       oc.tv_nsec += NSEC_PER_SEC;
-                       oc.tv_sec--;
-               }
+               set_normalized_timespec(&oc, oc.tv_sec - now.tv_sec,
+                                       oc.tv_nsec - now.tv_nsec);
        }else{
                jiffies_64_f = get_jiffies_64();
        }
@@ -983,8 +955,8 @@ common_timer_set(struct k_itimer *timr, int flags,
         * careful here.  If smp we could be in the "fire" routine which will
         * be spinning as we hold the lock.  But this is ONLY an SMP issue.
         */
+       if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
 #ifdef CONFIG_SMP
-       if (timer_active(timr) && !del_timer(&timr->it.real.timer))
                /*
                 * It can only be active if on an other cpu.  Since
                 * we have cleared the interval stuff above, it should
@@ -994,11 +966,9 @@ common_timer_set(struct k_itimer *timr, int flags,
                 * a "retry" exit status.
                 */
                return TIMER_RETRY;
-
-       set_timer_inactive(timr);
-#else
-       del_timer(&timr->it.real.timer);
 #endif
+       }
+
        remove_from_abslist(timr);
 
        timr->it_requeue_pending = (timr->it_requeue_pending + 2) & 
@@ -1083,8 +1053,9 @@ retry:
 static inline int common_timer_del(struct k_itimer *timer)
 {
        timer->it.real.incr = 0;
+
+       if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
 #ifdef CONFIG_SMP
-       if (timer_active(timer) && !del_timer(&timer->it.real.timer))
                /*
                 * It can only be active if on an other cpu.  Since
                 * we have cleared the interval stuff above, it should
@@ -1094,9 +1065,9 @@ static inline int common_timer_del(struct k_itimer *timer)
                 * a "retry" exit status.
                 */
                return TIMER_RETRY;
-#else
-       del_timer(&timer->it.real.timer);
 #endif
+       }
+
        remove_from_abslist(timer);
 
        return 0;
@@ -1197,7 +1168,6 @@ void exit_itimers(struct signal_struct *sig)
                tmr = list_entry(sig->posix_timers.next, struct k_itimer, list);
                itimer_delete(tmr);
        }
-       del_timer_sync(&sig->real_timer);
 }
 
 /*