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