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
6//
7
8/*============================================================
9**
10** Header: COMUtilNative
11**
12**
13** Purpose: A dumping ground for classes which aren't large
14** enough to get their own file in the VM.
15**
16**
17===========================================================*/
18#ifndef _COMUTILNATIVE_H_
19#define _COMUTILNATIVE_H_
20
21#include "object.h"
22#include "util.hpp"
23#include "cgensys.h"
24#include "fcall.h"
25#include "qcall.h"
26#include "windows.h"
27#undef GetCurrentTime
28
29//
30//
31// EXCEPTION NATIVE
32//
33//
34
35void FreeExceptionData(ExceptionData *pedata);
36
37class ExceptionNative
38{
39private:
40 enum ExceptionMessageKind {
41 ThreadAbort = 1,
42 ThreadInterrupted = 2,
43 OutOfMemory = 3
44 };
45
46public:
47 static FCDECL1(FC_BOOL_RET, IsImmutableAgileException, Object* pExceptionUNSAFE);
48 static FCDECL1(FC_BOOL_RET, IsTransient, INT32 hresult);
49 static FCDECL3(StringObject *, StripFileInfo, Object *orefExcepUNSAFE, StringObject *orefStrUNSAFE, CLR_BOOL isRemoteStackTrace);
50 static void QCALLTYPE GetMessageFromNativeResources(ExceptionMessageKind kind, QCall::StringHandleOnStack retMesg);
51 static FCDECL0(VOID, PrepareForForeignExceptionRaise);
52 static FCDECL1(Object*, CopyStackTrace, Object* pStackTraceUNSAFE);
53 static FCDECL1(Object*, CopyDynamicMethods, Object* pDynamicMethodsUNSAFE);
54 static FCDECL3(VOID, GetStackTracesDeepCopy, Object* pExceptionObjectUnsafe, Object **pStackTraceUnsafe, Object **pDynamicMethodsUnsafe);
55 static FCDECL3(VOID, SaveStackTracesFromDeepCopy, Object* pExceptionObjectUnsafe, Object *pStackTraceUnsafe, Object *pDynamicMethodsUnsafe);
56
57
58 // NOTE: caller cleans up any partially initialized BSTRs in pED
59 static void GetExceptionData(OBJECTREF, ExceptionData *);
60
61 // Note: these are on the PInvoke class to hide these from the user.
62 static FCDECL0(EXCEPTION_POINTERS*, GetExceptionPointers);
63 static FCDECL0(INT32, GetExceptionCode);
64};
65
66class MemoryNative
67{
68public:
69 static void QCALLTYPE Clear(void *dst, size_t length);
70 static FCDECL3(VOID, BulkMoveWithWriteBarrier, void *dst, void *src, size_t byteCount);
71};
72
73//
74// Buffer
75//
76class Buffer {
77public:
78
79 // BlockCopy
80 // This method from one primitive array to another based
81 // upon an offset into each an a byte count.
82 static FCDECL5(VOID, BlockCopy, ArrayBase *src, int srcOffset, ArrayBase *dst, int dstOffset, int count);
83 static FCDECL2(FC_UINT8_RET, GetByte, ArrayBase *arrayUNSAFE, INT32 index);
84 static FCDECL3(VOID, SetByte, ArrayBase *arrayUNSAFE, INT32 index, UINT8 bData);
85 static FCDECL1(FC_BOOL_RET, IsPrimitiveTypeArray, ArrayBase *arrayUNSAFE);
86 static FCDECL1(INT32, ByteLength, ArrayBase *arrayUNSAFE);
87
88 static void QCALLTYPE MemMove(void *dst, void *src, size_t length);
89};
90
91#define MIN_GC_MEMORYPRESSURE_THRESHOLD 100000
92#define RELATIVE_GC_RATIO 8
93
94const UINT NEW_PRESSURE_COUNT = 4;
95
96class GCInterface {
97private:
98
99 static MethodDesc *m_pCacheMethod;
100 static UINT64 m_ulMemPressure;
101 static UINT64 m_ulThreshold;
102 static INT32 m_gc_counts[3];
103
104 static UINT64 m_addPressure[NEW_PRESSURE_COUNT];
105 static UINT64 m_remPressure[NEW_PRESSURE_COUNT];
106 static UINT m_iteration;
107
108public:
109 static CrstStatic m_MemoryPressureLock;
110
111 static FORCEINLINE UINT64 InterlockedAdd(UINT64 *pAugend, UINT64 addend);
112 static FORCEINLINE UINT64 InterlockedSub(UINT64 *pMinuend, UINT64 subtrahend);
113
114 static FCDECL5(void, GetMemoryInfo, UINT32* highMemLoadThreshold, UINT64* totalPhysicalMem, UINT32* lastRecordedMemLoad, size_t* lastRecordedHeapSize, size_t* lastRecordedFragmentation);
115 static FCDECL0(int, GetGcLatencyMode);
116 static FCDECL1(int, SetGcLatencyMode, int newLatencyMode);
117 static FCDECL0(int, GetLOHCompactionMode);
118 static FCDECL1(void, SetLOHCompactionMode, int newLOHCompactionyMode);
119 static FCDECL2(FC_BOOL_RET, RegisterForFullGCNotification, UINT32 gen2Percentage, UINT32 lohPercentage);
120 static FCDECL0(FC_BOOL_RET, CancelFullGCNotification);
121 static FCDECL1(int, WaitForFullGCApproach, int millisecondsTimeout);
122 static FCDECL1(int, WaitForFullGCComplete, int millisecondsTimeout);
123 static FCDECL1(int, GetGenerationWR, LPVOID handle);
124 static FCDECL1(int, GetGeneration, Object* objUNSAFE);
125
126 static
127 INT64 QCALLTYPE GetTotalMemory();
128
129 static
130 void QCALLTYPE Collect(INT32 generation, INT32 mode);
131
132 static
133 void QCALLTYPE WaitForPendingFinalizers();
134
135 static FCDECL0(int, GetMaxGeneration);
136 static FCDECL1(void, KeepAlive, Object *obj);
137 static FCDECL1(void, SuppressFinalize, Object *obj);
138 static FCDECL1(void, ReRegisterForFinalize, Object *obj);
139 static FCDECL2(int, CollectionCount, INT32 generation, INT32 getSpecialGCCount);
140
141 static FCDECL0(INT64, GetAllocatedBytesForCurrentThread);
142
143 static
144 int QCALLTYPE StartNoGCRegion(INT64 totalSize, BOOL lohSizeKnown, INT64 lohSize, BOOL disallowFullBlockingGC);
145
146 static
147 int QCALLTYPE EndNoGCRegion();
148
149 static
150 void QCALLTYPE _AddMemoryPressure(UINT64 bytesAllocated);
151
152 static
153 void QCALLTYPE _RemoveMemoryPressure(UINT64 bytesAllocated);
154
155 static void RemoveMemoryPressure(UINT64 bytesAllocated);
156 static void AddMemoryPressure(UINT64 bytesAllocated);
157 NOINLINE static void SendEtwRemoveMemoryPressureEvent(UINT64 bytesAllocated);
158 static void SendEtwAddMemoryPressureEvent(UINT64 bytesAllocated);
159
160 // New less sensitive implementation of Add/RemoveMemoryPressure:
161 static void CheckCollectionCount();
162 static void NewRemoveMemoryPressure(UINT64 bytesAllocated);
163 static void NewAddMemoryPressure(UINT64 bytesAllocated);
164
165private:
166 // Out-of-line helper to avoid EH prolog/epilog in functions that otherwise don't throw.
167 NOINLINE static void GarbageCollectModeAny(int generation);
168};
169
170class COMInterlocked
171{
172public:
173 static FCDECL2(INT32, Exchange, INT32 *location, INT32 value);
174 static FCDECL2_IV(INT64, Exchange64, INT64 *location, INT64 value);
175 static FCDECL2(LPVOID, ExchangePointer, LPVOID* location, LPVOID value);
176 static FCDECL3(INT32, CompareExchange, INT32* location, INT32 value, INT32 comparand);
177 static FCDECL4(INT32, CompareExchangeReliableResult, INT32* location, INT32 value, INT32 comparand, CLR_BOOL* succeeded);
178 static FCDECL3_IVV(INT64, CompareExchange64, INT64* location, INT64 value, INT64 comparand);
179 static FCDECL3(LPVOID, CompareExchangePointer, LPVOID* location, LPVOID value, LPVOID comparand);
180 static FCDECL2_IV(float, ExchangeFloat, float *location, float value);
181 static FCDECL2_IV(double, ExchangeDouble, double *location, double value);
182 static FCDECL3_IVV(float, CompareExchangeFloat, float *location, float value, float comparand);
183 static FCDECL3_IVV(double, CompareExchangeDouble, double *location, double value, double comparand);
184 static FCDECL2(LPVOID, ExchangeObject, LPVOID* location, LPVOID value);
185 static FCDECL3(LPVOID, CompareExchangeObject, LPVOID* location, LPVOID value, LPVOID comparand);
186 static FCDECL2(INT32, ExchangeAdd32, INT32 *location, INT32 value);
187 static FCDECL2_IV(INT64, ExchangeAdd64, INT64 *location, INT64 value);
188
189 static FCDECL0(void, FCMemoryBarrier);
190 static void QCALLTYPE MemoryBarrierProcessWide();
191};
192
193class ValueTypeHelper {
194public:
195 static FCDECL1(FC_BOOL_RET, CanCompareBits, Object* obj);
196 static FCDECL2(FC_BOOL_RET, FastEqualsCheck, Object* obj1, Object* obj2);
197 static FCDECL1(INT32, GetHashCode, Object* objRef);
198 static FCDECL1(INT32, GetHashCodeOfPtr, LPVOID ptr);
199};
200
201class StreamNative {
202public:
203 static FCDECL1(FC_BOOL_RET, HasOverriddenBeginEndRead, Object *stream);
204 static FCDECL1(FC_BOOL_RET, HasOverriddenBeginEndWrite, Object *stream);
205};
206
207#endif // _COMUTILNATIVE_H_
208