From ca4fb5f2d08959e7296382318646047c452ba718 Mon Sep 17 00:00:00 2001 From: Chaskiel M Grundman Date: Fri, 17 Feb 2006 15:22:24 +0000 Subject: [PATCH] darwin-lost-wakeups-20060213 eliminate the apparent lost wakeup problem in tiger --- src/afs/DARWIN/osi_sleep.c | 97 +++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/src/afs/DARWIN/osi_sleep.c b/src/afs/DARWIN/osi_sleep.c index 193e3a1d4..049516441 100644 --- a/src/afs/DARWIN/osi_sleep.c +++ b/src/afs/DARWIN/osi_sleep.c @@ -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 EVTLOCK_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; + } + } +} + -- 2.39.5