Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / afs_osi_alloc.c
CommitLineData
805e021f
CE
1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10#include <afsconfig.h>
11#include "afs/param.h"
12
13
14
15
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 */
19
20
21
22#ifdef AFS_AIX41_ENV
23#include "sys/lockl.h"
24#include "sys/sleep.h"
25#include "sys/syspest.h"
26#include "sys/lock_def.h"
27#endif
28
29#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
30
31afs_lock_t osi_fsplock;
32afs_lock_t osi_flplock;
33
34static struct osi_packet {
35 struct osi_packet *next;
36} *freePacketList = NULL, *freeSmallList = NULL;
37
38#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
39
40static char memZero; /* address of 0 bytes for kmem_alloc */
41
42void *
43afs_osi_Alloc(size_t size)
44{
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 */
48 if (size == 0)
49 return &memZero;
50
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);
57#else
58 return AFS_KALLOC(size);
59#endif
60}
61
62void
63afs_osi_Free(void *x, size_t asize)
64{
65 AFS_STATCNT(osi_Free);
66 if (x == &memZero || x == NULL)
67 return; /* check for putting memZero back */
68
69 AFS_STATS(afs_stats_cmperf.OutStandingAllocs--);
70 AFS_STATS(afs_stats_cmperf.OutStandingMemUsage -= asize);
71#if defined(AFS_LINUX20_ENV)
72 osi_linux_free(x);
73#elif defined(AFS_FBSD_ENV)
74 osi_fbsd_free(x);
75#else
76 AFS_KFREE(x, asize);
77#endif
78}
79
80void
81afs_osi_FreeStr(char *x)
82{
83 afs_osi_Free(x, strlen(x) + 1);
84}
85
86#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
87
88/* free space allocated by AllocLargeSpace. Also called by mclput when freeing
89 * a packet allocated by osi_NetReceive. */
90
91void
92osi_FreeLargeSpace(void *adata)
93{
94
95 AFS_ASSERT_GLOCK();
96
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);
103}
104
105void
106osi_FreeSmallSpace(void *adata)
107{
108
109 AFS_ASSERT_GLOCK();
110
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);
117}
118
119
120/* allocate space for sender */
121void *
122osi_AllocLargeSpace(size_t size)
123{
124 struct osi_packet *tp;
125
126 AFS_ASSERT_GLOCK();
127
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) {
133 char *p;
134
135 afs_stats_cmperf.LargeBlocksAlloced++;
136 p = afs_osi_Alloc(AFS_LRALLOCSIZ);
137#ifdef KERNEL_HAVE_PIN
138 /*
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.
142 */
143 pin(p, AFS_LRALLOCSIZ);
144#endif
145 return p;
146 }
147 ObtainWriteLock(&osi_flplock, 324);
148 tp = freePacketList;
149 if (tp)
150 freePacketList = tp->next;
151 ReleaseWriteLock(&osi_flplock);
152 return (char *)tp;
153}
154
155
156/* allocate space for sender */
157void *
158osi_AllocSmallSpace(size_t size)
159{
160 struct osi_packet *tp;
161
162 AFS_STATCNT(osi_AllocSmallSpace);
163 if (size > AFS_SMALLOCSIZ)
164 osi_Panic("osi_AllocSmallS: size=%d\n", (int)size);
165
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);
172#endif
173 return (char *)tp;
174 }
175 afs_stats_cmperf.SmallBlocksActive++;
176 ObtainWriteLock(&osi_fsplock, 327);
177 tp = freeSmallList;
178 if (tp)
179 freeSmallList = tp->next;
180 ReleaseWriteLock(&osi_fsplock);
181 return (char *)tp;
182}
183#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
184
185void
186shutdown_osinet(void)
187{
188 AFS_STATCNT(shutdown_osinet);
189#ifndef AFS_PRIVATE_OSI_ALLOCSPACES
190 if (afs_cold_shutdown) {
191 struct osi_packet *tp;
192
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);
198#endif
199 }
200
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);
206#endif
207 }
208 LOCK_INIT(&osi_fsplock, "osi_fsplock");
209 LOCK_INIT(&osi_flplock, "osi_flplock");
210 }
211#endif /* AFS_PRIVATE_OSI_ALLOCSPACES */
212 if (afs_stats_cmperf.LargeBlocksActive ||
213 afs_stats_cmperf.SmallBlocksActive)
214 {
215 afs_warn("WARNING: not all blocks freed: large %d small %d\n",
216 afs_stats_cmperf.LargeBlocksActive,
217 afs_stats_cmperf.SmallBlocksActive);
218 }
219}
220