1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//---------------------------------------------------------------------------
5// CCacheLineAllocator
6//
7
8//
9// This file dImplements the CCacheLineAllocator class.
10//
11// @comm
12//
13// Notes:
14// The CacheLineAllocator maintains a pool of free CacheLines
15//
16// The CacheLine Allocator provides static member functions
17// GetCacheLine and FreeCacheLine,
18//---------------------------------------------------------------------------
19
20
21
22#include "common.h"
23#include <stddef.h>
24#include "cachelinealloc.h"
25
26#include "threads.h"
27#include "excep.h"
28
29///////////////////////////////////////////////////////
30// CCacheLineAllocator::CCacheLineAllocator()
31//
32//////////////////////////////////////////////////////
33
34CCacheLineAllocator::CCacheLineAllocator()
35{
36 CONTRACTL
37 {
38 NOTHROW;
39 GC_NOTRIGGER;
40 MODE_ANY;
41 }
42 CONTRACTL_END;
43
44 m_freeList32.Init();
45 m_freeList64.Init();
46 m_registryList.Init();
47}
48
49///////////////////////////////////////////////////////
50// void CCacheLineAllocator::~CCacheLineAllocator()
51//
52//////////////////////////////////////////////////////
53
54CCacheLineAllocator::~CCacheLineAllocator()
55{
56 CONTRACTL
57 {
58 NOTHROW;
59 GC_NOTRIGGER;
60 MODE_ANY;
61 }
62 CONTRACTL_END;
63
64 LPCacheLine tempPtr = NULL;
65 while((tempPtr = m_registryList.RemoveHead()) != NULL)
66 {
67 for (int i =0; i < CacheLine::numEntries; i++)
68 {
69 if(tempPtr->m_pAddr[i] != NULL)
70 {
71 if (!g_fProcessDetach)
72 VFree(tempPtr->m_pAddr[i]);
73 }
74 }
75 delete tempPtr;
76 }
77}
78
79
80
81///////////////////////////////////////////////////////
82// static void *CCacheLineAllocator::VAlloc(ULONG cbSize)
83//
84//////////////////////////////////////////////////////
85
86
87void *CCacheLineAllocator::VAlloc(ULONG cbSize)
88{
89 CONTRACT(void*)
90 {
91 NOTHROW;
92 GC_NOTRIGGER;
93 MODE_ANY;
94 INJECT_FAULT(CONTRACT_RETURN NULL);
95 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
96 }
97 CONTRACT_END;
98
99 // helper to call virtual free to release memory
100
101 int i =0;
102 void* pv = ClrVirtualAlloc (NULL, cbSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
103 if (pv != NULL)
104 {
105 LPCacheLine tempPtr = m_registryList.GetHead();
106 if (tempPtr == NULL)
107 {
108 goto LNew;
109 }
110
111 for (i =0; i < CacheLine::numEntries; i++)
112 {
113 if(tempPtr->m_pAddr[i] == NULL)
114 {
115 tempPtr->m_pAddr[i] = pv;
116 RETURN pv;
117 }
118 }
119
120LNew:
121 // initialize the bucket before returning
122 tempPtr = new (nothrow) CacheLine();
123 if (tempPtr != NULL)
124 {
125 tempPtr->Init64();
126 tempPtr->m_pAddr[0] = pv;
127 m_registryList.InsertHead(tempPtr);
128 }
129 else
130 {
131 // couldn't find space to register this page
132 ClrVirtualFree(pv, 0, MEM_RELEASE);
133 RETURN NULL;
134 }
135 }
136 RETURN pv;
137}
138
139///////////////////////////////////////////////////////
140// void CCacheLineAllocator::VFree(void* pv)
141//
142//////////////////////////////////////////////////////
143
144
145void CCacheLineAllocator::VFree(void* pv)
146{
147 BOOL bRes = FALSE;
148
149 CONTRACT_VOID
150 {
151 NOTHROW;
152 GC_NOTRIGGER;
153 MODE_ANY;
154 PRECONDITION(CheckPointer(pv));
155 POSTCONDITION(bRes);
156 }
157 CONTRACT_END;
158
159 // helper to call virtual free to release memory
160
161 bRes = ClrVirtualFree (pv, 0, MEM_RELEASE);
162
163 RETURN_VOID;
164}
165
166///////////////////////////////////////////////////////
167// void *CCacheLineAllocator::GetCacheLine()
168//
169//////////////////////////////////////////////////////
170
171//WARNING: must have a lock when calling this function
172void *CCacheLineAllocator::GetCacheLine64()
173{
174 CONTRACT(void*)
175 {
176 NOTHROW;
177 GC_NOTRIGGER;
178 MODE_ANY;
179 INJECT_FAULT(CONTRACT_RETURN NULL);
180 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
181 }
182 CONTRACT_END;
183
184 LPCacheLine tempPtr = m_freeList64.RemoveHead();
185 if (tempPtr != NULL)
186 {
187 // initialize the bucket before returning
188 tempPtr->Init64();
189 RETURN tempPtr;
190 }
191
192#define AllocSize 4096*16
193
194 ////////////////////////////////'
195 /// Virtual Allocation for some more cache lines
196
197 BYTE* ptr = (BYTE*)VAlloc(AllocSize);
198
199 if(!ptr)
200 RETURN NULL;
201
202
203 tempPtr = (LPCacheLine)ptr;
204 // Link all the buckets
205 tempPtr = tempPtr+1;
206 LPCacheLine maxPtr = (LPCacheLine)(ptr + AllocSize);
207
208 while(tempPtr < maxPtr)
209 {
210 m_freeList64.InsertHead(tempPtr);
211 tempPtr++;
212 }
213
214 // return the first block
215 tempPtr = (LPCacheLine)ptr;
216 tempPtr->Init64();
217 RETURN tempPtr;
218}
219
220
221///////////////////////////////////////////////////////
222// void *CCacheLineAllocator::GetCacheLine32()
223//
224//////////////////////////////////////////////////////
225
226//WARNING: must have a lock when calling this function
227void *CCacheLineAllocator::GetCacheLine32()
228{
229 CONTRACT(void*)
230 {
231 NOTHROW;
232 GC_NOTRIGGER;
233 MODE_ANY;
234 INJECT_FAULT(CONTRACT_RETURN NULL);
235 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
236 }
237 CONTRACT_END;
238
239 LPCacheLine tempPtr = m_freeList32.RemoveHead();
240 if (tempPtr != NULL)
241 {
242 // initialize the bucket before returning
243 tempPtr->Init32();
244 RETURN tempPtr;
245 }
246 tempPtr = (LPCacheLine)GetCacheLine64();
247 if (tempPtr != NULL)
248 {
249 m_freeList32.InsertHead(tempPtr);
250 tempPtr = (LPCacheLine)((BYTE *)tempPtr+32);
251 }
252 RETURN tempPtr;
253}
254///////////////////////////////////////////////////////
255// void CCacheLineAllocator::FreeCacheLine64(void * tempPtr)
256//
257//////////////////////////////////////////////////////
258//WARNING: must have a lock when calling this function
259void CCacheLineAllocator::FreeCacheLine64(void * tempPtr)
260{
261 CONTRACTL
262 {
263 NOTHROW;
264 GC_NOTRIGGER;
265 MODE_ANY;
266
267 PRECONDITION(CheckPointer(tempPtr));
268 }
269 CONTRACTL_END;
270
271 LPCacheLine pCLine = (LPCacheLine )tempPtr;
272 m_freeList64.InsertHead(pCLine);
273}
274
275
276///////////////////////////////////////////////////////
277// void CCacheLineAllocator::FreeCacheLine32(void * tempPtr)
278//
279//////////////////////////////////////////////////////
280//WARNING: must have a lock when calling this function
281void CCacheLineAllocator::FreeCacheLine32(void * tempPtr)
282{
283 CONTRACTL
284 {
285 NOTHROW;
286 GC_NOTRIGGER;
287 MODE_ANY;
288
289 PRECONDITION(CheckPointer(tempPtr));
290 }
291 CONTRACTL_END;
292
293 LPCacheLine pCLine = (LPCacheLine )tempPtr;
294 m_freeList32.InsertHead(pCLine);
295}
296