Cleanup usage of LINUX_VERSION_CODE for older kernels
[openafs.git] / src / rx / LINUX / rx_kmutex.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /*
11  * rx_kmutex.c - mutex and condition variable macros for kernel environment.
12  *
13  * Linux implementation.
14  */
15
16 #include <afsconfig.h>
17 #include "afs/param.h"
18
19
20 #include "rx/rx_kcommon.h"
21 #include "rx_kmutex.h"
22 #include "rx/rx_kernel.h"
23
24 #include "osi_compat.h"
25
26 void
27 afs_mutex_init(afs_kmutex_t * l)
28 {
29     mutex_init(&l->mutex);
30     l->owner = 0;
31 }
32
33 void
34 afs_mutex_enter(afs_kmutex_t * l)
35 {
36     mutex_lock(&l->mutex);
37     if (l->owner)
38         osi_Panic("mutex_enter: 0x%lx held by %d", (unsigned long)l, l->owner);
39     l->owner = current->pid;
40 }
41
42 int
43 afs_mutex_tryenter(afs_kmutex_t * l)
44 {
45     if (mutex_trylock(&l->mutex) == 0)
46         return 0;
47     l->owner = current->pid;
48     return 1;
49 }
50
51 void
52 afs_mutex_exit(afs_kmutex_t * l)
53 {
54     if (l->owner != current->pid)
55         osi_Panic("mutex_exit: 0x%lx held by %d", (unsigned long)l, l->owner);
56     l->owner = 0;
57     mutex_unlock(&l->mutex);
58 }
59
60 /* CV_WAIT and CV_TIMEDWAIT sleep until the specified event occurs, or, in the
61  * case of CV_TIMEDWAIT, until the specified timeout occurs.
62  * - NOTE: that on Linux, there are circumstances in which TASK_INTERRUPTIBLE
63  *   can wake up, even if all signals are blocked
64  * - TODO: handle signals correctly by passing an indication back to the
65  *   caller that the wait has been interrupted and the stack should be cleaned
66  *   up preparatory to signal delivery
67  */
68 int
69 afs_cv_wait(afs_kcondvar_t * cv, afs_kmutex_t * l, int sigok)
70 {
71     int seq, isAFSGlocked = ISAFS_GLOCK();
72     sigset_t saved_set;
73 #ifdef DECLARE_WAITQUEUE
74     DECLARE_WAITQUEUE(wait, current);
75 #else
76     struct wait_queue wait = { current, NULL };
77 #endif
78     sigemptyset(&saved_set);
79     seq = cv->seq;
80     
81     set_current_state(TASK_INTERRUPTIBLE);
82     add_wait_queue(&cv->waitq, &wait);
83
84     if (isAFSGlocked)
85         AFS_GUNLOCK();
86     MUTEX_EXIT(l);
87
88     if (!sigok) {
89         SIG_LOCK(current);
90         saved_set = current->blocked;
91         sigfillset(&current->blocked);
92         RECALC_SIGPENDING(current);
93         SIG_UNLOCK(current);
94     }
95
96     while(seq == cv->seq) {
97         schedule();
98         afs_try_to_freeze();
99         set_current_state(TASK_INTERRUPTIBLE);
100     }
101
102     remove_wait_queue(&cv->waitq, &wait);
103     set_current_state(TASK_RUNNING);
104
105     if (!sigok) {
106         SIG_LOCK(current);
107         current->blocked = saved_set;
108         RECALC_SIGPENDING(current);
109         SIG_UNLOCK(current);
110     }
111
112     if (isAFSGlocked)
113         AFS_GLOCK();
114     MUTEX_ENTER(l);
115
116     return (sigok && signal_pending(current)) ? EINTR : 0;
117 }
118
119 void
120 afs_cv_timedwait(afs_kcondvar_t * cv, afs_kmutex_t * l, int waittime)
121 {
122     int seq, isAFSGlocked = ISAFS_GLOCK();
123     long t = waittime * HZ / 1000;
124 #ifdef DECLARE_WAITQUEUE
125     DECLARE_WAITQUEUE(wait, current);
126 #else
127     struct wait_queue wait = { current, NULL };
128 #endif
129     seq = cv->seq;
130
131     set_current_state(TASK_INTERRUPTIBLE);
132     add_wait_queue(&cv->waitq, &wait);
133
134     if (isAFSGlocked)
135         AFS_GUNLOCK();
136     MUTEX_EXIT(l);
137
138     while(seq == cv->seq) {
139         t = schedule_timeout(t);
140         if (!t)         /* timeout */
141             break;
142     }
143     
144     remove_wait_queue(&cv->waitq, &wait);
145     set_current_state(TASK_RUNNING);
146
147     if (isAFSGlocked)
148         AFS_GLOCK();
149     MUTEX_ENTER(l);
150 }