dcache-fix-alen-miscalculation-bug-20020805
[openafs.git] / src / afs / afs_osi_alloc.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 RCSID("$Header$");
14
15
16
17 #include "../afs/sysincludes.h" /* Standard vendor system headers */
18 #include "../afs/afsincludes.h" /* Afs-based standard headers */
19 #include "../afs/afs_stats.h"   /* afs statistics */
20
21 #ifdef AFS_AIX41_ENV
22 #include "sys/lockl.h"
23 #include "sys/sleep.h"
24 #include "sys/syspest.h"
25 #include "sys/lock_def.h"
26 /*lock_t osi_fsplock = LOCK_AVAIL;*/
27 #else
28 afs_lock_t osi_fsplock;
29 #endif
30
31
32
33 static struct osi_packet {
34     struct osi_packet *next;
35 } *freePacketList = 0, *freeSmallList, *freeMediumList;
36 afs_lock_t osi_flplock;
37
38
39 afs_int32 afs_preallocs = 512;  /* Reserve space for all small allocs! */
40 void osi_AllocMoreSSpace(preallocs)
41     register afs_int32 preallocs;
42 {
43     register int i;
44     char *p;
45
46     p = (char *) afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
47 #ifdef  AFS_AIX32_ENV
48     pin(p, AFS_SMALLOCSIZ * preallocs); /* XXXX */
49 #endif
50     for (i=0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
51 #ifdef AFS_AIX32_ENV
52         *p = '\0'; /* page fault it in. */
53 #endif
54         osi_FreeSmallSpace((char *) p);
55     }
56     afs_stats_cmperf.SmallBlocksAlloced += preallocs;
57     afs_stats_cmperf.SmallBlocksActive  += preallocs;
58 }
59
60
61
62 /* free space allocated by AllocLargeSpace.  Also called by mclput when freeing
63  * a packet allocated by osi_NetReceive. */
64
65 void
66 osi_FreeLargeSpace(void *adata)
67 {
68
69     AFS_ASSERT_GLOCK();
70
71     AFS_STATCNT(osi_FreeLargeSpace);
72     afs_stats_cmperf.LargeBlocksActive--;
73     MObtainWriteLock(&osi_flplock,322);
74     ((struct osi_packet *)adata)->next = freePacketList;
75     freePacketList = adata;
76     MReleaseWriteLock(&osi_flplock);
77 }
78
79 void
80 osi_FreeSmallSpace(void *adata)
81 {
82
83 #if     defined(AFS_AIX32_ENV)
84     int x;
85 #endif
86 #if     defined(AFS_HPUX_ENV)
87     ulong_t x;
88 #endif
89
90     AFS_ASSERT_GLOCK();
91
92     AFS_STATCNT(osi_FreeSmallSpace);
93     afs_stats_cmperf.SmallBlocksActive--;
94 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
95     x = splnet();       /*lockl(&osi_fsplock, LOCK_SHORT);*/
96 #else
97     MObtainWriteLock(&osi_fsplock,323);
98 #endif
99     ((struct osi_packet *)adata)->next = freeSmallList;
100     freeSmallList = adata;
101 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
102     splx(x);            /*unlockl(&osi_fsplock);*/
103 #else
104     MReleaseWriteLock(&osi_fsplock);
105 #endif
106 }
107
108 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
109 osi_AllocMoreMSpace(preallocs)
110     register afs_int32 preallocs;
111 {
112     register int i;
113     char *p;
114
115     p = (char *) afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
116 #ifdef  AFS_AIX32_ENV
117     pin(p, AFS_MDALLOCSIZ * preallocs); /* XXXX */
118 #endif
119     for (i=0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
120 #ifdef AFS_AIX32_ENV
121         *p = '\0'; /* page fault it in. */
122 #endif
123         osi_FreeMediumSpace((char *) p);
124     }
125     afs_stats_cmperf.MediumBlocksAlloced += preallocs;
126     afs_stats_cmperf.MediumBlocksActive  += preallocs;
127 }
128
129
130 void *osi_AllocMediumSpace(size_t size) 
131 {
132     register struct osi_packet *tp;
133 #if     defined(AFS_AIX32_ENV)
134     int x;
135 #endif
136 #if     defined(AFS_HPUX_ENV)
137     ulong_t x;
138 #endif
139
140     afs_stats_cmperf.MediumBlocksActive++;
141  retry:
142     x = splnet();
143     tp = freeMediumList;
144     if ( tp ) freeMediumList = tp->next;
145     splx(x);
146     if (!tp) {
147         osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER); 
148         goto retry;
149     }
150     return tp;
151 }
152
153 void
154 osi_FreeMediumSpace(void *adata)
155 {
156
157 #if     defined(AFS_AIX32_ENV)
158     int x;
159 #endif
160 #if     defined(AFS_HPUX_ENV)
161     ulong_t x;
162 #endif
163
164     afs_stats_cmperf.MediumBlocksActive--;
165     x = splnet();
166     ((struct osi_packet *)adata)->next = freeMediumList;
167     freeMediumList = adata;
168     splx(x);
169 }
170 #endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
171
172
173 /* allocate space for sender */
174 void *osi_AllocLargeSpace(size_t size) 
175 {
176     register struct osi_packet *tp;
177
178     AFS_ASSERT_GLOCK();
179
180     AFS_STATCNT(osi_AllocLargeSpace);
181     if (size > AFS_LRALLOCSIZ)
182         osi_Panic("osi_AllocLargeSpace: size=%d\n", size);
183     afs_stats_cmperf.LargeBlocksActive++;
184     if (!freePacketList) {
185         char *p;
186
187         afs_stats_cmperf.LargeBlocksAlloced++;
188         p = (char *) afs_osi_Alloc(AFS_LRALLOCSIZ);
189 #ifdef  AFS_AIX32_ENV
190         /*
191          * Need to pin this memory since under heavy conditions this memory
192          * could be swapped out; the problem is that we could inside rx where
193          * interrupts are disabled and thus we would panic if we don't pin it.
194          */
195         pin(p, AFS_LRALLOCSIZ); 
196 #endif
197         return p;
198     }
199     MObtainWriteLock(&osi_flplock,324);
200     tp = freePacketList;
201     if ( tp ) freePacketList = tp->next;
202     MReleaseWriteLock(&osi_flplock);
203     return (char *) tp;
204 }
205
206 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
207 /*
208  * XXX We could have used a macro around osi_AllocSmallSpace but it's
209  * probably better like this so that we can remove this at some point.
210  */
211 char *osi_AllocSmall(size, morespace) 
212     register afs_int32 morespace;               /* 1 - means we called at splnet level */
213     register afs_int32 size;
214 {
215     register struct osi_packet *tp;
216 #if     defined(AFS_AIX32_ENV)
217     int x;
218 #endif
219 #if     defined(AFS_HPUX_ENV)
220     ulong_t x;
221 #endif
222
223     AFS_ASSERT_GLOCK();
224
225     AFS_STATCNT(osi_AllocSmallSpace);
226     if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmall, size=%d", size);
227     if ((!morespace && 
228          ((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
229           <= AFS_SALLOC_LOW_WATER)) 
230         || !freeSmallList) {
231         osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
232     }
233     afs_stats_cmperf.SmallBlocksActive++;
234 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
235     x = splnet();       /*lockl(&osi_fsplock, LOCK_SHORT);*/
236 #else
237     MObtainWriteLock(&osi_fsplock,325);
238 #endif
239     tp = freeSmallList;
240     if ( tp ) freeSmallList = tp->next;
241 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
242     splx(x);            /*unlockl(&osi_fsplock);*/
243 #else
244     MReleaseWriteLock(&osi_fsplock);
245 #endif
246
247     return (char *) tp;
248 }
249
250 osi_FreeSmall(adata)
251     register struct osi_packet *adata; {
252 #if     defined(AFS_AIX32_ENV)
253     int x;
254 #endif
255 #if     defined(AFS_HPUX_ENV)
256     ulong_t x;
257 #endif
258
259     AFS_STATCNT(osi_FreeSmallSpace);
260     afs_stats_cmperf.SmallBlocksActive--;
261 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
262     x = splnet();       /*lockl(&osi_fsplock, LOCK_SHORT);*/
263 #else
264     MObtainWriteLock(&osi_fsplock,326);
265 #endif
266     adata->next = freeSmallList;
267     freeSmallList = adata;
268 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
269     splx(x);            /*unlockl(&osi_fsplock);*/
270 #else
271     MReleaseWriteLock(&osi_fsplock);
272 #endif
273     return 0;
274 }
275 #endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
276
277 /* allocate space for sender */
278 void *osi_AllocSmallSpace(size_t size) 
279 {
280     register struct osi_packet *tp;
281 #if     defined(AFS_AIX32_ENV)
282     int x;
283 #endif
284 #if     defined(AFS_HPUX_ENV)
285     ulong_t x;
286 #endif
287
288     AFS_STATCNT(osi_AllocSmallSpace);
289     if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmallS: size=%d\n", size);
290
291 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
292     /* 
293      * We're running out of free blocks (< 50); get some more ourselves so that
294      * when we don't run out of them when called under splnet() (from rx);
295      */
296     if (((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
297           <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
298         osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
299     }
300 #else
301     if (!freeSmallList) {
302         afs_stats_cmperf.SmallBlocksAlloced++;
303         afs_stats_cmperf.SmallBlocksActive++;
304         return afs_osi_Alloc(AFS_SMALLOCSIZ);
305     }
306 #endif
307     afs_stats_cmperf.SmallBlocksActive++;
308 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
309     x = splnet();       /*lockl(&osi_fsplock, LOCK_SHORT);*/
310 #else
311     MObtainWriteLock(&osi_fsplock,327);
312 #endif
313     tp = freeSmallList;
314     if ( tp ) freeSmallList = tp->next;
315 #if     defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
316     splx(x);            /*unlockl(&osi_fsplock);*/
317 #else
318     MReleaseWriteLock(&osi_fsplock);
319 #endif
320     return (char *) tp;
321 }
322
323
324
325 void shutdown_osinet()
326 {   
327   extern int afs_cold_shutdown;
328
329   AFS_STATCNT(shutdown_osinet);
330   if (afs_cold_shutdown) {
331     struct osi_packet *tp;
332
333     while (tp = freePacketList) {
334       freePacketList = tp->next;
335       afs_osi_Free(tp, AFS_LRALLOCSIZ);
336 #ifdef  AFS_AIX32_ENV
337       unpin(tp, AFS_LRALLOCSIZ);        
338 #endif
339     }
340
341     while (tp = freeSmallList) {
342       freeSmallList = tp->next;
343       afs_osi_Free(tp, AFS_SMALLOCSIZ);
344 #ifdef  AFS_AIX32_ENV
345       unpin(tp, AFS_SMALLOCSIZ);        
346 #endif
347     }
348     afs_preallocs = 512;
349 #ifndef AFS_AIX32_ENV
350     LOCK_INIT(&osi_fsplock, "osi_fsplock");
351 #endif
352     LOCK_INIT(&osi_flplock, "osi_flplock");
353   }
354 }
355