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));
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) {
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
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
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
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;
}
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;
+ }
+ }
+}
+