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 | // EEContract.h |
7 | // |
8 | |
9 | // ! I am the owner for issues in the contract *infrastructure*, not for every |
10 | // ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine |
11 | // ! CONTRACT_VIOLATION, you will become the new owner of this file. |
12 | // --------------------------------------------------------------------------- |
13 | |
14 | |
15 | #ifndef EECONTRACT_H_ |
16 | #define EECONTRACT_H_ |
17 | |
18 | #include "contract.h" |
19 | #include "stackprobe.h" |
20 | |
21 | // -------------------------------------------------------------------------------- |
22 | // EECONTRACT is an extension of the lower level CONTRACT macros to include some |
23 | // EE specific stuff like GC mode checking. See check.h for more info on CONTRACT. |
24 | // -------------------------------------------------------------------------------- |
25 | |
26 | #undef GC_TRIGGERS |
27 | #undef GC_NOTRIGGER |
28 | |
29 | #ifdef ENABLE_CONTRACTS_IMPL |
30 | |
31 | class EEContract : public BaseContract |
32 | { |
33 | private: |
34 | Thread *m_pThread; // Current thread pointer |
35 | // Have to override this function in any derived class to indicate that a valid destructor is defined for this class |
36 | virtual void DestructorDefinedThatCallsRestore(){} |
37 | |
38 | public: |
39 | __declspec(nothrow) ~EEContract() |
40 | { |
41 | Restore(); |
42 | } |
43 | |
44 | void Disable(); |
45 | void DoChecks(UINT testmask, __in_z const char *szFunction, __in_z const char *szFile, int lineNum); |
46 | }; |
47 | |
48 | |
49 | |
50 | #define MODE_COOPERATIVE do { STATIC_CONTRACT_MODE_COOPERATIVE; REQUEST_TEST(Contract::MODE_Coop, Contract::MODE_Disabled); } while(0) |
51 | #define MODE_PREEMPTIVE do { STATIC_CONTRACT_MODE_PREEMPTIVE; REQUEST_TEST(Contract::MODE_Preempt, Contract::MODE_Disabled); } while(0) |
52 | #define MODE_ANY do { STATIC_CONTRACT_MODE_ANY; REQUEST_TEST(Contract::MODE_Disabled, Contract::MODE_Disabled); } while(0) |
53 | |
54 | #define GC_TRIGGERS do { STATIC_CONTRACT_GC_TRIGGERS; REQUEST_TEST(Contract::GC_Triggers, Contract::GC_Disabled); } while(0) |
55 | #define GC_NOTRIGGER do { STATIC_CONTRACT_GC_NOTRIGGER; REQUEST_TEST(Contract::GC_NoTrigger, Contract::GC_Disabled); } while(0) |
56 | |
57 | // Notice there's no static contract component to this. It's |
58 | // perfectly reasonable to find EE_THREAD_REQUIRED inside the scope of |
59 | // EE_THREAD_NOT_REQUIRED (e.g., an EE_THREAD_NOT_REQUIRED scope can have two |
60 | // possible code paths--one with an EE Thread and one without). So we can't do |
61 | // any meaningful testing statically. It's all gotta be done at runtime. |
62 | #define EE_THREAD_NOT_REQUIRED \ |
63 | do { REQUEST_TEST(Contract::EE_THREAD_Not_Required, Contract::EE_THREAD_Disabled); } while(0) |
64 | |
65 | #define EE_THREAD_REQUIRED do { REQUEST_TEST(Contract::EE_THREAD_Required, Contract::EE_THREAD_Disabled); } while(0) |
66 | |
67 | #define HOST_NOCALLS do { STATIC_CONTRACT_HOST_NOCALLS; REQUEST_TEST(Contract::HOST_NoCalls, Contract::HOST_Disabled); } while(0) |
68 | #define HOST_CALLS do { STATIC_CONTRACT_HOST_CALLS; REQUEST_TEST(Contract::HOST_Calls, Contract::HOST_Disabled); } while(0) |
69 | |
70 | #else // ENABLE_CONTRACTS_IMPL |
71 | |
72 | #define MODE_COOPERATIVE |
73 | #define MODE_PREEMPTIVE |
74 | #define MODE_ANY |
75 | #define GC_TRIGGERS |
76 | #define GC_NOTRIGGER |
77 | #define HOST_NOCALLS |
78 | #define HOST_CALLS |
79 | #define EE_THREAD_NOT_REQUIRED |
80 | #define EE_THREAD_REQUIRED |
81 | |
82 | |
83 | #endif // ENABLE_CONTRACTS_IMPL |
84 | |
85 | // Replace the CONTRACT macro with the EE version |
86 | #undef CONTRACT |
87 | #define CONTRACT(_returntype) CUSTOM_CONTRACT(EEContract, _returntype) |
88 | |
89 | #undef CONTRACT_VOID |
90 | #define CONTRACT_VOID CUSTOM_CONTRACT_VOID(EEContract) |
91 | |
92 | #undef CONTRACTL |
93 | #define CONTRACTL CUSTOM_CONTRACTL(EEContract) |
94 | |
95 | #undef LIMITED_METHOD_CONTRACT |
96 | #define LIMITED_METHOD_CONTRACT CUSTOM_LIMITED_METHOD_CONTRACT(EEContract) |
97 | |
98 | #undef WRAPPER_NO_CONTRACT |
99 | #define WRAPPER_NO_CONTRACT CUSTOM_WRAPPER_NO_CONTRACT(EEContract) |
100 | |
101 | // |
102 | // The default contract is the recommended contract for ordinary EE code. |
103 | // The ordinary EE code can throw or trigger GC any time, does not operate |
104 | // on raw object refs, etc. |
105 | // |
106 | |
107 | #undef STANDARD_VM_CHECK |
108 | #define STANDARD_VM_CHECK \ |
109 | THROWS; \ |
110 | GC_TRIGGERS; \ |
111 | MODE_PREEMPTIVE; \ |
112 | SO_INTOLERANT; \ |
113 | INJECT_FAULT(COMPlusThrowOM();); \ |
114 | |
115 | #endif // EECONTRACT_H_ |
116 | |