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);
55 #elif defined(AFS_FBSD_ENV)
56 return osi_fbsd_alloc(size
, 1);
58 return AFS_KALLOC(size
);
63 afs_osi_Free(void *x
, size_t asize
)
65 AFS_STATCNT(osi_Free
);
66 if (x
== &memZero
|| x
== NULL
)
67 return; /* check for putting memZero back */
69 AFS_STATS(afs_stats_cmperf
.OutStandingAllocs
--);
70 AFS_STATS(afs_stats_cmperf
.OutStandingMemUsage
-= asize
);
71 #if defined(AFS_LINUX20_ENV)
73 #elif defined(AFS_FBSD_ENV)
81 afs_osi_FreeStr(char *x
)
83 afs_osi_Free(x
, strlen(x
) + 1);
86 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
88 /* free space allocated by AllocLargeSpace. Also called by mclput when freeing
89 * a packet allocated by osi_NetReceive. */
92 osi_FreeLargeSpace(void *adata
)
97 AFS_STATCNT(osi_FreeLargeSpace
);
98 afs_stats_cmperf
.LargeBlocksActive
--;
99 ObtainWriteLock(&osi_flplock
, 322);
100 ((struct osi_packet
*)adata
)->next
= freePacketList
;
101 freePacketList
= adata
;
102 ReleaseWriteLock(&osi_flplock
);
106 osi_FreeSmallSpace(void *adata
)
111 AFS_STATCNT(osi_FreeSmallSpace
);
112 afs_stats_cmperf
.SmallBlocksActive
--;
113 ObtainWriteLock(&osi_fsplock
, 323);
114 ((struct osi_packet
*)adata
)->next
= freeSmallList
;
115 freeSmallList
= adata
;
116 ReleaseWriteLock(&osi_fsplock
);
120 /* allocate space for sender */
122 osi_AllocLargeSpace(size_t size
)
124 struct osi_packet
*tp
;
128 AFS_STATCNT(osi_AllocLargeSpace
);
129 if (size
> AFS_LRALLOCSIZ
)
130 osi_Panic("osi_AllocLargeSpace: size=%d\n", (int)size
);
131 afs_stats_cmperf
.LargeBlocksActive
++;
132 if (!freePacketList
) {
135 afs_stats_cmperf
.LargeBlocksAlloced
++;
136 p
= afs_osi_Alloc(AFS_LRALLOCSIZ
);
137 #ifdef KERNEL_HAVE_PIN
139 * Need to pin this memory since under heavy conditions this memory
140 * could be swapped out; the problem is that we could inside rx where
141 * interrupts are disabled and thus we would panic if we don't pin it.
143 pin(p
, AFS_LRALLOCSIZ
);
147 ObtainWriteLock(&osi_flplock
, 324);
150 freePacketList
= tp
->next
;
151 ReleaseWriteLock(&osi_flplock
);
156 /* allocate space for sender */
158 osi_AllocSmallSpace(size_t size
)
160 struct osi_packet
*tp
;
162 AFS_STATCNT(osi_AllocSmallSpace
);
163 if (size
> AFS_SMALLOCSIZ
)
164 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size
);
166 if (!freeSmallList
) {
167 afs_stats_cmperf
.SmallBlocksAlloced
++;
168 afs_stats_cmperf
.SmallBlocksActive
++;
169 tp
= afs_osi_Alloc(AFS_SMALLOCSIZ
);
170 #ifdef KERNEL_HAVE_PIN
171 pin((char *)tp
, AFS_SMALLOCSIZ
);
175 afs_stats_cmperf
.SmallBlocksActive
++;
176 ObtainWriteLock(&osi_fsplock
, 327);
179 freeSmallList
= tp
->next
;
180 ReleaseWriteLock(&osi_fsplock
);
183 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
186 shutdown_osinet(void)
188 AFS_STATCNT(shutdown_osinet
);
189 #ifndef AFS_PRIVATE_OSI_ALLOCSPACES
190 if (afs_cold_shutdown
) {
191 struct osi_packet
*tp
;
193 while ((tp
= freePacketList
)) {
194 freePacketList
= tp
->next
;
195 afs_osi_Free(tp
, AFS_LRALLOCSIZ
);
196 #ifdef KERNEL_HAVE_PIN
197 unpin(tp
, AFS_LRALLOCSIZ
);
201 while ((tp
= freeSmallList
)) {
202 freeSmallList
= tp
->next
;
203 afs_osi_Free(tp
, AFS_SMALLOCSIZ
);
204 #ifdef KERNEL_HAVE_PIN
205 unpin(tp
, AFS_SMALLOCSIZ
);
208 LOCK_INIT(&osi_fsplock
, "osi_fsplock");
209 LOCK_INIT(&osi_flplock
, "osi_flplock");
211 #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
212 if (afs_stats_cmperf
.LargeBlocksActive
||
213 afs_stats_cmperf
.SmallBlocksActive
)
215 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
216 afs_stats_cmperf
.LargeBlocksActive
,
217 afs_stats_cmperf
.SmallBlocksActive
);