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 */
25 #include "sys/lockl.h"
26 #include "sys/sleep.h"
27 #include "sys/syspest.h"
28 #include "sys/lock_def.h"
29 /*lock_t osi_fsplock = LOCK_AVAIL;*/
32 afs_lock_t osi_fsplock;
36 static struct osi_packet {
37 struct osi_packet *next;
38 } *freePacketList = NULL, *freeSmallList;
39 afs_lock_t osi_flplock;
41 static char memZero; /* address of 0 bytes for kmem_alloc */
49 afs_osi_Alloc(size_t x)
51 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
52 register struct osimem *tm = NULL;
56 AFS_STATCNT(osi_Alloc);
57 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
58 * things so that NULL returned iff an error occurred */
62 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
63 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
64 #ifdef AFS_LINUX20_ENV
65 return osi_linux_alloc(x, 1);
66 #elif defined(AFS_FBSD_ENV)
67 return osi_fbsd_alloc(x, 1);
70 tm = (struct osimem *)AFS_KALLOC(size);
73 osi_Panic("osi_Alloc: Couldn't allocate %d bytes; out of memory!\n",
80 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
83 afs_osi_Alloc_NoSleep(size_t x)
85 register struct osimem *tm;
88 AFS_STATCNT(osi_Alloc);
89 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
90 * things so that NULL returned iff an error occurred */
95 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
96 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
97 tm = (struct osimem *)AFS_KALLOC_NOSLEEP(size);
101 #endif /* SUN || SGI */
104 afs_osi_Free(void *x, size_t asize)
106 AFS_STATCNT(osi_Free);
108 return; /* check for putting memZero back */
110 AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
111 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
112 #if defined(AFS_LINUX20_ENV)
114 #elif defined(AFS_FBSD_ENV)
116 #elif defined(AFS_OBSD44_ENV)
117 osi_obsd_Free(x, asize);
119 AFS_KFREE((struct osimem *)x, asize);
124 afs_osi_FreeStr(char *x)
126 afs_osi_Free(x, strlen(x) + 1);
131 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
132 * a packet allocated by osi_NetReceive. */
135 osi_FreeLargeSpace(void *adata)
140 AFS_STATCNT(osi_FreeLargeSpace);
141 afs_stats_cmperf.LargeBlocksActive--;
142 MObtainWriteLock(&osi_flplock, 322);
143 ((struct osi_packet *)adata)->next = freePacketList;
144 freePacketList = adata;
145 MReleaseWriteLock(&osi_flplock);
149 osi_FreeSmallSpace(void *adata)
154 AFS_STATCNT(osi_FreeSmallSpace);
155 afs_stats_cmperf.SmallBlocksActive--;
156 MObtainWriteLock(&osi_fsplock, 323);
157 ((struct osi_packet *)adata)->next = freeSmallList;
158 freeSmallList = adata;
159 MReleaseWriteLock(&osi_fsplock);
163 /* allocate space for sender */
165 osi_AllocLargeSpace(size_t size)
167 register struct osi_packet *tp;
171 AFS_STATCNT(osi_AllocLargeSpace);
172 if (size > AFS_LRALLOCSIZ)
173 osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size);
174 afs_stats_cmperf.LargeBlocksActive++;
175 if (!freePacketList) {
178 afs_stats_cmperf.LargeBlocksAlloced++;
179 p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
180 #ifdef KERNEL_HAVE_PIN
182 * Need to pin this memory since under heavy conditions this memory
183 * could be swapped out; the problem is that we could inside rx where
184 * interrupts are disabled and thus we would panic if we don't pin it.
186 pin(p, AFS_LRALLOCSIZ);
190 MObtainWriteLock(&osi_flplock, 324);
193 freePacketList = tp->next;
194 MReleaseWriteLock(&osi_flplock);
199 /* allocate space for sender */
201 osi_AllocSmallSpace(size_t size)
203 register struct osi_packet *tp;
205 AFS_STATCNT(osi_AllocSmallSpace);
206 if (size > AFS_SMALLOCSIZ)
207 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
209 if (!freeSmallList) {
210 afs_stats_cmperf.SmallBlocksAlloced++;
211 afs_stats_cmperf.SmallBlocksActive++;
212 tp = afs_osi_Alloc(AFS_SMALLOCSIZ);
213 #ifdef KERNEL_HAVE_PIN
214 pin((char *)tp, AFS_SMALLOCSIZ);
218 afs_stats_cmperf.SmallBlocksActive++;
219 MObtainWriteLock(&osi_fsplock, 327);
222 freeSmallList = tp->next;
223 MReleaseWriteLock(&osi_fsplock);
230 shutdown_osinet(void)
232 AFS_STATCNT(shutdown_osinet);
233 if (afs_cold_shutdown) {
234 struct osi_packet *tp;
236 while ((tp = freePacketList)) {
237 freePacketList = tp->next;
238 afs_osi_Free(tp, AFS_LRALLOCSIZ);
239 #ifdef KERNEL_HAVE_PIN
240 unpin(tp, AFS_LRALLOCSIZ);
244 while ((tp = freeSmallList)) {
245 freeSmallList = tp->next;
246 afs_osi_Free(tp, AFS_SMALLOCSIZ);
247 #ifdef KERNEL_HAVE_PIN
248 unpin(tp, AFS_SMALLOCSIZ);
251 LOCK_INIT(&osi_fsplock, "osi_fsplock");
252 LOCK_INIT(&osi_flplock, "osi_flplock");
254 if (afs_stats_cmperf.LargeBlocksActive ||
255 afs_stats_cmperf.SmallBlocksActive)
257 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
258 afs_stats_cmperf.LargeBlocksActive,
259 afs_stats_cmperf.SmallBlocksActive);