2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include "afs/param.h"
18 #include "afs/sysincludes.h" /* Standard vendor system headers */
19 #include "afsincludes.h" /* Afs-based standard headers */
20 #include "afs/afs_stats.h" /* afs statistics */
24 #include "sys/lockl.h"
25 #include "sys/sleep.h"
26 #include "sys/syspest.h"
27 #include "sys/lock_def.h"
28 /*lock_t osi_fsplock = LOCK_AVAIL;*/
30 afs_lock_t osi_fsplock;
35 static struct osi_packet {
36 struct osi_packet *next;
37 } *freePacketList = NULL, *freeSmallList;
38 afs_lock_t osi_flplock;
41 afs_int32 afs_preallocs = 512; /* Reserve space for all small allocs! */
43 osi_AllocMoreSSpace(register afs_int32 preallocs)
48 p = (char *)afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
49 #ifdef KERNEL_HAVE_PIN
50 pin(p, AFS_SMALLOCSIZ * preallocs); /* XXXX */
52 for (i = 0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
54 *p = '\0'; /* page fault it in. */
56 osi_FreeSmallSpace((char *)p);
58 afs_stats_cmperf.SmallBlocksAlloced += preallocs;
59 afs_stats_cmperf.SmallBlocksActive += preallocs;
64 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
65 * a packet allocated by osi_NetReceive. */
68 osi_FreeLargeSpace(void *adata)
73 AFS_STATCNT(osi_FreeLargeSpace);
74 afs_stats_cmperf.LargeBlocksActive--;
75 MObtainWriteLock(&osi_flplock, 322);
76 ((struct osi_packet *)adata)->next = freePacketList;
77 freePacketList = adata;
78 MReleaseWriteLock(&osi_flplock);
82 osi_FreeSmallSpace(void *adata)
85 #if defined(AFS_AIX32_ENV)
88 #if defined(AFS_HPUX_ENV)
94 AFS_STATCNT(osi_FreeSmallSpace);
95 afs_stats_cmperf.SmallBlocksActive--;
96 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
97 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
99 MObtainWriteLock(&osi_fsplock, 323);
101 ((struct osi_packet *)adata)->next = freeSmallList;
102 freeSmallList = adata;
103 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
104 splx(x); /*unlockl(&osi_fsplock); */
106 MReleaseWriteLock(&osi_fsplock);
110 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
111 static struct osi_packet *freeMediumList;
113 osi_AllocMoreMSpace(register afs_int32 preallocs)
118 p = (char *)afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
119 #ifdef KERNEL_HAVE_PIN
120 pin(p, AFS_MDALLOCSIZ * preallocs); /* XXXX */
122 for (i = 0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
124 *p = '\0'; /* page fault it in. */
126 osi_FreeMediumSpace((char *)p);
128 afs_stats_cmperf.MediumBlocksAlloced += preallocs;
129 afs_stats_cmperf.MediumBlocksActive += preallocs;
134 osi_AllocMediumSpace(size_t size)
136 register struct osi_packet *tp;
137 #if defined(AFS_AIX32_ENV)
140 #if defined(AFS_HPUX_ENV)
144 afs_stats_cmperf.MediumBlocksActive++;
149 freeMediumList = tp->next;
152 osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER);
159 osi_FreeMediumSpace(void *adata)
162 #if defined(AFS_AIX32_ENV)
165 #if defined(AFS_HPUX_ENV)
169 afs_stats_cmperf.MediumBlocksActive--;
171 ((struct osi_packet *)adata)->next = freeMediumList;
172 freeMediumList = adata;
175 #endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
178 /* allocate space for sender */
180 osi_AllocLargeSpace(size_t size)
182 register struct osi_packet *tp;
186 AFS_STATCNT(osi_AllocLargeSpace);
187 if (size > AFS_LRALLOCSIZ)
188 osi_Panic("osi_AllocLargeSpace: size=%d\n", size);
189 afs_stats_cmperf.LargeBlocksActive++;
190 if (!freePacketList) {
193 afs_stats_cmperf.LargeBlocksAlloced++;
194 p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
195 #ifdef KERNEL_HAVE_PIN
197 * Need to pin this memory since under heavy conditions this memory
198 * could be swapped out; the problem is that we could inside rx where
199 * interrupts are disabled and thus we would panic if we don't pin it.
201 pin(p, AFS_LRALLOCSIZ);
205 MObtainWriteLock(&osi_flplock, 324);
208 freePacketList = tp->next;
209 MReleaseWriteLock(&osi_flplock);
213 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
215 * XXX We could have used a macro around osi_AllocSmallSpace but it's
216 * probably better like this so that we can remove this at some point.
218 /* morespace 1 - means we called at splnet level */
220 osi_AllocSmall(register afs_int32 size, register afs_int32 morespace)
222 register struct osi_packet *tp;
223 #if defined(AFS_AIX32_ENV)
226 #if defined(AFS_HPUX_ENV)
232 AFS_STATCNT(osi_AllocSmallSpace);
233 if (size > AFS_SMALLOCSIZ)
234 osi_Panic("osi_AllocSmall, size=%d", size);
237 ((afs_stats_cmperf.SmallBlocksAlloced -
238 afs_stats_cmperf.SmallBlocksActive)
239 <= AFS_SALLOC_LOW_WATER))
241 osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
243 afs_stats_cmperf.SmallBlocksActive++;
244 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
245 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
247 MObtainWriteLock(&osi_fsplock, 325);
251 freeSmallList = tp->next;
252 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
253 splx(x); /*unlockl(&osi_fsplock); */
255 MReleaseWriteLock(&osi_fsplock);
262 osi_FreeSmall(register struct osi_packet *adata)
264 #if defined(AFS_AIX32_ENV)
267 #if defined(AFS_HPUX_ENV)
271 AFS_STATCNT(osi_FreeSmallSpace);
272 afs_stats_cmperf.SmallBlocksActive--;
273 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
274 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
276 MObtainWriteLock(&osi_fsplock, 326);
278 adata->next = freeSmallList;
279 freeSmallList = adata;
280 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
281 splx(x); /*unlockl(&osi_fsplock); */
283 MReleaseWriteLock(&osi_fsplock);
287 #endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
289 /* allocate space for sender */
291 osi_AllocSmallSpace(size_t size)
293 register struct osi_packet *tp;
294 #if defined(AFS_AIX32_ENV)
297 #if defined(AFS_HPUX_ENV)
301 AFS_STATCNT(osi_AllocSmallSpace);
302 if (size > AFS_SMALLOCSIZ)
303 osi_Panic("osi_AllocSmallS: size=%d\n", size);
305 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
307 * We're running out of free blocks (< 50); get some more ourselves so that
308 * when we don't run out of them when called under splnet() (from rx);
310 if (((afs_stats_cmperf.SmallBlocksAlloced -
311 afs_stats_cmperf.SmallBlocksActive)
312 <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
313 osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
316 if (!freeSmallList) {
317 afs_stats_cmperf.SmallBlocksAlloced++;
318 afs_stats_cmperf.SmallBlocksActive++;
319 return afs_osi_Alloc(AFS_SMALLOCSIZ);
322 afs_stats_cmperf.SmallBlocksActive++;
323 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
324 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT); */
326 MObtainWriteLock(&osi_fsplock, 327);
330 freeSmallList = tp->next;
331 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
332 splx(x); /*unlockl(&osi_fsplock); */
334 MReleaseWriteLock(&osi_fsplock);
342 shutdown_osinet(void)
344 extern int afs_cold_shutdown;
346 AFS_STATCNT(shutdown_osinet);
347 if (afs_cold_shutdown) {
348 struct osi_packet *tp;
350 while ((tp = freePacketList)) {
351 freePacketList = tp->next;
352 afs_osi_Free(tp, AFS_LRALLOCSIZ);
353 #ifdef KERNEL_HAVE_PIN
354 unpin(tp, AFS_LRALLOCSIZ);
358 while ((tp = freeSmallList)) {
359 freeSmallList = tp->next;
360 afs_osi_Free(tp, AFS_SMALLOCSIZ);
361 #ifdef KERNEL_HAVE_PIN
362 unpin(tp, AFS_SMALLOCSIZ);
366 #ifndef AFS_AIX32_ENV
367 LOCK_INIT(&osi_fsplock, "osi_fsplock");
369 LOCK_INIT(&osi_flplock, "osi_flplock");