]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE12-linux-sleep-wakeup-cleanup-20020624
authorChas Williams <chas@cmf.nrl.navy.mil>
Wed, 10 Jul 2002 22:04:45 +0000 (22:04 +0000)
committerDerrick Brashear <shadow@dementia.org>
Wed, 10 Jul 2002 22:04:45 +0000 (22:04 +0000)
"cleanup osi_sleep.c to remove some additional races.  this patches
removes AFS_GLOBAL_SUNLOCK and just uses that case to handle both
smp and non smp cases.  osi_TimedSleep always sleeps atleast 1 hz.
(it also always sleeps interruptibly -- you might get some extra
loops but this is better than the load average running away)
sleep_on's are replaced with the more appropriate add_waitq/schedule
sequence.  getevent is called after addevent since there is no
danger of GLOCK dropping.  getevent/addevent isnt re-merged since
osi_Wakeup doesnt create entries in the event table."

(cherry picked from commit 048543ade8eab56d47e5094fdb56bb7f49983dcf)

src/afs/LINUX/osi_sleep.c

index b5b5e96ce55276f69974ccc33822b18852148f16..0247f45d4b18a6a350b67939e18a3b9a9c1f83b4 100644 (file)
@@ -18,51 +18,12 @@ RCSID("$Header$");
 
 
 
-#if defined(AFS_GLOBAL_SUNLOCK)
 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok);
-#endif
-
 void afs_osi_Wakeup(char *event);
 void afs_osi_Sleep(char *event);
 
 static char waitV, dummyV;
 
-#if ! defined(AFS_GLOBAL_SUNLOCK)
-
-/* call procedure aproc with arock as an argument, in ams milliseconds */
-static struct timer_list *afs_osi_CallProc(void *aproc, void *arock, int ams)
-{
-    struct timer_list *timer = NULL;
-    
-    timer = (struct timer_list*)osi_Alloc(sizeof(struct timer_list));
-    if (timer) {
-       init_timer(timer);
-       timer->expires = (ams*afs_hz)/1000 + 1;
-       timer->data = (unsigned long)arock;
-       timer->function = aproc;
-       add_timer(timer);
-    }
-    return timer;
-}
-
-/* cancel a timeout, whether or not it has already occurred */
-static int afs_osi_CancelProc(struct timer_list *timer)
-{
-    if (timer) {
-       del_timer(timer);
-       osi_Free(timer, sizeof(struct timer_list));
-    }
-    return 0;
-}
-
-static AfsWaitHack()
-{
-    AFS_STATCNT(WaitHack);
-    wakeup(&waitV);
-}
-
-#endif
-
 void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle)
 {
     AFS_STATCNT(osi_InitWaitHandle);
@@ -96,25 +57,18 @@ int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok)
     if (ahandle)
        ahandle->proc = (caddr_t) current;
 
-    AFS_ASSERT_GLOCK();
     do {
-#if    defined(AFS_GLOBAL_SUNLOCK)
-        code = osi_TimedSleep(&waitV, ams, 1);
-        if (code == EINTR) {
-                if (aintok) 
-                   return EINTR;
-        }
-#else
-       timer = afs_osi_CallProc(AfsWaitHack, (char *) current, ams);
-       afs_osi_Sleep(&waitV);
-       afs_osi_CancelProc(timer);
-#endif /* AFS_GLOBAL_SUNLOCK */
+        AFS_ASSERT_GLOCK();
+        code = 0;
+        code = osi_TimedSleep(&waitV, ams, aintok);
+
+        if (code) break;
        if (ahandle && (ahandle->proc == (caddr_t) 0)) {
            /* we've been signalled */
-           return EINTR;
+           break;
        }
     } while (osi_Time() < endTime);
-    return 0;
+    return code;
 }
 
 
@@ -199,6 +153,9 @@ static void afs_addevent(char *event)
     newp->refcount = 0;
 }
 
+#ifndef set_current_state
+#define set_current_state(x)            current->state = (x);
+#endif
 
 /* Release the specified event */
 #define relevent(evp) ((evp)->refcount--)
@@ -209,22 +166,25 @@ void afs_osi_Sleep(char *event)
 {
     struct afs_event *evp;
     int seq;
+#ifdef DECLARE_WAITQUEUE
+    DECLARE_WAITQUEUE(wait, current);
+#else
+    struct wait_queue wait = { current, NULL };
+#endif
 
     evp = afs_getevent(event);
     if (!evp) {
-       /* Can't block because allocating a new event would require dropping
-         * the GLOCK, which may cause us to miss the wakeup.  So call the
-         * allocator then return immediately.  We'll find the new event next
-         * time around without dropping the GLOCK. */
         afs_addevent(event);
-        return;
+       evp = afs_getevent(event);
     }
 
     seq = evp->seq;
 
+    add_wait_queue(&evp->cond, &wait);
     while (seq == evp->seq) {
        sigset_t saved_set;
 
+       set_current_state(TASK_INTERRUPTIBLE);
        AFS_ASSERT_GLOCK();
        AFS_GUNLOCK();
        spin_lock_irq(&current->sigmask_lock);
@@ -233,7 +193,7 @@ void afs_osi_Sleep(char *event)
        recalc_sigpending(current);
        spin_unlock_irq(&current->sigmask_lock);
 
-       interruptible_sleep_on(&evp->cond);
+       schedule();
 
        spin_lock_irq(&current->sigmask_lock);
        current->blocked = saved_set;
@@ -241,6 +201,9 @@ void afs_osi_Sleep(char *event)
        spin_unlock_irq(&current->sigmask_lock);
        AFS_GLOCK();
     }
+    remove_wait_queue(&evp->cond, &wait);
+    set_current_state(TASK_RUNNING);
+
     relevent(evp);
 }
 
@@ -256,29 +219,40 @@ void afs_osi_Sleep(char *event)
  */
 static int osi_TimedSleep(char *event, afs_int32 ams, int aintok)
 {
-    long t = ams * HZ / 1000;
+    int code = 0;
+    long ticks = (ams * HZ / 1000) + 1;
     struct afs_event *evp;
+#ifdef DECLARE_WAITQUEUE
+    DECLARE_WAITQUEUE(wait, current);
+#else
+    struct wait_queue wait = { current, NULL };
+#endif
 
     evp = afs_getevent(event);
     if (!evp) {
-        /* Can't block because allocating a new event would require dropping
-         * the GLOCK, which may cause us to miss the wakeup.  So call the
-         * allocator then return immediately.  We'll find the new event next
-         * time around without dropping the GLOCK. */
         afs_addevent(event);
-        return EAGAIN;
+       evp = afs_getevent(event);
     }
 
+    add_wait_queue(&evp->cond, &wait);
+    set_current_state(TASK_INTERRUPTIBLE);
+    /* always sleep TASK_INTERRUPTIBLE to keep load average
+       from artifically increasing. */
+
     AFS_GUNLOCK();
-    if (aintok)
-       t = interruptible_sleep_on_timeout(&evp->cond, t);
-    else
-       t = sleep_on_timeout(&evp->cond, t);
+    if (aintok) {
+        if (schedule_timeout(ticks))
+            code = EINTR;
+    } else
+        schedule_timeout(ticks);
     AFS_GLOCK();
 
+    remove_wait_queue(&evp->cond, &wait);
+    set_current_state(TASK_RUNNING);
+
     relevent(evp);
 
-    return t ? EINTR : 0;
+    return code;
 }