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 */
43 afs_osi_Alloc(size_t size)
45 AFS_STATCNT(osi_Alloc);
46 /* 0-length allocs may return NULL ptr from AFS_KALLOC, so we special-case
47 * things so that NULL returned iff an error occurred */
51 AFS_STATS(afs_stats_cmperf.OutStandingAllocs++);
52 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage += size);
53 #ifdef AFS_LINUX20_ENV
54 return osi_linux_alloc(size, 1);
56 return AFS_KALLOC(size);
61 afs_osi_Free(void *x, size_t asize)
63 AFS_STATCNT(osi_Free);
64 if (x == &memZero || x == NULL)
65 return; /* check for putting memZero back */
67 AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
68 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
69 #if defined(AFS_LINUX20_ENV)
77 afs_osi_FreeStr(char *x)
79 afs_osi_Free(x, strlen(x) + 1);
82 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
84 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
85 * a packet allocated by osi_NetReceive. */
88 osi_FreeLargeSpace(void *adata)
93 AFS_STATCNT(osi_FreeLargeSpace);
94 afs_stats_cmperf.LargeBlocksActive--;
95 ObtainWriteLock(&osi_flplock, 322);
96 ((struct osi_packet *)adata)->next = freePacketList;
97 freePacketList = adata;
98 ReleaseWriteLock(&osi_flplock);
102 osi_FreeSmallSpace(void *adata)
107 AFS_STATCNT(osi_FreeSmallSpace);
108 afs_stats_cmperf.SmallBlocksActive--;
109 ObtainWriteLock(&osi_fsplock, 323);
110 ((struct osi_packet *)adata)->next = freeSmallList;
111 freeSmallList = adata;
112 ReleaseWriteLock(&osi_fsplock);
116 /* allocate space for sender */
118 osi_AllocLargeSpace(size_t size)
120 struct osi_packet *tp;
124 AFS_STATCNT(osi_AllocLargeSpace);
125 if (size > AFS_LRALLOCSIZ)
126 osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size);
127 afs_stats_cmperf.LargeBlocksActive++;
128 if (!freePacketList) {
131 afs_stats_cmperf.LargeBlocksAlloced++;
132 p = afs_osi_Alloc(AFS_LRALLOCSIZ);
133 #ifdef KERNEL_HAVE_PIN
135 * Need to pin this memory since under heavy conditions this memory
136 * could be swapped out; the problem is that we could inside rx where
137 * interrupts are disabled and thus we would panic if we don't pin it.
139 pin(p, AFS_LRALLOCSIZ);
143 ObtainWriteLock(&osi_flplock, 324);
146 freePacketList = tp->next;
147 ReleaseWriteLock(&osi_flplock);
152 /* allocate space for sender */
154 osi_AllocSmallSpace(size_t size)
156 struct osi_packet *tp;
158 AFS_STATCNT(osi_AllocSmallSpace);
159 if (size > AFS_SMALLOCSIZ)
160 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
162 if (!freeSmallList) {
163 afs_stats_cmperf.SmallBlocksAlloced++;
164 afs_stats_cmperf.SmallBlocksActive++;
165 tp = afs_osi_Alloc(AFS_SMALLOCSIZ);
166 #ifdef KERNEL_HAVE_PIN
167 pin((char *)tp, AFS_SMALLOCSIZ);
171 afs_stats_cmperf.SmallBlocksActive++;
172 ObtainWriteLock(&osi_fsplock, 327);
175 freeSmallList = tp->next;
176 ReleaseWriteLock(&osi_fsplock);
179 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
182 shutdown_osinet(void)
184 AFS_STATCNT(shutdown_osinet);
185 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
186 if (afs_cold_shutdown) {
187 struct osi_packet *tp;
189 while ((tp = freePacketList)) {
190 freePacketList = tp->next;
191 afs_osi_Free(tp, AFS_LRALLOCSIZ);
192 #ifdef KERNEL_HAVE_PIN
193 unpin(tp, AFS_LRALLOCSIZ);
197 while ((tp = freeSmallList)) {
198 freeSmallList = tp->next;
199 afs_osi_Free(tp, AFS_SMALLOCSIZ);
200 #ifdef KERNEL_HAVE_PIN
201 unpin(tp, AFS_SMALLOCSIZ);
204 LOCK_INIT(&osi_fsplock, "osi_fsplock");
205 LOCK_INIT(&osi_flplock, "osi_flplock");
207 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
208 if (afs_stats_cmperf.LargeBlocksActive ||
209 afs_stats_cmperf.SmallBlocksActive)
211 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
212 afs_stats_cmperf.LargeBlocksActive,
213 afs_stats_cmperf.SmallBlocksActive);