From 6c628445ebc3203ddcb8167914d61ef3711380c7 Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Thu, 4 Feb 2010 03:22:15 -0500 Subject: [PATCH] provide afs_osi_TimedSleep this interface works how osi_Wait *should*, except on some platforms Wait appears to wake up all waiters(!) by using a single wait channel in the backend. rather than change that and risk problems, introduce an interface using the same system of events we use for osi_Sleep Change-Id: Ic91726b138bd2512282896ec48c542063ef000cf Reviewed-on: http://gerrit.openafs.org/1233 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- src/afs/AIX/osi_sleep.c | 12 ++--- src/afs/DARWIN/osi_sleep.c | 12 ++--- src/afs/FBSD/osi_sleep.c | 100 ++++++++++++++++++++++++++++++----- src/afs/HPUX/osi_sleep.c | 16 ++++++ src/afs/IRIX/osi_sleep.c | 14 ++--- src/afs/LINUX/osi_sleep.c | 10 ++-- src/afs/LINUX24/osi_sleep.c | 10 ++-- src/afs/NBSD/osi_sleep.c | 12 ++--- src/afs/OBSD/osi_sleep.c | 24 +++++++++ src/afs/SOLARIS/osi_sleep.c | 10 ++-- src/afs/UKERNEL/afs_usrops.c | 6 +++ src/afs/afs_prototypes.h | 1 + 12 files changed, 161 insertions(+), 66 deletions(-) diff --git a/src/afs/AIX/osi_sleep.c b/src/afs/AIX/osi_sleep.c index 33e6505816..3ba0e41d9d 100644 --- a/src/afs/AIX/osi_sleep.c +++ b/src/afs/AIX/osi_sleep.c @@ -15,10 +15,6 @@ #include "afsincludes.h" /* Afs-based standard headers */ #include "afs/afs_stats.h" /* afs statistics */ - - -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV; static void @@ -70,7 +66,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); code = 0; - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ @@ -163,7 +159,7 @@ afs_osi_SleepSig(void *event) return 0; } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -172,8 +168,8 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; diff --git a/src/afs/DARWIN/osi_sleep.c b/src/afs/DARWIN/osi_sleep.c index 33e16c33bb..5c4085efc5 100644 --- a/src/afs/DARWIN/osi_sleep.c +++ b/src/afs/DARWIN/osi_sleep.c @@ -15,12 +15,8 @@ #include "afsincludes.h" /* Afs-based standard headers */ #include "afs/afs_stats.h" /* afs statistics */ - -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV; - void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle) { @@ -60,7 +56,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); code = 0; - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ @@ -244,7 +240,7 @@ afs_osi_SleepSig(void *event) return 0; } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -253,8 +249,8 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; diff --git a/src/afs/FBSD/osi_sleep.c b/src/afs/FBSD/osi_sleep.c index 466e280d96..10b6bef242 100644 --- a/src/afs/FBSD/osi_sleep.c +++ b/src/afs/FBSD/osi_sleep.c @@ -17,7 +17,6 @@ #include "afs/afs_stats.h" /* afs statistics */ #ifndef AFS_FBSD50_ENV -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); static char waitV; #endif @@ -88,8 +87,10 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) AFS_ASSERT_GLOCK(); if (ahandle == NULL) { /* This is nasty and evil and rude. */ + afs_global_owner = 0; code = msleep(&tv, &afs_global_mtx, (aintok ? PPAUSE|PCATCH : PVFS), "afswait", ticks); + afs_global_owner = curthread; } else { if (!ahandle->wh_inited) afs_osi_InitWaitHandle(ahandle); /* XXX should not be needed */ @@ -106,7 +107,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) ahandle->proc = (caddr_t) curproc; do { AFS_ASSERT_GLOCK(); - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ /* if we we're cancelled, quit now */ @@ -129,7 +130,12 @@ typedef struct afs_event { int seq; /* Sequence number: this is incremented * by wakeup calls; wait will not return until * it changes */ +#ifdef AFS_FBSD50_ENV + struct mtx *lck; + struct thread *owner; +#else int cond; +#endif } afs_event_t; #define HASHSIZE 128 @@ -137,6 +143,34 @@ afs_event_t *afs_evhasht[HASHSIZE]; /* Hash table for events */ #define afs_evhash(event) (afs_uint32) ((((long)event)>>2) & (HASHSIZE-1)); int afs_evhashcnt = 0; +#ifdef AFS_FBSD50_ENV +#define EVTLOCK_INIT(e) \ + do { \ + mtx_init((e)->lck, "event lock", NULL, MTX_DEF); \ + (e)->owner = 0; \ + } while (0) +#define EVTLOCK_LOCK(e) \ + do { \ + osi_Assert((e)->owner != curthread); \ + mtx_lock((e)->lck); \ + osi_Assert((e)->owner == 0); \ + (e)->owner = curthread; \ + } while (0) +#define EVTLOCK_UNLOCK(e) \ + do { \ + osi_Assert((e)->owner == curthread); \ + (e)->owner = 0; \ + mtx_unlock((e)->lck); \ + } while (0) +#define EVTLOCK_DESTROY(e) mtx_destroy((e)->lck) +#else +#define EVTLOCK_INIT(e) +#define EVTLOCK_LOCK(e) +#define EVTLOCK_UNLOCK(e) +#define EVTLOCK_DESTROY(e) +#endif +#endif + /* Get and initialize event structure corresponding to lwp event (i.e. address) * */ static afs_event_t * @@ -149,12 +183,14 @@ afs_getevent(char *event) 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) { @@ -163,15 +199,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_FBSD50_ENV +#define relevent(evp) \ + do { \ + osi_Assert((evp)->owner == curthread); \ + (evp)->refcount--; \ + (evp)->owner = 0; \ + mtx_unlock((evp)->lck); \ + } while (0) +#else #define relevent(evp) ((evp)->refcount--) - +#endif void afs_osi_Sleep(void *event) @@ -184,7 +231,9 @@ afs_osi_Sleep(void *event) while (seq == evp->seq) { AFS_ASSERT_GLOCK(); #ifdef AFS_FBSD50_ENV + evp->owner = 0; msleep(event, &afs_global_mtx, PVFS, "afsslp", 0); + evp->owner = curthread; #else AFS_GUNLOCK(); tsleep(event, PVFS, "afs_osi_Sleep", 0); @@ -201,8 +250,7 @@ afs_osi_SleepSig(void *event) return 0; } -#ifndef AFS_FBSD50_ENV -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -211,16 +259,13 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; - int ticks; int seq, prio; - - ticks = (ams * afs_hz) / 1000; - + struct timespec ts; evp = afs_getevent(event); seq = evp->seq; @@ -229,14 +274,17 @@ osi_TimedSleep(char *event, afs_int32 ams, int aintok) prio = PCATCH | PPAUSE; else prio = PVFS; - code = tsleep(event, prio, "afs_osi_TimedSleep", ticks); - AFS_GLOCK(); + ts.tv_sec = ams / 1000; + ts.tv_nsec = (ams % 1000) * 1000000; + evp->owner = 0; + code = msleep(event, evp->lck, prio, "afsslp", &ts); + evp->owner = curthread; if (seq == evp->seq) code = EINTR; relevent(evp); + AFS_GLOCK(); return code; } -#endif /* not AFS_FBSD50_ENV */ int afs_osi_Wakeup(void *event) @@ -253,3 +301,27 @@ 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; + } + } +} diff --git a/src/afs/HPUX/osi_sleep.c b/src/afs/HPUX/osi_sleep.c index 2b12b4dc6e..61eb55eb14 100644 --- a/src/afs/HPUX/osi_sleep.c +++ b/src/afs/HPUX/osi_sleep.c @@ -163,6 +163,22 @@ afs_osi_SleepSig(void *event) } #if defined(AFS_HPUX110_ENV) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) +{ + lock_t *sleep_lock; + int intr = EWOULDBLOCK; + + AFS_ASSERT_GLOCK(); + AFS_GUNLOCK(); + afs_osi_CallProc(AfsWaitHack, event, ams); + sleep((caddr_t) event, PZERO - 2); + if (afs_osi_CancelProc(AfsWaitHack, event) < 0) + intr = 0; + AFS_GLOCK(); + return intr; +} + void afs_osi_Sleep(void *event) { diff --git a/src/afs/IRIX/osi_sleep.c b/src/afs/IRIX/osi_sleep.c index 9795ab48cc..5b67f27f05 100644 --- a/src/afs/IRIX/osi_sleep.c +++ b/src/afs/IRIX/osi_sleep.c @@ -15,13 +15,8 @@ #include "afsincludes.h" /* Afs-based standard headers */ #include "afs/afs_stats.h" /* afs statistics */ - - -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV; - void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle) { @@ -60,7 +55,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); code = 0; - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ @@ -154,7 +149,7 @@ afs_osi_SleepSig(void *event) return 0; } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -163,8 +158,8 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; @@ -173,7 +168,6 @@ osi_TimedSleep(char *event, afs_int32 ams, int aintok) ticks.tv_sec = ams / 1000; ticks.tv_nsec = (ams - (ticks.tv_sec * 1000)) * 1000000; - evp = afs_getevent(event); AFS_ASSERT_GLOCK(); diff --git a/src/afs/LINUX/osi_sleep.c b/src/afs/LINUX/osi_sleep.c index dd45ee3314..84882bfcb5 100644 --- a/src/afs/LINUX/osi_sleep.c +++ b/src/afs/LINUX/osi_sleep.c @@ -19,8 +19,6 @@ #include #endif -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV, dummyV; void @@ -61,7 +59,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); - code = osi_TimedSleep(&waitV, ams, 1); + code = afs_osi_TimedSleep(&waitV, ams, 1); if (code) break; if (ahandle && (ahandle->proc == (caddr_t) 0)) { @@ -247,7 +245,7 @@ afs_osi_Sleep(void *event) SIG_UNLOCK(current); } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -257,8 +255,8 @@ afs_osi_Sleep(void *event) * Returns 0 if timeout, EINTR if signalled, and EGAIN if it might * have raced. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; long ticks = (ams * HZ / 1000) + 1; diff --git a/src/afs/LINUX24/osi_sleep.c b/src/afs/LINUX24/osi_sleep.c index 93ba264f6b..c820f1e038 100644 --- a/src/afs/LINUX24/osi_sleep.c +++ b/src/afs/LINUX24/osi_sleep.c @@ -19,8 +19,6 @@ #include #endif -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV, dummyV; void @@ -61,7 +59,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); - code = osi_TimedSleep(&waitV, ams, 1); + code = afs_osi_TimedSleep(&waitV, ams, 1); if (code) break; if (ahandle && (ahandle->proc == (caddr_t) 0)) { @@ -233,7 +231,7 @@ afs_osi_Sleep(void *event) SIG_UNLOCK(current); } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -243,8 +241,8 @@ afs_osi_Sleep(void *event) * Returns 0 if timeout, EINTR if signalled, and EGAIN if it might * have raced. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; long ticks = (ams * HZ / 1000) + 1; diff --git a/src/afs/NBSD/osi_sleep.c b/src/afs/NBSD/osi_sleep.c index 71cf22541b..9dcbb7c7eb 100644 --- a/src/afs/NBSD/osi_sleep.c +++ b/src/afs/NBSD/osi_sleep.c @@ -16,12 +16,8 @@ #include "afsincludes.h" /* Afs-based standard headers */ #include "afs/afs_stats.h" /* afs statistics */ - - -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); static char waitV; - void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle) { @@ -60,7 +56,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); code = 0; - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ @@ -152,7 +148,7 @@ afs_osi_SleepSig(void *event) return 0; } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -161,8 +157,8 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; diff --git a/src/afs/OBSD/osi_sleep.c b/src/afs/OBSD/osi_sleep.c index b3628088cc..6f9c19514c 100644 --- a/src/afs/OBSD/osi_sleep.c +++ b/src/afs/OBSD/osi_sleep.c @@ -125,6 +125,30 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) return code; } +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) +{ + int code = 0; + struct afs_event *evp; + int seq, prio; + int ticks; + + evp = afs_getevent(event); + seq = evp->seq; + AFS_GUNLOCK(); + if (aintok) + prio = PCATCH | PPAUSE; + else + prio = PVFS; + ticks = (ams * afs_hz) / 1000; + code = tsleep(event, prio, "afs_osi_TimedSleep", ticks); + if (seq == evp->seq) + code = EINTR; + relevent(evp); + AFS_GLOCK(); + return code; +} + void afs_osi_Sleep(void *event) { diff --git a/src/afs/SOLARIS/osi_sleep.c b/src/afs/SOLARIS/osi_sleep.c index bf62279532..d84ff64964 100644 --- a/src/afs/SOLARIS/osi_sleep.c +++ b/src/afs/SOLARIS/osi_sleep.c @@ -15,8 +15,6 @@ #include "afsincludes.h" /* Afs-based standard headers */ #include "afs/afs_stats.h" /* afs statistics */ -static int osi_TimedSleep(char *event, afs_int32 ams, int aintok); - static char waitV; void @@ -57,7 +55,7 @@ afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) do { AFS_ASSERT_GLOCK(); code = 0; - code = osi_TimedSleep(&waitV, ams, aintok); + code = afs_osi_TimedSleep(&waitV, ams, aintok); if (code) break; /* if something happened, quit now */ @@ -159,7 +157,7 @@ afs_osi_SleepSig(void *event) return code; } -/* osi_TimedSleep +/* afs_osi_TimedSleep * * Arguments: * event - event to sleep on @@ -168,8 +166,8 @@ afs_osi_SleepSig(void *event) * * Returns 0 if timeout and EINTR if signalled. */ -static int -osi_TimedSleep(char *event, afs_int32 ams, int aintok) +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) { int code = 0; struct afs_event *evp; diff --git a/src/afs/UKERNEL/afs_usrops.c b/src/afs/UKERNEL/afs_usrops.c index fe4e2ad509..1480c4252d 100644 --- a/src/afs/UKERNEL/afs_usrops.c +++ b/src/afs/UKERNEL/afs_usrops.c @@ -533,6 +533,12 @@ afs_osi_Wakeup(void *x) return 0; } +int +afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok) +{ + return afs_osi_Wait(ams, event, aintok); +} + int afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok) { diff --git a/src/afs/afs_prototypes.h b/src/afs/afs_prototypes.h index fe9a2cc68c..39d52979b2 100644 --- a/src/afs/afs_prototypes.h +++ b/src/afs/afs_prototypes.h @@ -636,6 +636,7 @@ extern void afs_osi_InitWaitHandle(struct afs_osi_WaitHandle *achandle); extern void afs_osi_CancelWait(struct afs_osi_WaitHandle *achandle); extern int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok); +extern int afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok); #ifndef afs_osi_Wakeup extern int afs_osi_Wakeup(void *event); #endif