Further rationalise our usage of assert()
[openafs.git] / src / rx / rx_misc.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #ifdef  KERNEL
14 # include <afs/sysincludes.h>
15 # include <afsincludes.h>
16 #else
17 # include <roken.h>
18 # include <afs/opr.h>
19
20 # include <afs/errors.h>
21 # include "xdr.h"
22 # ifdef AFS_PTHREAD_ENV
23 #  include "rx.h"
24 # endif /* AFS_PTHREAD_ENV */
25 # ifdef AFS_NT40_ENV
26 #  ifndef EDQUOT
27 #   define EDQUOT WSAEDQUOT
28 #  endif /* EDQUOT */
29 # endif /* AFS_NT40_ENV */
30 #endif
31
32 /*
33  * We currently only include below the errors that
34  * affect us the most. We should add to this list
35  * more code mappings, as necessary.
36  */
37
38 /*
39  * Convert from the local (host) to the standard
40  * (network) system error code.
41  */
42 int
43 hton_syserr_conv(afs_int32 code)
44 {
45     afs_int32 err;
46
47     if (code == ENOSPC)
48         err = VDISKFULL;
49 #ifdef EDQUOT
50     else if (code == EDQUOT)
51         err = VOVERQUOTA;
52 #endif
53     else
54         err = code;
55     return err;
56 }
57
58
59 /*
60  * Convert from the standard (Network) format to the
61  * local (host) system error code.
62  */
63 int
64 ntoh_syserr_conv(int code)
65 {
66     afs_int32 err;
67
68     if (code == VDISKFULL)
69         err = ENOSPC;
70     else if (code == VOVERQUOTA)
71 #ifndef EDQUOT
72         err = ENOSPC;
73 #else
74         err = EDQUOT;
75 #endif
76     else
77         err = code;
78     return err;
79 }
80
81
82 #ifndef KERNEL
83 /*
84  * We provide the following because some systems (like aix) would fail if we pass
85  * 0 as length.
86  */
87
88 #ifndef osi_alloc
89 static const char memZero;
90 char *
91 osi_alloc(afs_int32 x)
92 {
93     /*
94      * 0-length allocs may return NULL ptr from osi_kalloc, so we special-case
95      * things so that NULL returned iff an error occurred
96      */
97     if (x == 0)
98         return (char *)&memZero;
99     return (char *)(mem_alloc(x));
100 }
101
102 int
103 osi_free(char *x, afs_int32 size)
104 {
105     if ((x == &memZero) || !x)
106         return 0;
107     mem_free(x, size);
108     return 0;
109 }
110 #endif
111 #endif /* KERNEL */
112
113 #if defined(RX_ENABLE_LOCKS) && defined(RX_REFCOUNT_CHECK)
114 int rx_callHoldType = 0;
115 #endif
116
117
118 #ifdef RX_LOCKS_DB
119 /* What follows is a lock database for RX. There is currently room for 400
120  * locks to be held. Routines panic if there is an error. To port, add
121  * RX_LOCKS_DB versions of MUTEX_{ENTER, EXIT, TRYENTER} and CV_*WAIT to
122  * rx_kmutex.h and define lock macros below.
123  */
124 #if (defined(AFS_AIX41_ENV) || (defined(AFS_SGI53_ENV) && defined(MP))) && defined(KERNEL)
125
126 #ifdef AFS_AIX41_ENV
127 Simple_lock rxdb_lock;
128 #define RXDB_LOCK_INIT()        lock_alloc(&rxdb_lock, LOCK_ALLOC_PIN, 1, 0), \
129                                 simple_lock_init(&rxdb_lock)
130 #define RXDB_LOCK_ENTER()       simple_lock(&rxdb_lock)
131 #define RXDB_LOCK_EXIT()        simple_unlock(&rxdb_lock)
132 #else /* AFS_AIX41_ENV */
133 #ifdef AFS_SGI53_ENV
134 afs_kmutex_t rxdb_lock;
135 #define RXDB_LOCK_INIT()        mutex_init(&rxdb_lock, "rxdb lock", 0, 0)
136 #define RXDB_LOCK_ENTER()       AFS_MUTEX_ENTER(&rxdb_lock)
137 #define RXDB_LOCK_EXIT()        mutex_exit(&rxdb_lock)
138 #endif /* AFS_SGI53_ENV */
139 #endif /* AFS_AIX41_ENV */
140
141
142 int RXDB_LockPos = 0;
143
144 #define RXDB_NLOCKS 32
145 struct rxdb_lock_t {
146     afs_int32 id;               /* id of lock holder. */
147     void *a;                    /* address of lock. */
148     u_short fileId;             /* fileID# of RX file. */
149     u_short line;
150     u_short next;
151     u_short prev;
152 };
153
154 #define RXDB_HASHSIZE 8
155
156
157 struct rxdb_lock_t rxdb_lockList[RXDB_NLOCKS];
158 short rxdb_idHash[RXDB_HASHSIZE];
159 #define RXDB_IDHASH(id) ((((u_long)id)>>1) & (RXDB_HASHSIZE-1))
160
161 /* Record locations of all locks we enter/exit. */
162 struct rxdb_lockloc_t {
163     u_short fileId;             /* fileID# of RX file. */
164     u_short line;
165     u_short next;
166     u_short prev;
167 };
168 #ifdef RX_LOCKS_COVERAGE
169 #define RXDB_NlockLocs 512
170 #define RXDB_LOCHASHSIZE 256
171 struct rxdb_lockloc_t rxdb_lockLocs[RXDB_NlockLocs];
172 short rxdb_lockLocHash[RXDB_LOCHASHSIZE];
173 #define RXDB_LOCHASH(a) ((((u_long)a)) & (RXDB_LOCHASHSIZE-1))
174 #endif /* RX_LOCKS_COVERAGE */
175
176 /* Element 0 of each of the above arrays serves as the pointer to the list of
177  * free elements.
178  */
179 void
180 rxdb_init(void)
181 {
182     static int initted = 0;
183     int i;
184
185     if (initted)
186         return;
187
188     initted = 1;
189
190     RXDB_LOCK_INIT();
191     RXDB_LOCK_ENTER();
192
193     for (i = 1; i < RXDB_NLOCKS - 1; i++) {
194         rxdb_lockList[i].next = i + 1;
195         rxdb_lockList[i].prev = i - 1;
196     }
197     rxdb_lockList[0].next = 1;
198     rxdb_lockList[0].prev = 0;
199     rxdb_lockList[RXDB_NLOCKS - 1].next = 0;
200     rxdb_lockList[RXDB_NLOCKS - 1].prev = RXDB_NLOCKS - 2;
201
202 #ifdef RX_LOCKS_COVERAGE
203     for (i = 1; i < RXDB_NlockLocs - 1; i++) {
204         rxdb_lockLocs[i].next = i + 1;
205         rxdb_lockLocs[i].prev = i - 1;
206     }
207     rxdb_lockLocs[0].next = 1;
208     rxdb_lockLocs[0].prev = 0;
209     rxdb_lockLocs[RXDB_NlockLocs - 1].next = 0;
210     rxdb_lockLocs[RXDB_NlockLocs - 1].prev = RXDB_NlockLocs - 2;
211 #endif /* RX_LOCKS_COVERAGE */
212
213     RXDB_LOCK_EXIT();
214 }
215
216 #ifdef RX_LOCKS_COVERAGE
217 void
218 rxdb_RecordLockLocation(fileId, line)
219      afs_int32 fileId, line;
220 {
221     u_short i, j;
222
223     i = RXDB_LOCHASH(line);
224
225     /* Only enter lock location into list once. */
226     for (j = rxdb_lockLocHash[i]; j; j = rxdb_lockLocs[j].next) {
227         if ((rxdb_lockLocs[j].line == line)
228             && (rxdb_lockLocs[j].fileId == fileId))
229             return;
230     }
231
232     /* Add lock to list. */
233     j = rxdb_lockLocs[0].next;
234     if (j == 0) {
235         osi_Panic("rxdb_initLock: used up all the lock locations.\n");
236     }
237
238     /* Fix up free list. */
239     rxdb_lockLocs[0].next = rxdb_lockLocs[j].next;
240
241     /* Put new element at head of list. */
242     rxdb_lockLocs[j].next = rxdb_lockLocHash[i];
243     rxdb_lockLocs[j].prev = 0;
244     if (rxdb_lockLocHash[i]) {
245         rxdb_lockLocs[rxdb_lockLocHash[i]].prev = j;
246     }
247     rxdb_lockLocHash[i] = j;
248
249     /* Set data in element. */
250     rxdb_lockLocs[j].fileId = fileId;
251     rxdb_lockLocs[j].line = line;
252
253 }
254 #endif /* RX_LOCKS_COVERAGE */
255
256
257 /* Set lock as possessed by me. */
258 void
259 rxdb_grablock(a, id, fileId, line)
260      void *a;
261      afs_int32 id;
262      afs_int32 fileId;
263      afs_int32 line;
264 {
265     int i, j, k;
266
267     RXDB_LOCK_ENTER();
268 #ifdef RX_LOCKS_COVERAGE
269     rxdb_RecordLockLocation(fileId, line);
270 #endif /* RX_LOCKS_COVERAGE */
271     /* Is lock already held by anyone? */
272     for (i = 0; i < RXDB_HASHSIZE; i++) {
273         for (j = rxdb_idHash[i]; j; j = rxdb_lockList[j].next) {
274             if (rxdb_lockList[j].a == a) {
275                 RXDB_LockPos = j;
276                 osi_Panic("rxdb_grablock: lock already held.");
277             }
278         }
279     }
280
281     i = RXDB_IDHASH(id);
282     j = rxdb_lockList[0].next;
283     if (j == 0) {
284         osi_Panic("rxdb_grablock: rxdb_lockList is full.");
285     }
286     rxdb_lockList[0].next = rxdb_lockList[j].next;
287
288     /* Put element at head of list. */
289     rxdb_lockList[j].next = rxdb_idHash[i];
290     rxdb_lockList[j].prev = 0;
291     if (rxdb_idHash[i]) {
292         rxdb_lockList[rxdb_idHash[i]].prev = j;
293     }
294     rxdb_idHash[i] = j;
295
296     /* Set data into element. */
297     rxdb_lockList[j].a = a;
298     rxdb_lockList[j].id = id;
299     rxdb_lockList[j].fileId = fileId;
300     rxdb_lockList[j].line = line;
301
302     RXDB_LOCK_EXIT();
303 }
304
305 /* unlock */
306 rxdb_droplock(a, id, fileId, line)
307      void *a;
308      afs_int32 id;
309      int fileId;
310      int line;
311 {
312     int i, j;
313     int found;
314
315     RXDB_LOCK_ENTER();
316 #ifdef RX_LOCKS_COVERAGE
317     rxdb_RecordLockLocation(fileId, line);
318 #endif /* RX_LOCKS_COVERAGE */
319     found = 0;
320
321     /* Do I have the lock? */
322     i = rxdb_idHash[RXDB_IDHASH(id)];
323     for (j = i; j; j = rxdb_lockList[j].next) {
324         if (rxdb_lockList[j].a == a) {
325             found = 1;
326             break;
327         }
328     }
329
330     if (!found) {
331         osi_Panic("rxdb_unlock: lock not held by me.\n");
332     }
333
334     /* delete lock from queue. */
335     if (i == j) {
336         /* head of list. */
337         i = RXDB_IDHASH(id);
338         rxdb_idHash[i] = rxdb_lockList[j].next;
339         rxdb_lockList[rxdb_lockList[j].next].prev = 0;
340     } else {
341         if (rxdb_lockList[j].next)
342             rxdb_lockList[rxdb_lockList[j].next].prev = rxdb_lockList[j].prev;
343         rxdb_lockList[rxdb_lockList[j].prev].next = rxdb_lockList[j].next;
344     }
345     /* Put back on free list. */
346     rxdb_lockList[j].next = rxdb_lockList[0].next;
347     rxdb_lockList[j].prev = 0;
348     rxdb_lockList[0].next = j;
349
350     RXDB_LOCK_EXIT();
351 }
352
353 #endif /* (AIX41 || SGI53) && KERNEL */
354
355 #endif /* RX_LOCKS_DB */