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 <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Derrick Brashear 2010-02-04 03:22:15 -05:00
parent 01d8b61c7f
commit 6c628445eb
12 changed files with 161 additions and 66 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
}

View File

@ -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)
{

View File

@ -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();

View File

@ -19,8 +19,6 @@
#include <linux/freezer.h>
#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;

View File

@ -19,8 +19,6 @@
#include <linux/freezer.h>
#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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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)
{

View File

@ -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