From: Nickolai Zeldovich Date: Fri, 1 Feb 2002 20:29:59 +0000 (+0000) Subject: First pass at better signal handling: X-Git-Tag: openafs-devel-1_3_0~18 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=7b8d569f42d9906ef0ed0b11f66962e00ad04cc6 First pass at better signal handling: -- Add afs_osi_SleepSig, which returns EINTR when interrupted by signal. -- Similar CV_WAIT_SIG for Rx code. -- Implement afs_osi_SleepSig and CV_WAIT_SIG for Linux, Solaris. -- Use afs_osi_SleepSig in afs_{UFS,Mem}Read, allowing user to interrupt an AFS read if it's being handled by background daemon. -- Balance the number of open & close braces in CV_TIMEDWAIT macros, even though noone uses them. -- Untangle parts of the macro forest by moving some of the Rx CV code into rx_kmutex.c. --- diff --git a/src/afs/AIX/osi_sleep.c b/src/afs/AIX/osi_sleep.c index 13eb885..bee54e6 100644 --- a/src/afs/AIX/osi_sleep.c +++ b/src/afs/AIX/osi_sleep.c @@ -148,6 +148,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/DARWIN/osi_sleep.c b/src/afs/DARWIN/osi_sleep.c index ceac98d..83bb904 100644 --- a/src/afs/DARWIN/osi_sleep.c +++ b/src/afs/DARWIN/osi_sleep.c @@ -144,6 +144,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/DUX/osi_sleep.c b/src/afs/DUX/osi_sleep.c index 94c70a9..3c38401 100644 --- a/src/afs/DUX/osi_sleep.c +++ b/src/afs/DUX/osi_sleep.c @@ -141,6 +141,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/FBSD/osi_sleep.c b/src/afs/FBSD/osi_sleep.c index 11f26ed..1b018a5 100644 --- a/src/afs/FBSD/osi_sleep.c +++ b/src/afs/FBSD/osi_sleep.c @@ -142,6 +142,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/HPUX/osi_sleep.c b/src/afs/HPUX/osi_sleep.c index 248c858..f586fe7 100644 --- a/src/afs/HPUX/osi_sleep.c +++ b/src/afs/HPUX/osi_sleep.c @@ -106,3 +106,9 @@ int afs_osi_Wait(afs_int32 ams, struct afs_osi_WaitHandle *ahandle, int aintok) } while (osi_Time() < endTime); return code; } + +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} diff --git a/src/afs/IRIX/osi_sleep.c b/src/afs/IRIX/osi_sleep.c index 7437974..a4eb686 100644 --- a/src/afs/IRIX/osi_sleep.c +++ b/src/afs/IRIX/osi_sleep.c @@ -143,6 +143,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/LINUX/osi_sleep.c b/src/afs/LINUX/osi_sleep.c index b5b5e96..cf30788 100644 --- a/src/afs/LINUX/osi_sleep.c +++ b/src/afs/LINUX/osi_sleep.c @@ -203,12 +203,15 @@ static void afs_addevent(char *event) /* Release the specified event */ #define relevent(evp) ((evp)->refcount--) -/* afs_osi_Sleep -- waits for an event to be notified. */ - -void afs_osi_Sleep(char *event) +/* afs_osi_SleepSig + * + * Waits for an event to be notified, returning early if a signal + * is received. Returns EINTR if signaled, and 0 otherwise. + */ +int afs_osi_SleepSig(char *event) { struct afs_event *evp; - int seq; + int seq, retval; evp = afs_getevent(event); if (!evp) { @@ -217,31 +220,43 @@ void afs_osi_Sleep(char *event) * allocator then return immediately. We'll find the new event next * time around without dropping the GLOCK. */ afs_addevent(event); - return; + return 0; } seq = evp->seq; + retval = 0; while (seq == evp->seq) { - sigset_t saved_set; - AFS_ASSERT_GLOCK(); AFS_GUNLOCK(); - spin_lock_irq(¤t->sigmask_lock); - saved_set = current->blocked; - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - interruptible_sleep_on(&evp->cond); - - spin_lock_irq(¤t->sigmask_lock); - current->blocked = saved_set; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); AFS_GLOCK(); + if (signal_pending(current)) { + retval = EINTR; + break; + } } relevent(evp); + return retval; +} + +/* afs_osi_Sleep -- waits for an event to be notified, ignoring signals. */ +void afs_osi_Sleep(char *event) +{ + sigset_t saved_set; + + spin_lock_irq(¤t->sigmask_lock); + saved_set = current->blocked; + sigfillset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + afs_osi_SleepSig(event); + + spin_lock_irq(¤t->sigmask_lock); + current->blocked = saved_set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); } /* osi_TimedSleep diff --git a/src/afs/NBSD/osi_sleep.c b/src/afs/NBSD/osi_sleep.c index 11f26ed..1b018a5 100644 --- a/src/afs/NBSD/osi_sleep.c +++ b/src/afs/NBSD/osi_sleep.c @@ -142,6 +142,12 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + afs_osi_Sleep(event); + return 0; +} + /* osi_TimedSleep * * Arguments: diff --git a/src/afs/SOLARIS/osi_sleep.c b/src/afs/SOLARIS/osi_sleep.c index 9ae0b09..97b95d4 100644 --- a/src/afs/SOLARIS/osi_sleep.c +++ b/src/afs/SOLARIS/osi_sleep.c @@ -136,6 +136,24 @@ void afs_osi_Sleep(char *event) relevent(evp); } +int afs_osi_SleepSig(char *event) +{ + struct afs_event *evp; + int seq, code = 0; + + evp = afs_getevent(event); + seq = evp->seq; + while (seq == evp->seq) { + AFS_ASSERT_GLOCK(); + if (cv_wait_sig(&evp->cond, &afs_global_lock) == 0) { + code = EINTR; + break; + } + } + relevent(evp); + return code; +} + /* osi_TimedSleep * * Arguments: @@ -158,7 +176,7 @@ static int osi_TimedSleep(char *event, afs_int32 ams, int aintok) AFS_ASSERT_GLOCK(); if (aintok) { - if (cv_timedwait_sig(&evp->cond, &afs_global_lock, ticks) == -1) + if (cv_timedwait_sig(&evp->cond, &afs_global_lock, ticks) == 0) code = EINTR; } else { cv_timedwait(&evp->cond, &afs_global_lock, ticks); diff --git a/src/afs/UKERNEL/afs_usrops.c b/src/afs/UKERNEL/afs_usrops.c index c64484d..57fcff0 100644 --- a/src/afs/UKERNEL/afs_usrops.c +++ b/src/afs/UKERNEL/afs_usrops.c @@ -487,6 +487,13 @@ caddr_t x; } } +int afs_osi_SleepSig(x) + caddr_t x; +{ + afs_osi_Sleep(x); + return 0; +} + int afs_osi_Wakeup(x) caddr_t x; { diff --git a/src/afs/VNOPS/afs_vnop_read.c b/src/afs/VNOPS/afs_vnop_read.c index 8fa980b..a0222f4 100644 --- a/src/afs/VNOPS/afs_vnop_read.c +++ b/src/afs/VNOPS/afs_vnop_read.c @@ -192,24 +192,33 @@ tagain: ConvertWToSLock(&tdc->mflock); /* don't use bp pointer! */ } + code = 0; ConvertSToRLock(&tdc->mflock); - while (tdc->mflags & DFFetchReq) { + while (!code && tdc->mflags & DFFetchReq) { /* don't need waiting flag on this one */ ReleaseReadLock(&tdc->mflock); ReleaseReadLock(&tdc->lock); ReleaseReadLock(&avc->lock); - afs_osi_Sleep(&tdc->validPos); + code = afs_osi_SleepSig(&tdc->validPos); ObtainReadLock(&avc->lock); ObtainReadLock(&tdc->lock); ObtainReadLock(&tdc->mflock); } ReleaseReadLock(&tdc->mflock); + if (code) { + error = code; + break; + } } } /* now data may have started flowing in (if DFFetching is on). If - * data is now streaming in, then wait for some interesting stuff. */ - while ((tdc->dflags & DFFetching) && tdc->validPos <= filePos) { - /* too early: wait for DFFetching flag to vanish, or data to appear */ + * data is now streaming in, then wait for some interesting stuff. + */ + code = 0; + while (!code && (tdc->dflags & DFFetching) && + tdc->validPos <= filePos) { + /* too early: wait for DFFetching flag to vanish, + * or data to appear */ afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32, __LINE__, @@ -217,10 +226,14 @@ tagain: ICL_TYPE_INT32, tdc->dflags); ReleaseReadLock(&tdc->lock); ReleaseReadLock(&avc->lock); - afs_osi_Sleep(&tdc->validPos); + code = afs_osi_SleepSig(&tdc->validPos); ObtainReadLock(&avc->lock); ObtainReadLock(&tdc->lock); } + if (code) { + error = code; + break; + } /* fetching flag gone, data is here, or we never tried (BBusy for instance) */ if (tdc->dflags & DFFetching) { /* still fetching, some new data is here: compute length and offset */ @@ -711,24 +724,33 @@ tagain: } ConvertWToSLock(&tdc->mflock); } + code = 0; ConvertSToRLock(&tdc->mflock); - while (tdc->mflags & DFFetchReq) { + while (!code && tdc->mflags & DFFetchReq) { /* don't need waiting flag on this one */ ReleaseReadLock(&tdc->mflock); ReleaseReadLock(&tdc->lock); ReleaseReadLock(&avc->lock); - afs_osi_Sleep(&tdc->validPos); + code = afs_osi_SleepSig(&tdc->validPos); ObtainReadLock(&avc->lock); ObtainReadLock(&tdc->lock); ObtainReadLock(&tdc->mflock); } ReleaseReadLock(&tdc->mflock); + if (code) { + error = code; + break; + } } } /* now data may have started flowing in (if DFFetching is on). If - * data is now streaming in, then wait for some interesting stuff. */ - while ((tdc->dflags & DFFetching) && tdc->validPos <= filePos) { - /* too early: wait for DFFetching flag to vanish, or data to appear */ + * data is now streaming in, then wait for some interesting stuff. + */ + code = 0; + while (!code && (tdc->dflags & DFFetching) && + tdc->validPos <= filePos) { + /* too early: wait for DFFetching flag to vanish, + * or data to appear */ afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING, __FILE__, ICL_TYPE_INT32, __LINE__, @@ -736,18 +758,25 @@ tagain: ICL_TYPE_INT32, tdc->dflags); ReleaseReadLock(&tdc->lock); ReleaseReadLock(&avc->lock); - afs_osi_Sleep(&tdc->validPos); + code = afs_osi_SleepSig(&tdc->validPos); ObtainReadLock(&avc->lock); ObtainReadLock(&tdc->lock); } - /* fetching flag gone, data is here, or we never tried (BBusy for instance) */ + if (code) { + error = code; + break; + } + /* fetching flag gone, data is here, or we never tried + * (BBusy for instance) */ if (tdc->dflags & DFFetching) { - /* still fetching, some new data is here: compute length and offset */ + /* still fetching, some new data is here: + * compute length and offset */ offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk); len = tdc->validPos - filePos; } else { - /* no longer fetching, verify data version (avoid new GetDCache call) */ + /* no longer fetching, verify data version (avoid new + * GetDCache call) */ if (hsame(avc->m.DataVersion, tdc->f.versionNo)) { offset = filePos - AFS_CHUNKTOBASE(tdc->f.chunk); len = tdc->f.chunkBytes - offset; diff --git a/src/libafs/Makefile.common.in b/src/libafs/Makefile.common.in index f56c303..3ee5551 100644 --- a/src/libafs/Makefile.common.in +++ b/src/libafs/Makefile.common.in @@ -99,6 +99,7 @@ AFSAOBJS = \ rx_clock.o \ rx_event.o \ rx_globals.o \ + rx_kmutex.o \ rx_knet.o \ rx_kcommon.o \ rx_misc.o \ @@ -313,6 +314,8 @@ Kvldbint.xdr.o: $(AFSINT)/Kvldbint.xdr.c $(CRULE1) -DAFS_UUID_XG afs_main.o: $(AFS)/afs_main.c $(CRULE1) +rx_kmutex.o: $(RX)/rx_kmutex.c + $(CRULE1) rx_knet.o: $(RX)/rx_knet.c $(CRULE1) rx_kcommon.o: $(RX)/rx_kcommon.c diff --git a/src/libuafs/Makefile.common.in b/src/libuafs/Makefile.common.in index bf1043f..805dd24 100644 --- a/src/libuafs/Makefile.common.in +++ b/src/libuafs/Makefile.common.in @@ -113,6 +113,7 @@ UAFSOBJ = \ $(UOBJ)/rx_clock.o \ $(UOBJ)/rx_event.o \ $(UOBJ)/rx_globals.o \ + $(UOBJ)/rx_kmutex.o \ $(UOBJ)/rx_knet.o \ $(UOBJ)/rx_kcommon.o \ $(UOBJ)/rx_misc.o \ @@ -230,6 +231,7 @@ AFSWEBOBJ = \ $(WEBOBJ)/rx_clock.o \ $(WEBOBJ)/rx_event.o \ $(WEBOBJ)/rx_globals.o \ + $(WEBOBJ)/rx_kmutex.o \ $(WEBOBJ)/rx_knet.o \ $(WEBOBJ)/rx_kcommon.o \ $(WEBOBJ)/rx_misc.o \ @@ -347,6 +349,7 @@ AFSWEBOBJKRB = \ $(WEBOBJ)/rx_clock.o \ $(WEBOBJ)/rx_event.o \ $(WEBOBJ)/rx_globals.o \ + $(WEBOBJ)/rx_kmutex.o \ $(WEBOBJ)/rx_knet.o \ $(WEBOBJ)/rx_kcommon.o \ $(WEBOBJ)/rx_misc.o \ @@ -564,6 +567,8 @@ $(UOBJ)/Kvldbint.xdr.o: $(AFSINT)/Kvldbint.xdr.c $(CRULE1) $(UOBJ)/afs_main.o: $(AFS)/afs_main.c $(CRULE1) +$(UOBJ)/rx_kmutex.o: $(RX)/rx_kmutex.c + $(CRULE1) $(UOBJ)/rx_knet.o: $(RX)/rx_knet.c $(CRULE1) $(UOBJ)/rx_kcommon.o: $(RX)/rx_kcommon.c @@ -807,6 +812,8 @@ $(WEBOBJ)/Kvldbint.xdr.o: $(AFSINT)/Kvldbint.xdr.c $(CRULE2) $(WEBOBJ)/afs_main.o: $(AFS)/afs_main.c $(CRULE2) +$(WEBOBJ)/rx_kmutex.o: $(RX)/rx_kmutex.c + $(CRULE2) $(WEBOBJ)/rx_knet.o: $(RX)/rx_knet.c $(CRULE2) $(WEBOBJ)/rx_kcommon.o: $(RX)/rx_kcommon.c diff --git a/src/rx/AIX/rx_kmutex.c b/src/rx/AIX/rx_kmutex.c new file mode 100644 index 0000000..8f344f3 --- /dev/null +++ b/src/rx/AIX/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * AIX 4.x implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/DARWIN/rx_kmutex.c b/src/rx/DARWIN/rx_kmutex.c new file mode 100644 index 0000000..7aa430c --- /dev/null +++ b/src/rx/DARWIN/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * MACOS implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/DARWIN/rx_kmutex.h b/src/rx/DARWIN/rx_kmutex.h index 530b3ce..98fecf6 100644 --- a/src/rx/DARWIN/rx_kmutex.h +++ b/src/rx/DARWIN/rx_kmutex.h @@ -54,6 +54,7 @@ thread_block(0); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ + } #define CV_SIGNAL(cv) thread_wakeup_one((event_t)(cv)) #define CV_BROADCAST(cv) thread_wakeup((event_t)(cv)) diff --git a/src/rx/DUX/rx_kmutex.c b/src/rx/DUX/rx_kmutex.c new file mode 100644 index 0000000..e269509 --- /dev/null +++ b/src/rx/DUX/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * DUX implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/DUX/rx_kmutex.h b/src/rx/DUX/rx_kmutex.h index 683360b..791b77c 100644 --- a/src/rx/DUX/rx_kmutex.h +++ b/src/rx/DUX/rx_kmutex.h @@ -53,6 +53,7 @@ thread_block(); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ + } #define CV_SIGNAL(cv) thread_wakeup_one((vm_offset_t)(cv)) #define CV_BROADCAST(cv) thread_wakeup((vm_offset_t)(cv)) diff --git a/src/rx/FBSD/rx_kmutex.c b/src/rx/FBSD/rx_kmutex.c new file mode 100644 index 0000000..0d756f4 --- /dev/null +++ b/src/rx/FBSD/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * FreeBSD implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/FBSD/rx_kmutex.h b/src/rx/FBSD/rx_kmutex.h index 924d8c2..771d2fc 100644 --- a/src/rx/FBSD/rx_kmutex.h +++ b/src/rx/FBSD/rx_kmutex.h @@ -45,6 +45,7 @@ thread_block(); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ + } #define CV_SIGNAL(cv) thread_wakeup_one((vm_offset_t)(cv)) #define CV_BROADCAST(cv) thread_wakeup((vm_offset_t)(cv)) diff --git a/src/rx/HPUX/rx_kmutex.c b/src/rx/HPUX/rx_kmutex.c new file mode 100644 index 0000000..2d5e40c --- /dev/null +++ b/src/rx/HPUX/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * HPUX implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/IRIX/rx_kmutex.c b/src/rx/IRIX/rx_kmutex.c new file mode 100644 index 0000000..31b6296 --- /dev/null +++ b/src/rx/IRIX/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * IRIX implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/LINUX/rx_kmutex.c b/src/rx/LINUX/rx_kmutex.c new file mode 100644 index 0000000..3ee6926 --- /dev/null +++ b/src/rx/LINUX/rx_kmutex.c @@ -0,0 +1,120 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * Linux implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +#include "../rx/rx_kcommon.h" +#include "../rx/rx_kmutex.h" +#include "../rx/rx_kernel.h" + +#ifdef CONFIG_SMP + +void afs_mutex_init(afs_kmutex_t *l) +{ +#if defined(AFS_LINUX24_ENV) + init_MUTEX(&l->sem); +#else + l->sem = MUTEX; +#endif + l->owner = 0; +} + +void afs_mutex_enter(afs_kmutex_t *l) +{ + down(&l->sem); + if (l->owner) + osi_Panic("mutex_enter: 0x%x held by %d", l, l->owner); + l->owner = current->pid; +} + +int afs_mutex_tryenter(afs_kmutex_t *l) +{ + if (down_trylock(&l->sem)) + return 0; + l->owner = current->pid; + return 1; +} + +void afs_mutex_exit(afs_kmutex_t *l) +{ + if (l->owner != current->pid) + osi_Panic("mutex_exit: 0x%x held by %d", + l, l->owner); + l->owner = 0; + up(&l->sem); +} + +/* + * CV_WAIT and CV_TIMEDWAIT rely on the fact that the Linux kernel has + * a global lock. Thus we can safely drop our locks before calling the + * kernel sleep services. + */ +int afs_cv_wait(afs_kcondvar_t *cv, afs_kmutex_t *l, int sigok) +{ + int isAFSGlocked = ISAFS_GLOCK(); + sigset_t saved_set; + + if (isAFSGlocked) AFS_GUNLOCK(); + MUTEX_EXIT(l); + + if (!sigok) { + spin_lock_irq(¤t->sigmask_lock); + saved_set = current->blocked; + sigfillset(¤t->blocked); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } + +#if defined(AFS_LINUX24_ENV) + interruptible_sleep_on((wait_queue_head_t *)cv); +#else + interruptible_sleep_on((struct wait_queue**)cv); +#endif + + if (!sigok) { + spin_lock_irq(¤t->sigmask_lock); + current->blocked = saved_set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } + + MUTEX_ENTER(l); + if (isAFSGlocked) AFS_GLOCK(); + + return (sigok && signal_pending(current)) ? EINTR : 0; +} + +void afs_cv_timedwait(afs_kcondvar_t *cv, afs_kmutex_t *l, int waittime) +{ + int isAFSGlocked = ISAFS_GLOCK(); + long t = waittime * HZ / 1000; + + if (isAFSGlocked) AFS_GUNLOCK(); + MUTEX_EXIT(l); + +#if defined(AFS_LINUX24_ENV) + t = interruptible_sleep_on_timeout((wait_queue_head_t *)cv, t); +#else + t = interruptible_sleep_on_timeout((struct wait_queue**)cv, t); +#endif + + MUTEX_ENTER(l); + if (isAFSGlocked) AFS_GLOCK(); +} + +#endif diff --git a/src/rx/LINUX/rx_kmutex.h b/src/rx/LINUX/rx_kmutex.h index 8b49213..d8f5499 100644 --- a/src/rx/LINUX/rx_kmutex.h +++ b/src/rx/LINUX/rx_kmutex.h @@ -50,128 +50,28 @@ static inline int MUTEX_ISMINE(afs_kmutex_t *l) return l->owner == current->pid; } - -static inline void afs_mutex_init(afs_kmutex_t *l) -{ -#if defined(AFS_LINUX24_ENV) - init_MUTEX(&l->sem); -#else - l->sem = MUTEX; -#endif - l->owner = 0; -} -#define MUTEX_INIT(a,b,c,d) afs_mutex_init(a) - +#define MUTEX_INIT(a,b,c,d) afs_mutex_init(a) #define MUTEX_DESTROY(a) - -static inline void MUTEX_ENTER(afs_kmutex_t *l) -{ - down(&l->sem); - if (l->owner) - osi_Panic("mutex_enter: 0x%x held by %d", l, l->owner); - l->owner = current->pid; -} - -/* And how to do a good tryenter? */ -static inline int MUTEX_TRYENTER(afs_kmutex_t *l) -{ - if (!l->owner) { - MUTEX_ENTER(l); - return 1; - } - else - return 0; -} - -static inline void MUTEX_EXIT(afs_kmutex_t *l) -{ - if (l->owner != current->pid) - osi_Panic("mutex_exit: 0x%x held by %d", - l, l->owner); - l->owner = 0; - up(&l->sem); -} +#define MUTEX_ENTER afs_mutex_enter +#define MUTEX_TRYENTER afs_mutex_tryenter +#define MUTEX_EXIT afs_mutex_exit #if defined(AFS_LINUX24_ENV) -#define CV_INIT(cv,b,c,d) init_waitqueue_head((wait_queue_head_t *)(cv)) +#define CV_INIT(cv,b,c,d) init_waitqueue_head((wait_queue_head_t *)(cv)) #else -#define CV_INIT(cv,b,c,d) init_waitqueue((struct wait_queue**)(cv)) +#define CV_INIT(cv,b,c,d) init_waitqueue((struct wait_queue**)(cv)) #endif #define CV_DESTROY(cv) - -/* CV_WAIT and CV_TIMEDWAIT rely on the fact that the Linux kernel has - * a global lock. Thus we can safely drop our locks before calling the - * kernel sleep services. - */ -static inline int CV_WAIT(afs_kcondvar_t *cv, afs_kmutex_t *l) -{ - int isAFSGlocked = ISAFS_GLOCK(); - sigset_t saved_set; - - if (isAFSGlocked) AFS_GUNLOCK(); - MUTEX_EXIT(l); - - spin_lock_irq(¤t->sigmask_lock); - saved_set = current->blocked; - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - -#if defined(AFS_LINUX24_ENV) - interruptible_sleep_on((wait_queue_head_t *)cv); -#else - interruptible_sleep_on((struct wait_queue**)cv); -#endif - - spin_lock_irq(¤t->sigmask_lock); - current->blocked = saved_set; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - MUTEX_ENTER(l); - if (isAFSGlocked) AFS_GLOCK(); - - return 0; -} - -static inline int CV_TIMEDWAIT(afs_kcondvar_t *cv, afs_kmutex_t *l, int waittime) -{ - int isAFSGlocked = ISAFS_GLOCK(); - long t = waittime * HZ / 1000; - sigset_t saved_set; - - if (isAFSGlocked) AFS_GUNLOCK(); - MUTEX_EXIT(l); - - spin_lock_irq(¤t->sigmask_lock); - saved_set = current->blocked; - sigfillset(¤t->blocked); - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - -#if defined(AFS_LINUX24_ENV) - t = interruptible_sleep_on_timeout((wait_queue_head_t *)cv, t); -#else - t = interruptible_sleep_on_timeout((struct wait_queue**)cv, t); -#endif - - spin_lock_irq(¤t->sigmask_lock); - current->blocked = saved_set; - recalc_sigpending(current); - spin_unlock_irq(¤t->sigmask_lock); - - MUTEX_ENTER(l); - if (isAFSGlocked) AFS_GLOCK(); - - return 0; -} +#define CV_WAIT_SIG(cv, m) afs_cv_wait(cv, m, 1) +#define CV_WAIT(cv, m) afs_cv_wait(cv, m, 0) +#define CV_TIMEDWAIT afs_cv_timedwait #if defined(AFS_LINUX24_ENV) -#define CV_SIGNAL(cv) wake_up((wait_queue_head_t *)cv) -#define CV_BROADCAST(cv) wake_up((wait_queue_head_t *)cv) +#define CV_SIGNAL(cv) wake_up((wait_queue_head_t *)cv) +#define CV_BROADCAST(cv) wake_up((wait_queue_head_t *)cv) #else -#define CV_SIGNAL(cv) wake_up((struct wait_queue**)cv) -#define CV_BROADCAST(cv) wake_up((struct wait_queue**)cv) +#define CV_SIGNAL(cv) wake_up((struct wait_queue**)cv) +#define CV_BROADCAST(cv) wake_up((struct wait_queue**)cv) #endif #else diff --git a/src/rx/Makefile.in b/src/rx/Makefile.in index d7fd900..dd59dcd 100644 --- a/src/rx/Makefile.in +++ b/src/rx/Makefile.in @@ -186,6 +186,7 @@ kinstall: \ ${KERNELDIR}/rx/rx_kcommon.c \ ${KERNELDIR}/rx/rx_kcommon.h \ ${KERNELDIR}/rx/rx_kernel.h \ + ${KERNELDIR}/rx/rx_kmutex.c \ ${KERNELDIR}/rx/rx_kmutex.h \ ${KERNELDIR}/rx/rx_knet.c \ ${KERNELDIR}/rx/rx_misc.c \ @@ -221,6 +222,7 @@ ukinstall: \ ${UKERNELDIR}/rx/rx_kcommon.c \ ${UKERNELDIR}/rx/rx_kcommon.h \ ${UKERNELDIR}/rx/rx_kernel.h \ + ${UKERNELDIR}/rx/rx_kmutex.c \ ${UKERNELDIR}/rx/rx_kmutex.h \ ${UKERNELDIR}/rx/rx_knet.c \ ${UKERNELDIR}/rx/rx_misc.c \ @@ -284,6 +286,9 @@ ${KERNELDIR}/rx/rx_kcommon.h: rx_kcommon.h ${KERNELDIR}/rx/rx_kernel.h: rx_kernel.h ${INSTALL} $? $@ +${KERNELDIR}/rx/rx_kmutex.c: ${MKAFS_OSTYPE}/rx_kmutex.c + ${INSTALL} $? $@ + ${KERNELDIR}/rx/rx_kmutex.h: ${MKAFS_OSTYPE}/rx_kmutex.h ${INSTALL} $? $@ @@ -380,6 +385,9 @@ ${UKERNELDIR}/rx/rx_kcommon.h: UKERNEL/rx_kcommon.h ${UKERNELDIR}/rx/rx_kernel.h: rx_kernel.h ${INSTALL} $? $@ +${UKERNELDIR}/rx/rx_kmutex.c: UKERNEL/rx_kmutex.c + ${INSTALL} $? $@ + ${UKERNELDIR}/rx/rx_kmutex.h: UKERNEL/rx_kmutex.h ${INSTALL} $? $@ diff --git a/src/rx/NBSD/rx_kmutex.c b/src/rx/NBSD/rx_kmutex.c new file mode 100644 index 0000000..c4b5782 --- /dev/null +++ b/src/rx/NBSD/rx_kmutex.c @@ -0,0 +1,18 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * NetBSD implementation. + */ + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/NBSD/rx_kmutex.h b/src/rx/NBSD/rx_kmutex.h index 530b3ce..98fecf6 100644 --- a/src/rx/NBSD/rx_kmutex.h +++ b/src/rx/NBSD/rx_kmutex.h @@ -54,6 +54,7 @@ thread_block(0); \ if (isGlockOwner) AFS_GLOCK(); \ MUTEX_ENTER(lck); \ + } #define CV_SIGNAL(cv) thread_wakeup_one((event_t)(cv)) #define CV_BROADCAST(cv) thread_wakeup((event_t)(cv)) diff --git a/src/rx/SOLARIS/rx_kmutex.c b/src/rx/SOLARIS/rx_kmutex.c new file mode 100644 index 0000000..38e6798 --- /dev/null +++ b/src/rx/SOLARIS/rx_kmutex.c @@ -0,0 +1,103 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * Solaris implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +#if defined(AFS_SUN5_ENV) && defined(KERNEL) + +#include "../rx/rx_kmutex.h" + +#include +#include +#include +#include + +#ifdef RX_LOCKS_DB +int afs_cv_wait(cv, m, sigok, fileid, line) + int fileid; + int line; +#else +int afs_cv_wait(cv, m, sigok) +#endif + afs_kcondvar_t *cv; + afs_kmutex_t *m; + int sigok; +{ + int haveGlock = ISAFS_GLOCK(); + int retval = 0; + + if (haveGlock) + AFS_GUNLOCK(); +#ifdef RX_LOCKS_DB + rxdb_droplock(m, osi_ThreadUnique(), fileid, line); +#endif + if (sigok) { + if (cv_wait_sig(cv, m) == 0) + retval = EINTR; + } else { + cv_wait(cv, m); + } +#ifdef RX_LOCKS_DB + rxdb_grablock(m, osi_ThreadUnique(), fileid, line); +#endif + if (haveGlock) { + MUTEX_EXIT(m); + AFS_GLOCK(); + MUTEX_ENTER(m); + } + return retval; +} + +#ifdef RX_LOCKS_DB +int afs_cv_timedwait(cv, m, t, sigok, fileid, line) + int fileid; + int line; +#else +int afs_cv_timedwait(cv, m, t, sigok) +#endif + afs_kcondvar_t *cv; + afs_kmutex_t *m; + clock_t t; + int sigok; +{ + int haveGlock = ISAFS_GLOCK(); + int retval = 0; + + if (haveGlock) + AFS_GUNLOCK(); +#ifdef RX_LOCKS_DB + rxdb_droplock(m, osi_ThreadUnique(), fileid, line); +#endif + if (sigok) { + if (cv_timedwait_sig(cv, m, t) == 0) + retval = EINTR; + } else { + cv_timedwait(cv, m, t); + } +#ifdef RX_LOCKS_DB + rxdb_grablock(m, osi_ThreadUnique(), fileid, line); +#endif + if (haveGlock) { + MUTEX_EXIT(m); + AFS_GLOCK(); + MUTEX_ENTER(m); + } + return retval; +} + +#endif /* SUN5 && KERNEL */ diff --git a/src/rx/SOLARIS/rx_kmutex.h b/src/rx/SOLARIS/rx_kmutex.h index ca0f17c..eaf324a 100644 --- a/src/rx/SOLARIS/rx_kmutex.h +++ b/src/rx/SOLARIS/rx_kmutex.h @@ -57,35 +57,11 @@ extern void osirx_AssertMine(afs_kmutex_t *lockaddr, char *msg); mutex_exit(a); \ } while(0) -#define CV_WAIT(_cv, _lck) \ - do { \ - int haveGlock = ISAFS_GLOCK(); \ - if (haveGlock) \ - AFS_GUNLOCK(); \ - rxdb_droplock((_lck), osi_ThreadUnique(), rxdb_fileID, __LINE__); \ - cv_wait(_cv, _lck); \ - rxdb_grablock((_lck), osi_ThreadUnique(), rxdb_fileID, __LINE__); \ - if (haveGlock) { \ - MUTEX_EXIT(_lck); \ - AFS_GLOCK(); \ - MUTEX_ENTER(_lck); \ - } \ - } while (0) - -#define CV_TIMEDWAIT(_cv,_lck,_t) \ - do { \ - int haveGlock = ISAFS_GLOCK(); \ - if (haveGlock) \ - AFS_GUNLOCK(); \ - rxdb_droplock((_lck), osi_ThreadUnique(), rxdb_fileID, __LINE__); \ - cv_timedwait(_cv, _lck, t); \ - rxdb_grablock((_lck), osi_ThreadUnique(), rxdb_fileID, __LINE__); \ - if (haveGlock) { \ - MUTEX_EXIT(_lck); \ - AFS_GLOCK(); \ - MUTEX_ENTER(_lck); \ - } \ - } while (0) +#define CV_WAIT_SIG(cv, m) afs_cv_wait(cv, m, 1, rxdb_fileID, __LINE__) +#define CV_WAIT(cv, m) afs_cv_wait(cv, m, 0, rxdb_fileID, __LINE__) + +#define CV_TIMEDWAIT(cv, m, t) \ + afs_cv_timedwait(cv, lck, t, 0, rxdb_fileID, __LINE__) #else /* RX_LOCKS_DB */ @@ -93,31 +69,10 @@ extern void osirx_AssertMine(afs_kmutex_t *lockaddr, char *msg); #define MUTEX_TRYENTER(a) mutex_tryenter(a) #define MUTEX_EXIT(a) mutex_exit(a) -#define CV_WAIT(_cv, _lck) \ - do { \ - int haveGlock = ISAFS_GLOCK(); \ - if (haveGlock) \ - AFS_GUNLOCK(); \ - cv_wait(_cv, _lck); \ - if (haveGlock) { \ - MUTEX_EXIT(_lck); \ - AFS_GLOCK(); \ - MUTEX_ENTER(_lck); \ - } \ - } while (0) - -#define CV_TIMEDWAIT(_cv,_lck,_t) \ - do { \ - int haveGlock = ISAFS_GLOCK(); \ - if (haveGlock) \ - AFS_GUNLOCK(); \ - cv_timedwait(_cv, _lck, t); \ - if (haveGlock) { \ - MUTEX_EXIT(_lck); \ - AFS_GLOCK(); \ - MUTEX_ENTER(_lck); \ - } \ - } while (0) +#define CV_WAIT_SIG(cv, m) afs_cv_wait(cv, m, 1) +#define CV_WAIT(cv, m) afs_cv_wait(cv, m, 0) + +#define CV_TIMEDWAIT(cv, m, t) afs_cv_timedwait(cv, m, t, 0) #endif /* RX_LOCKS_DB */ diff --git a/src/rx/UKERNEL/rx_kmutex.c b/src/rx/UKERNEL/rx_kmutex.c new file mode 100644 index 0000000..6127dce --- /dev/null +++ b/src/rx/UKERNEL/rx_kmutex.c @@ -0,0 +1,23 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +/* + * rx_kmutex.c - mutex and condition variable macros for kernel environment. + * + * UKERNEL implementation. + */ + +#include +#include "../afs/param.h" + +RCSID("$Header$"); + +/* + * Currently everything is implemented in rx_kmutex.h + */ diff --git a/src/rx/UKERNEL/rx_kmutex.h b/src/rx/UKERNEL/rx_kmutex.h index 170e8e6..4247e6e 100644 --- a/src/rx/UKERNEL/rx_kmutex.h +++ b/src/rx/UKERNEL/rx_kmutex.h @@ -10,7 +10,7 @@ /* * rx_kmutex.h - mutex and condition variable macros for kernel environment. * - * Solaris implementation. + * User-space implementation. */ #ifndef _RX_KMUTEX_H_