Commit | Line | Data |
---|---|---|
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 | ||
31 | afs_lock_t osi_fsplock; | |
32 | afs_lock_t osi_flplock; | |
33 | ||
34 | static struct osi_packet { | |
35 | struct osi_packet *next; | |
36 | } *freePacketList = NULL, *freeSmallList = NULL; | |
37 | ||
38 | #endif /* AFS_PRIVATE_OSI_ALLOCSPACES */ | |
39 | ||
40 | static char memZero; /* address of 0 bytes for kmem_alloc */ | |
41 | ||
42 | void * | |
43 | afs_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 | ||
62 | void | |
63 | afs_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 | ||
80 | void | |
81 | afs_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 | ||
91 | void | |
92 | osi_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 | ||
105 | void | |
106 | osi_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 */ | |
121 | void * | |
122 | osi_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 */ | |
157 | void * | |
158 | osi_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 | ||
185 | void | |
186 | shutdown_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 |