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"
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 */
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;*/
28 afs_lock_t osi_fsplock;
33 static struct osi_packet {
34 struct osi_packet *next;
35 } *freePacketList = NULL, *freeSmallList;
36 afs_lock_t osi_flplock;
39 afs_int32 afs_preallocs = 512; /* Reserve space for all small allocs! */
40 void osi_AllocMoreSSpace(register afs_int32 preallocs)
45 p = (char *) afs_osi_Alloc(AFS_SMALLOCSIZ * preallocs);
46 #ifdef KERNEL_HAVE_PIN
47 pin(p, AFS_SMALLOCSIZ * preallocs); /* XXXX */
49 for (i=0; i < preallocs; i++, p += AFS_SMALLOCSIZ) {
51 *p = '\0'; /* page fault it in. */
53 osi_FreeSmallSpace((char *) p);
55 afs_stats_cmperf.SmallBlocksAlloced += preallocs;
56 afs_stats_cmperf.SmallBlocksActive += preallocs;
61 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
62 * a packet allocated by osi_NetReceive. */
64 void osi_FreeLargeSpace(void *adata)
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);
77 void osi_FreeSmallSpace(void *adata)
80 #if defined(AFS_AIX32_ENV)
83 #if defined(AFS_HPUX_ENV)
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);*/
94 MObtainWriteLock(&osi_fsplock,323);
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);*/
101 MReleaseWriteLock(&osi_fsplock);
105 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
106 static struct osi_packet *freeMediumList;
108 osi_AllocMoreMSpace(register afs_int32 preallocs)
113 p = (char *) afs_osi_Alloc(AFS_MDALLOCSIZ * preallocs);
114 #ifdef KERNEL_HAVE_PIN
115 pin(p, AFS_MDALLOCSIZ * preallocs); /* XXXX */
117 for (i=0; i < preallocs; i++, p += AFS_MDALLOCSIZ) {
119 *p = '\0'; /* page fault it in. */
121 osi_FreeMediumSpace((char *) p);
123 afs_stats_cmperf.MediumBlocksAlloced += preallocs;
124 afs_stats_cmperf.MediumBlocksActive += preallocs;
128 void *osi_AllocMediumSpace(size_t size)
130 register struct osi_packet *tp;
131 #if defined(AFS_AIX32_ENV)
134 #if defined(AFS_HPUX_ENV)
138 afs_stats_cmperf.MediumBlocksActive++;
142 if ( tp ) freeMediumList = tp->next;
145 osi_AllocMoreMSpace(AFS_MALLOC_LOW_WATER);
151 void osi_FreeMediumSpace(void *adata)
154 #if defined(AFS_AIX32_ENV)
157 #if defined(AFS_HPUX_ENV)
161 afs_stats_cmperf.MediumBlocksActive--;
163 ((struct osi_packet *)adata)->next = freeMediumList;
164 freeMediumList = adata;
167 #endif /* defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV) */
170 /* allocate space for sender */
171 void *osi_AllocLargeSpace(size_t size)
173 register struct osi_packet *tp;
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) {
184 afs_stats_cmperf.LargeBlocksAlloced++;
185 p = (char *) afs_osi_Alloc(AFS_LRALLOCSIZ);
186 #ifdef KERNEL_HAVE_PIN
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.
192 pin(p, AFS_LRALLOCSIZ);
196 MObtainWriteLock(&osi_flplock,324);
198 if ( tp ) freePacketList = tp->next;
199 MReleaseWriteLock(&osi_flplock);
203 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
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.
208 /* morespace 1 - means we called at splnet level */
209 char *osi_AllocSmall(register afs_int32 size, register afs_int32 morespace)
211 register struct osi_packet *tp;
212 #if defined(AFS_AIX32_ENV)
215 #if defined(AFS_HPUX_ENV)
221 AFS_STATCNT(osi_AllocSmallSpace);
222 if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmall, size=%d", size);
224 ((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
225 <= AFS_SALLOC_LOW_WATER))
227 osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
229 afs_stats_cmperf.SmallBlocksActive++;
230 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
231 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT);*/
233 MObtainWriteLock(&osi_fsplock,325);
236 if ( tp ) freeSmallList = tp->next;
237 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
238 splx(x); /*unlockl(&osi_fsplock);*/
240 MReleaseWriteLock(&osi_fsplock);
246 int osi_FreeSmall(register struct osi_packet *adata)
248 #if defined(AFS_AIX32_ENV)
251 #if defined(AFS_HPUX_ENV)
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);*/
260 MObtainWriteLock(&osi_fsplock,326);
262 adata->next = freeSmallList;
263 freeSmallList = adata;
264 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
265 splx(x); /*unlockl(&osi_fsplock);*/
267 MReleaseWriteLock(&osi_fsplock);
271 #endif /* AFS_AIX32_ENV || AFS_HPUX_ENV */
273 /* allocate space for sender */
274 void *osi_AllocSmallSpace(size_t size)
276 register struct osi_packet *tp;
277 #if defined(AFS_AIX32_ENV)
280 #if defined(AFS_HPUX_ENV)
284 AFS_STATCNT(osi_AllocSmallSpace);
285 if (size > AFS_SMALLOCSIZ) osi_Panic("osi_AllocSmallS: size=%d\n", size);
287 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
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);
292 if (((afs_stats_cmperf.SmallBlocksAlloced - afs_stats_cmperf.SmallBlocksActive)
293 <= AFS_SALLOC_LOW_WATER) || !freeSmallList) {
294 osi_AllocMoreSSpace(AFS_SALLOC_LOW_WATER * 2);
297 if (!freeSmallList) {
298 afs_stats_cmperf.SmallBlocksAlloced++;
299 afs_stats_cmperf.SmallBlocksActive++;
300 return afs_osi_Alloc(AFS_SMALLOCSIZ);
303 afs_stats_cmperf.SmallBlocksActive++;
304 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
305 x = splnet(); /*lockl(&osi_fsplock, LOCK_SHORT);*/
307 MObtainWriteLock(&osi_fsplock,327);
310 if ( tp ) freeSmallList = tp->next;
311 #if defined(AFS_AIX32_ENV) || defined(AFS_HPUX_ENV)
312 splx(x); /*unlockl(&osi_fsplock);*/
314 MReleaseWriteLock(&osi_fsplock);
321 void shutdown_osinet(void)
323 extern int afs_cold_shutdown;
325 AFS_STATCNT(shutdown_osinet);
326 if (afs_cold_shutdown) {
327 struct osi_packet *tp;
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);
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);
345 #ifndef AFS_AIX32_ENV
346 LOCK_INIT(&osi_fsplock, "osi_fsplock");
348 LOCK_INIT(&osi_flplock, "osi_flplock");