summaryrefslogtreecommitdiff
path: root/src/vm/listlock.cpp
blob: 450e85aef5e3aedd3d2031fd4298cf10897f7bc8 (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
// 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.
// ===========================================================================
// File: ListLock.cpp
// 

// 
// ===========================================================================
// This file decribes the list lock and deadlock aware list lock.
// ===========================================================================


#include "common.h"
#include "listlock.h"
#include "listlock.inl"

ListLockEntry::ListLockEntry(ListLock *pList, void *pData, const char *description)
  : m_deadlock(description),
    m_pList(pList),
    m_pData(pData),
    m_Crst(CrstListLock,
           (CrstFlags)(CRST_REENTRANCY | (pList->IsHostBreakable()?CRST_HOST_BREAKABLE:0))),
    m_pszDescription(description),
    m_pNext(NULL),
    m_dwRefCount(1),
    m_hrResultCode(S_FALSE),
    m_hInitException(NULL),
    m_pLoaderAllocator(NULL)
#ifdef FEATURE_CORRUPTING_EXCEPTIONS
    ,
    m_CorruptionSeverity(NotCorrupting)
#endif // FEATURE_CORRUPTING_EXCEPTIONS
{
    WRAPPER_NO_CONTRACT;
}

ListLockEntry *ListLockEntry::Find(ListLock* pLock, LPVOID pPointer, const char *description)
{
    CONTRACTL
    {
        THROWS;
        GC_NOTRIGGER;
        MODE_ANY;
    }
    CONTRACTL_END;

    _ASSERTE(pLock->HasLock());

    ListLockEntry *pEntry = pLock->Find(pPointer);
    if (pEntry==NULL)
    {
        pEntry = new ListLockEntry(pLock, pPointer, description);
        pLock->AddElement(pEntry);
    }
    else
        pEntry->AddRef();

    return pEntry;
};

void ListLockEntry::AddRef()
{
    CONTRACTL
    {
        NOTHROW;
        GC_NOTRIGGER;
        MODE_ANY;
        PRECONDITION(CheckPointer(this));
    }
    CONTRACTL_END;

    FastInterlockIncrement((LONG*)&m_dwRefCount);
}

void ListLockEntry::Release()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_ANY;
        PRECONDITION(CheckPointer(this));
    }
    CONTRACTL_END;

    ListLockHolder lock(m_pList);

    if (FastInterlockDecrement((LONG*)&m_dwRefCount) == 0)
    {
        // Remove from list
        m_pList->Unlink(this);
        delete this;
    }
};