Add cv_wait_interruptible() function.
This is a minor extension to the condition variable API to allow for reasonable signal handling on Linux. The cv_wait() function by definition must wait unconditionally for cv_signal()/cv_broadcast() before waking it. This makes it impossible to woken by a signal such as SIGTERM. The cv_wait_interruptible() function was added to handle this case. It behaves identically to cv_wait() with the exception that it waits interruptibly allowing a signal to wake it up. This means you do need to be careful and check issig() after waking.
This commit is contained in:
parent
97f8f6d789
commit
f752b46eb3
|
@ -57,8 +57,8 @@ typedef enum { CV_DEFAULT=0, CV_DRIVER } kcv_type_t;
|
||||||
extern void __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg);
|
extern void __cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg);
|
||||||
extern void __cv_destroy(kcondvar_t *cvp);
|
extern void __cv_destroy(kcondvar_t *cvp);
|
||||||
extern void __cv_wait(kcondvar_t *cvp, kmutex_t *mp);
|
extern void __cv_wait(kcondvar_t *cvp, kmutex_t *mp);
|
||||||
extern clock_t __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp,
|
extern void __cv_wait_interruptible(kcondvar_t *cvp, kmutex_t *mp);
|
||||||
clock_t expire_time);
|
extern clock_t __cv_timedwait(kcondvar_t *cvp, kmutex_t *mp, clock_t exp_time);
|
||||||
extern void __cv_signal(kcondvar_t *cvp);
|
extern void __cv_signal(kcondvar_t *cvp);
|
||||||
extern void __cv_broadcast(kcondvar_t *cvp);
|
extern void __cv_broadcast(kcondvar_t *cvp);
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ extern void __cv_broadcast(kcondvar_t *cvp);
|
||||||
})
|
})
|
||||||
#define cv_destroy(cvp) __cv_destroy(cvp)
|
#define cv_destroy(cvp) __cv_destroy(cvp)
|
||||||
#define cv_wait(cvp, mp) __cv_wait(cvp, mp)
|
#define cv_wait(cvp, mp) __cv_wait(cvp, mp)
|
||||||
|
#define cv_wait_interruptible(cvp, mp) __cv_wait_interruptible(cvp, mp)
|
||||||
#define cv_timedwait(cvp, mp, t) __cv_timedwait(cvp, mp, t)
|
#define cv_timedwait(cvp, mp, t) __cv_timedwait(cvp, mp, t)
|
||||||
#define cv_signal(cvp) __cv_signal(cvp)
|
#define cv_signal(cvp) __cv_signal(cvp)
|
||||||
#define cv_broadcast(cvp) __cv_broadcast(cvp)
|
#define cv_broadcast(cvp) __cv_broadcast(cvp)
|
||||||
|
|
|
@ -84,8 +84,8 @@ __cv_destroy(kcondvar_t *cvp)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__cv_destroy);
|
EXPORT_SYMBOL(__cv_destroy);
|
||||||
|
|
||||||
void
|
static void
|
||||||
__cv_wait(kcondvar_t *cvp, kmutex_t *mp)
|
cv_wait_common(kcondvar_t *cvp, kmutex_t *mp, int state)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
ENTRY;
|
ENTRY;
|
||||||
|
@ -103,8 +103,7 @@ __cv_wait(kcondvar_t *cvp, kmutex_t *mp)
|
||||||
ASSERT(cvp->cv_mutex == mp);
|
ASSERT(cvp->cv_mutex == mp);
|
||||||
spin_unlock(&cvp->cv_lock);
|
spin_unlock(&cvp->cv_lock);
|
||||||
|
|
||||||
prepare_to_wait_exclusive(&cvp->cv_event, &wait,
|
prepare_to_wait_exclusive(&cvp->cv_event, &wait, state);
|
||||||
TASK_UNINTERRUPTIBLE);
|
|
||||||
atomic_inc(&cvp->cv_waiters);
|
atomic_inc(&cvp->cv_waiters);
|
||||||
|
|
||||||
/* Mutex should be dropped after prepare_to_wait() this
|
/* Mutex should be dropped after prepare_to_wait() this
|
||||||
|
@ -118,8 +117,21 @@ __cv_wait(kcondvar_t *cvp, kmutex_t *mp)
|
||||||
finish_wait(&cvp->cv_event, &wait);
|
finish_wait(&cvp->cv_event, &wait);
|
||||||
EXIT;
|
EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
__cv_wait(kcondvar_t *cvp, kmutex_t *mp)
|
||||||
|
{
|
||||||
|
cv_wait_common(cvp, mp, TASK_UNINTERRUPTIBLE);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL(__cv_wait);
|
EXPORT_SYMBOL(__cv_wait);
|
||||||
|
|
||||||
|
void
|
||||||
|
__cv_wait_interruptible(kcondvar_t *cvp, kmutex_t *mp)
|
||||||
|
{
|
||||||
|
cv_wait_common(cvp, mp, TASK_INTERRUPTIBLE);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(__cv_wait_interruptible);
|
||||||
|
|
||||||
/* 'expire_time' argument is an absolute wall clock time in jiffies.
|
/* 'expire_time' argument is an absolute wall clock time in jiffies.
|
||||||
* Return value is time left (expire_time - now) or -1 if timeout occurred.
|
* Return value is time left (expire_time - now) or -1 if timeout occurred.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue