summaryrefslogtreecommitdiff
path: root/src/vm/nativeoverlapped.h
blob: 7f12f477e85d0586efdfbd9961efad2cc157d232 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.


/*============================================================
**
** Header: COMNativeOverlapped.h
**
** Purpose: Native methods for allocating and freeing NativeOverlapped
**

** 
===========================================================*/

#ifndef _OVERLAPPED_H
#define _OVERLAPPED_H

// This should match the managed Overlapped object.
// If you make any change here, you need to change the managed part Overlapped.
class OverlappedDataObject : public Object
{
public:
    OBJECTREF m_asyncResult;
    OBJECTREF m_iocb;
    OBJECTREF m_iocbHelper;
    OBJECTREF m_overlapped;
    OBJECTREF m_userObject;

    //
    // NOTE!  WCF directly accesses m_pinSelf from managed code, using a hard-coded negative
    // offset from the Internal member, below.  They need this so they can modify the
    // contents of m_userObject; after such modification, they need to update this handle
    // to be in the correct GC generation.
    //
    // If you need to add or remove fields between this one and Internal, be sure that
    // you also fix the hard-coded offsets in ndp\cdf\src\WCF\ServiceModel\System\ServiceModel\Channels\OverlappedContext.cs.
    //
    OBJECTHANDLE m_pinSelf;

    // OverlappedDataObject is very special.  An async pin handle keeps it alive.
    // During GC, we also make sure
    // 1. m_userObject itself does not move if m_userObject is not array
    // 2. Every object pointed by m_userObject does not move if m_userObject is array
    // We do not want to pin m_userObject if it is array.  But m_userObject may be updated
    // during relocation phase before OverlappedDataObject is doing relocation.
    // m_userObjectInternal is used to track the location of the m_userObject before it is updated.
    void *m_userObjectInternal;
    DWORD m_AppDomainId;
    unsigned char m_isArray;
    unsigned char m_toBeCleaned;

    ULONG_PTR  Internal;
    ULONG_PTR  InternalHigh;
    int     OffsetLow;
    int     OffsetHigh;
    ULONG_PTR  EventHandle;

    static OverlappedDataObject* GetOverlapped (LPOVERLAPPED nativeOverlapped)
    {
        LIMITED_METHOD_CONTRACT;
        STATIC_CONTRACT_SO_TOLERANT;
        
        _ASSERTE (nativeOverlapped != NULL);
        _ASSERTE (GCHeapUtilities::GetGCHeap()->IsHeapPointer((BYTE *) nativeOverlapped));
        
        return (OverlappedDataObject*)((BYTE*)nativeOverlapped - offsetof(OverlappedDataObject, Internal));
    }

    DWORD GetAppDomainId()
    {
        return m_AppDomainId;
    }

    void HandleAsyncPinHandle();

    void FreeAsyncPinHandles();

    BOOL HasCompleted()
    {
        LIMITED_METHOD_CONTRACT;
#ifndef FEATURE_PAL        
        return HasOverlappedIoCompleted((LPOVERLAPPED) &Internal);
#else // !FEATURE_PAL
        return FALSE;
#endif // !FEATURE_PAL
    }

private:
    static LONG s_CleanupRequestCount;
    static BOOL s_CleanupInProgress;
    static BOOL s_GCDetectsCleanup;
    static BOOL s_CleanupFreeHandle;

public:
    static void RequestCleanup()
    {
        WRAPPER_NO_CONTRACT;

        FastInterlockIncrement(&s_CleanupRequestCount);
        if (!s_CleanupInProgress)
        {
            StartCleanup();
        }
    }
    static void StartCleanup();

    static void FinishCleanup(bool wasDrained);

    static void MarkCleanupNeededFromGC()
    {
        LIMITED_METHOD_CONTRACT;
        s_GCDetectsCleanup = TRUE;
    }

    static BOOL CleanupNeededFromGC()
    {
        return s_GCDetectsCleanup;
    }

    static void RequestCleanupFromGC()
    {
        WRAPPER_NO_CONTRACT;

        if (s_GCDetectsCleanup)
        {
            s_GCDetectsCleanup = FALSE;
            RequestCleanup();
        }
    }
};

#ifdef USE_CHECKED_OBJECTREFS

typedef REF<OverlappedDataObject> OVERLAPPEDDATAREF;
#define ObjectToOVERLAPPEDDATAREF(obj)     (OVERLAPPEDDATAREF(obj))
#define OVERLAPPEDDATAREFToObject(objref)  (OBJECTREFToObject (objref))

#else

typedef OverlappedDataObject* OVERLAPPEDDATAREF;
#define ObjectToOVERLAPPEDDATAREF(obj)    ((OverlappedDataObject*) (obj))
#define OVERLAPPEDDATAREFToObject(objref) ((OverlappedDataObject*) (objref))

#endif

FCDECL3(void, CheckVMForIOPacket, LPOVERLAPPED* lpOverlapped, DWORD* errorCode, DWORD* numBytes);
FCDECL1(void*, AllocateNativeOverlapped, OverlappedDataObject* overlapped);
FCDECL1(void, FreeNativeOverlapped, LPOVERLAPPED lpOverlapped);
FCDECL1(OverlappedDataObject*, GetOverlappedFromNative, LPOVERLAPPED lpOverlapped);

void InitializePinHandleTable();
void AddMTForPinHandle(OBJECTREF obj);
void BashMTForPinnedObject(OBJECTREF obj);

#endif