]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
STABLE14-darwin-lost-wakeups-20060213
authorChaskiel M Grundman <cg2v@andrew.cmu.edu>
Mon, 13 Feb 2006 18:19:49 +0000 (18:19 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 13 Feb 2006 18:19:49 +0000 (18:19 +0000)
eliminate the apparent lost wakeup problem in tiger

src/afs/DARWIN/osi_sleep.c

index 193e3a1d42dcad15e820e162203d0225fe7a3b39..15bd022d75b6ee3b081cce249b963720e095542b 100644 (file)
@@ -84,8 +84,38 @@ typedef struct afs_event {
     int seq;                   /* Sequence number: this is incremented
                                 * by wakeup calls; wait will not return until
                                 * it changes */
+#ifdef AFS_DARWIN80_ENV
+   lck_mtx_t *lck;
+   thread_t owner;
+#endif
 } afs_event_t;
 
+#ifdef AFS_DARWIN80_ENV
+#define EVTLOCK_INIT(e) \
+    do { \
+       (e)->lck = lck_mtx_alloc_init(openafs_lck_grp, 0); \
+       (e)->owner = 0; \
+    } while (0)
+#define EVTLOCK_LOCK(e) \
+    do { \
+       osi_Assert((e)->owner != current_thread()); \
+       lck_mtx_lock((e)->lck); \
+       osi_Assert((e)->owner == 0); \
+       (e)->owner = current_thread(); \
+    } while (0)
+#define EVTLOCK_UNLOCK(e) \
+    do { \
+       osi_Assert((e)->owner == current_thread()); \
+       (e)->owner = 0; \
+       lck_mtx_unlock((e)->lck); \
+    } while (0)
+#define EVTLOCK_DESTROY(e) lck_mtx_free((e)->lck, openafs_lck_grp)
+#else
+#define EVTLOCK_INIT(e)
+#define EVTLOCK_LOCK(e)
+#define EVTLCK_UNLOCK(e)
+#define EVTLOCK_DESTROY(e)
+#endif
 #define HASHSIZE 128
 afs_event_t *afs_evhasht[HASHSIZE];    /* Hash table for events */
 #define afs_evhash(event)       (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1));
@@ -96,19 +126,21 @@ int afs_evhashcnt = 0;
 static afs_event_t *
 afs_getevent(char *event)
 {
-    afs_event_t *evp, *newp = 0;
+    afs_event_t *evp, *oevp, *newp = 0;
     int hashcode;
 
     AFS_ASSERT_GLOCK();
     hashcode = afs_evhash(event);
     evp = afs_evhasht[hashcode];
     while (evp) {
+       EVTLOCK_LOCK(evp);
        if (evp->event == event) {
            evp->refcount++;
            return evp;
        }
        if (evp->refcount == 0)
            newp = evp;
+       EVTLOCK_UNLOCK(evp);
        evp = evp->next;
     }
     if (!newp) {
@@ -117,14 +149,26 @@ afs_getevent(char *event)
        newp->next = afs_evhasht[hashcode];
        afs_evhasht[hashcode] = newp;
        newp->seq = 0;
+       EVTLOCK_INIT(newp);
     }
+    EVTLOCK_LOCK(newp);
     newp->event = event;
     newp->refcount = 1;
     return newp;
 }
 
 /* Release the specified event */
+#ifdef AFS_DARWIN80_ENV
+#define relevent(evp) \
+    do { \
+       osi_Assert((evp)->owner == current_thread()); \
+        (evp)->refcount--; \
+       (evp)->owner = 0; \
+       lck_mtx_unlock((evp)->lck); \
+    } while (0)
+#else
 #define relevent(evp) ((evp)->refcount--)
+#endif
 
 
 void
@@ -134,24 +178,33 @@ afs_osi_Sleep(void *event)
     int seq;
 
     evp = afs_getevent(event);
+#ifdef AFS_DARWIN80_ENV
+     AFS_ASSERT_GLOCK();
+     AFS_GUNLOCK();
+#endif
     seq = evp->seq;
     while (seq == evp->seq) {
-       AFS_ASSERT_GLOCK();
-       AFS_GUNLOCK();
 #ifdef AFS_DARWIN80_ENV
-        msleep(event, NULL, PVFS, "afs_osi_Sleep", NULL);
+       evp->owner = 0;
+       msleep(event, evp->lck, PVFS, "afs_osi_Sleep", NULL);
+       evp->owner = current_thread();
 #else
+       AFS_ASSERT_GLOCK();
+       AFS_GUNLOCK();
 #ifdef AFS_DARWIN14_ENV
        /* this is probably safe for all versions, but testing is hard */
        sleep(event, PVFS);
 #else
        assert_wait((event_t) event, 0);
        thread_block(0);
-#endif
 #endif
        AFS_GLOCK();
+#endif
     }
     relevent(evp);
+#ifdef AFS_DARWIN80_ENV
+    AFS_GLOCK();
+#endif
 }
 
 void 
@@ -227,7 +280,9 @@ osi_TimedSleep(char *event, afs_int32 ams, int aintok)
         prio = PVFS;
     ts.tv_sec = ams / 1000;
     ts.tv_nsec = (ams % 1000) * 1000000;
-    code = msleep(event, NULL, prio, "afs_osi_TimedSleep", &ts);
+    evp->owner = 0;
+    code = msleep(event, evp->lck, prio, "afs_osi_TimedSleep", &ts);
+    evp->owner = current_thread();
 #else
     ticks = (ams * afs_hz) / 1000;
 #ifdef AFS_DARWIN14_ENV
@@ -249,13 +304,16 @@ osi_TimedSleep(char *event, afs_int32 ams, int aintok)
     thread_set_timer(ticks, NSEC_PER_SEC / hz);
     thread_block(0);
     code = 0;
-#endif
 #endif
     AFS_GLOCK();
+#endif
     if (seq == evp->seq)
        code = EINTR;
 
     relevent(evp);
+#ifdef AFS_DARWIN80_ENV
+    AFS_GLOCK();
+#endif
     return code;
 }
 
@@ -280,3 +338,28 @@ afs_osi_Wakeup(void *event)
     relevent(evp);
     return ret;
 }
+
+void
+shutdown_osisleep(void) {
+    struct afs_event *evp, *nevp, **pevpp;
+    int i;
+    for (i=0; i < HASHSIZE; i++) {
+       evp = afs_evhasht[i];
+       pevpp = &afs_evhasht[i];
+       while (evp) {
+           EVTLOCK_LOCK(evp);
+           nevp = evp->next;
+           if (evp->refcount == 0) {
+               EVTLOCK_DESTROY(evp);
+               *pevpp = evp->next;
+               osi_FreeSmallSpace(evp);
+               afs_evhashcnt--;
+           } else {
+               EVTLOCK_UNLOCK(evp);
+               pevpp = &evp->next;
+           }
+           evp = nevp;
+       }
+    }
+}
+