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"
16 #include "afs/sysincludes.h" /* Standard vendor system headers */
17 #include "afsincludes.h" /* Afs-based standard headers */
18 #include "afs/afs_stats.h" /* afs statistics */
23 #include "sys/lockl.h"
24 #include "sys/sleep.h"
25 #include "sys/syspest.h"
26 #include "sys/lock_def.h"
29 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
31 afs_lock_t osi_fsplock;
32 afs_lock_t osi_flplock;
34 static struct osi_packet {
35 struct osi_packet *next;
36 } *freePacketList = NULL, *freeSmallList = NULL;
38 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
40 static char memZero; /* address of 0 bytes for kmem_alloc */
46 #if !defined(AFS_NBSD_ENV) || defined(AFS_NBSD50_ENV)
48 afs_osi_Alloc(size_t x)
50 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
51 struct osimem *tm = NULL;
55 AFS_STATCNT(osi_Alloc);
56 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
57 * things so that NULL returned iff an error occurred */
61 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
62 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
63 #ifdef AFS_LINUX20_ENV
64 return osi_linux_alloc(x, 1);
65 #elif defined(AFS_FBSD_ENV)
66 return osi_fbsd_alloc(x, 1);
69 tm = (struct osimem *)AFS_KALLOC(size);
72 osi_Panic("osi_Alloc: Couldn't allocate %d bytes; out of memory!\n",
79 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
82 afs_osi_Alloc_NoSleep(size_t x)
87 AFS_STATCNT(osi_Alloc);
88 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
89 * things so that NULL returned iff an error occurred */
94 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
95 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
96 tm = (struct osimem *)AFS_KALLOC_NOSLEEP(size);
100 #endif /* SUN || SGI */
103 afs_osi_Free(void *x, size_t asize)
105 AFS_STATCNT(osi_Free);
107 return; /* check for putting memZero back */
109 AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
110 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
111 #if defined(AFS_LINUX20_ENV)
113 #elif defined(AFS_FBSD_ENV)
115 #elif defined(AFS_OBSD_ENV)
116 osi_obsd_Free(x, asize);
118 AFS_KFREE((struct osimem *)x, asize);
123 afs_osi_FreeStr(char *x)
125 afs_osi_Free(x, strlen(x) + 1);
128 #endif /* !AFS_NBSD_ENV && !defined(AFS_NBSD50_ENV) */
130 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
132 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
133 * a packet allocated by osi_NetReceive. */
136 osi_FreeLargeSpace(void *adata)
141 AFS_STATCNT(osi_FreeLargeSpace);
142 afs_stats_cmperf.LargeBlocksActive--;
143 ObtainWriteLock(&osi_flplock, 322);
144 ((struct osi_packet *)adata)->next = freePacketList;
145 freePacketList = adata;
146 ReleaseWriteLock(&osi_flplock);
150 osi_FreeSmallSpace(void *adata)
155 AFS_STATCNT(osi_FreeSmallSpace);
156 afs_stats_cmperf.SmallBlocksActive--;
157 ObtainWriteLock(&osi_fsplock, 323);
158 ((struct osi_packet *)adata)->next = freeSmallList;
159 freeSmallList = adata;
160 ReleaseWriteLock(&osi_fsplock);
164 /* allocate space for sender */
166 osi_AllocLargeSpace(size_t size)
168 struct osi_packet *tp;
172 AFS_STATCNT(osi_AllocLargeSpace);
173 if (size > AFS_LRALLOCSIZ)
174 osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size);
175 afs_stats_cmperf.LargeBlocksActive++;
176 if (!freePacketList) {
179 afs_stats_cmperf.LargeBlocksAlloced++;
180 p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
181 #ifdef KERNEL_HAVE_PIN
183 * Need to pin this memory since under heavy conditions this memory
184 * could be swapped out; the problem is that we could inside rx where
185 * interrupts are disabled and thus we would panic if we don't pin it.
187 pin(p, AFS_LRALLOCSIZ);
191 ObtainWriteLock(&osi_flplock, 324);
194 freePacketList = tp->next;
195 ReleaseWriteLock(&osi_flplock);
200 /* allocate space for sender */
202 osi_AllocSmallSpace(size_t size)
204 struct osi_packet *tp;
206 AFS_STATCNT(osi_AllocSmallSpace);
207 if (size > AFS_SMALLOCSIZ)
208 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
210 if (!freeSmallList) {
211 afs_stats_cmperf.SmallBlocksAlloced++;
212 afs_stats_cmperf.SmallBlocksActive++;
213 tp = afs_osi_Alloc(AFS_SMALLOCSIZ);
214 #ifdef KERNEL_HAVE_PIN
215 pin((char *)tp, AFS_SMALLOCSIZ);
219 afs_stats_cmperf.SmallBlocksActive++;
220 ObtainWriteLock(&osi_fsplock, 327);
223 freeSmallList = tp->next;
224 ReleaseWriteLock(&osi_fsplock);
227 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
230 shutdown_osinet(void)
232 AFS_STATCNT(shutdown_osinet);
233 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
234 if (afs_cold_shutdown) {
235 struct osi_packet *tp;
237 while ((tp = freePacketList)) {
238 freePacketList = tp->next;
239 afs_osi_Free(tp, AFS_LRALLOCSIZ);
240 #ifdef KERNEL_HAVE_PIN
241 unpin(tp, AFS_LRALLOCSIZ);
245 while ((tp = freeSmallList)) {
246 freeSmallList = tp->next;
247 afs_osi_Free(tp, AFS_SMALLOCSIZ);
248 #ifdef KERNEL_HAVE_PIN
249 unpin(tp, AFS_SMALLOCSIZ);
252 LOCK_INIT(&osi_fsplock, "osi_fsplock");
253 LOCK_INIT(&osi_flplock, "osi_flplock");
255 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
256 if (afs_stats_cmperf.LargeBlocksActive ||
257 afs_stats_cmperf.SmallBlocksActive)
259 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
260 afs_stats_cmperf.LargeBlocksActive,
261 afs_stats_cmperf.SmallBlocksActive);