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"
27 /*lock_t osi_fsplock = LOCK_AVAIL;*/
30 afs_lock_t osi_fsplock;
32 static struct osi_packet {
33 struct osi_packet *next;
34 } *freePacketList = NULL, *freeSmallList;
35 afs_lock_t osi_flplock;
37 static char memZero; /* address of 0 bytes for kmem_alloc */
43 #if !defined(AFS_NBSD_ENV)
45 afs_osi_Alloc(size_t x)
47 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_FBSD_ENV)
48 register struct osimem *tm = NULL;
52 AFS_STATCNT(osi_Alloc);
53 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
54 * things so that NULL returned iff an error occurred */
58 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
59 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
60 #ifdef AFS_LINUX20_ENV
61 return osi_linux_alloc(x, 1);
62 #elif defined(AFS_FBSD_ENV)
63 return osi_fbsd_alloc(x, 1);
66 tm = (struct osimem *)AFS_KALLOC(size);
69 osi_Panic("osi_Alloc: Couldn't allocate %d bytes; out of memory!\n",
76 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV)
79 afs_osi_Alloc_NoSleep(size_t x)
81 register struct osimem *tm;
84 AFS_STATCNT(osi_Alloc);
85 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
86 * things so that NULL returned iff an error occurred */
91 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
92 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += x);
93 tm = (struct osimem *)AFS_KALLOC_NOSLEEP(size);
97 #endif /* SUN || SGI */
100 afs_osi_Free(void *x, size_t asize)
102 AFS_STATCNT(osi_Free);
104 return; /* check for putting memZero back */
106 AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
107 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
108 #if defined(AFS_LINUX20_ENV)
110 #elif defined(AFS_FBSD_ENV)
112 #elif defined(AFS_OBSD_ENV)
113 osi_obsd_Free(x, asize);
115 AFS_KFREE((struct osimem *)x, asize);
120 afs_osi_FreeStr(char *x)
122 afs_osi_Free(x, strlen(x) + 1);
125 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
126 * a packet allocated by osi_NetReceive. */
129 osi_FreeLargeSpace(void *adata)
134 AFS_STATCNT(osi_FreeLargeSpace);
135 afs_stats_cmperf.LargeBlocksActive--;
136 ObtainWriteLock(&osi_flplock, 322);
137 ((struct osi_packet *)adata)->next = freePacketList;
138 freePacketList = adata;
139 ReleaseWriteLock(&osi_flplock);
143 osi_FreeSmallSpace(void *adata)
148 AFS_STATCNT(osi_FreeSmallSpace);
149 afs_stats_cmperf.SmallBlocksActive--;
150 ObtainWriteLock(&osi_fsplock, 323);
151 ((struct osi_packet *)adata)->next = freeSmallList;
152 freeSmallList = adata;
153 ReleaseWriteLock(&osi_fsplock);
157 /* allocate space for sender */
159 osi_AllocLargeSpace(size_t size)
161 register struct osi_packet *tp;
165 AFS_STATCNT(osi_AllocLargeSpace);
166 if (size > AFS_LRALLOCSIZ)
167 osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size);
168 afs_stats_cmperf.LargeBlocksActive++;
169 if (!freePacketList) {
172 afs_stats_cmperf.LargeBlocksAlloced++;
173 p = (char *)afs_osi_Alloc(AFS_LRALLOCSIZ);
174 #ifdef KERNEL_HAVE_PIN
176 * Need to pin this memory since under heavy conditions this memory
177 * could be swapped out; the problem is that we could inside rx where
178 * interrupts are disabled and thus we would panic if we don't pin it.
180 pin(p, AFS_LRALLOCSIZ);
184 ObtainWriteLock(&osi_flplock, 324);
187 freePacketList = tp->next;
188 ReleaseWriteLock(&osi_flplock);
193 /* allocate space for sender */
195 osi_AllocSmallSpace(size_t size)
197 register struct osi_packet *tp;
199 AFS_STATCNT(osi_AllocSmallSpace);
200 if (size > AFS_SMALLOCSIZ)
201 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
203 if (!freeSmallList) {
204 afs_stats_cmperf.SmallBlocksAlloced++;
205 afs_stats_cmperf.SmallBlocksActive++;
206 tp = afs_osi_Alloc(AFS_SMALLOCSIZ);
207 #ifdef KERNEL_HAVE_PIN
208 pin((char *)tp, AFS_SMALLOCSIZ);
212 afs_stats_cmperf.SmallBlocksActive++;
213 ObtainWriteLock(&osi_fsplock, 327);
216 freeSmallList = tp->next;
217 ReleaseWriteLock(&osi_fsplock);
221 #endif /* !AFS_NBSD_ENV */
224 shutdown_osinet(void)
226 AFS_STATCNT(shutdown_osinet);
227 if (afs_cold_shutdown) {
228 struct osi_packet *tp;
230 while ((tp = freePacketList)) {
231 freePacketList = tp->next;
232 afs_osi_Free(tp, AFS_LRALLOCSIZ);
233 #ifdef KERNEL_HAVE_PIN
234 unpin(tp, AFS_LRALLOCSIZ);
238 while ((tp = freeSmallList)) {
239 freeSmallList = tp->next;
240 afs_osi_Free(tp, AFS_SMALLOCSIZ);
241 #ifdef KERNEL_HAVE_PIN
242 unpin(tp, AFS_SMALLOCSIZ);
245 LOCK_INIT(&osi_fsplock, "osi_fsplock");
246 LOCK_INIT(&osi_flplock, "osi_flplock");
248 if (afs_stats_cmperf.LargeBlocksActive ||
249 afs_stats_cmperf.SmallBlocksActive)
251 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
252 afs_stats_cmperf.LargeBlocksActive,
253 afs_stats_cmperf.SmallBlocksActive);