2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * rx_kmutex.c - mutex and condition variable macros for kernel environment.
13 * Linux implementation.
16 #include <afsconfig.h>
17 #include "afs/param.h"
20 #include "rx/rx_kcommon.h"
21 #include "rx_kmutex.h"
22 #include "rx/rx_kernel.h"
24 #include "osi_compat.h"
27 afs_mutex_init(afs_kmutex_t
* l
)
29 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
30 mutex_init(&l
->mutex
);
31 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
40 afs_mutex_enter(afs_kmutex_t
* l
)
42 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
43 mutex_lock(&l
->mutex
);
48 osi_Panic("mutex_enter: 0x%lx held by %d", (unsigned long)l
, l
->owner
);
49 l
->owner
= current
->pid
;
53 afs_mutex_tryenter(afs_kmutex_t
* l
)
55 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
56 if (mutex_trylock(&l
->mutex
) == 0)
58 if (down_trylock(&l
->sem
))
61 l
->owner
= current
->pid
;
66 afs_mutex_exit(afs_kmutex_t
* l
)
68 if (l
->owner
!= current
->pid
)
69 osi_Panic("mutex_exit: 0x%lx held by %d", (unsigned long)l
, l
->owner
);
71 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
72 mutex_unlock(&l
->mutex
);
78 /* CV_WAIT and CV_TIMEDWAIT sleep until the specified event occurs, or, in the
79 * case of CV_TIMEDWAIT, until the specified timeout occurs.
80 * - NOTE: that on Linux, there are circumstances in which TASK_INTERRUPTIBLE
81 * can wake up, even if all signals are blocked
82 * - TODO: handle signals correctly by passing an indication back to the
83 * caller that the wait has been interrupted and the stack should be cleaned
84 * up preparatory to signal delivery
87 afs_cv_wait(afs_kcondvar_t
* cv
, afs_kmutex_t
* l
, int sigok
)
89 int seq
, isAFSGlocked
= ISAFS_GLOCK();
91 #ifdef DECLARE_WAITQUEUE
92 DECLARE_WAITQUEUE(wait
, current
);
94 struct wait_queue wait
= { current
, NULL
};
96 sigemptyset(&saved_set
);
99 set_current_state(TASK_INTERRUPTIBLE
);
100 add_wait_queue(&cv
->waitq
, &wait
);
108 saved_set
= current
->blocked
;
109 sigfillset(¤t
->blocked
);
110 RECALC_SIGPENDING(current
);
114 while(seq
== cv
->seq
) {
117 set_current_state(TASK_INTERRUPTIBLE
);
120 remove_wait_queue(&cv
->waitq
, &wait
);
121 set_current_state(TASK_RUNNING
);
125 current
->blocked
= saved_set
;
126 RECALC_SIGPENDING(current
);
134 return (sigok
&& signal_pending(current
)) ? EINTR
: 0;
138 afs_cv_timedwait(afs_kcondvar_t
* cv
, afs_kmutex_t
* l
, int waittime
)
140 int seq
, isAFSGlocked
= ISAFS_GLOCK();
141 long t
= waittime
* HZ
/ 1000;
142 #ifdef DECLARE_WAITQUEUE
143 DECLARE_WAITQUEUE(wait
, current
);
145 struct wait_queue wait
= { current
, NULL
};
149 set_current_state(TASK_INTERRUPTIBLE
);
150 add_wait_queue(&cv
->waitq
, &wait
);
156 while(seq
== cv
->seq
) {
157 t
= schedule_timeout(t
);
158 if (!t
) /* timeout */
162 remove_wait_queue(&cv
->waitq
, &wait
);
163 set_current_state(TASK_RUNNING
);