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