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