summaryrefslogtreecommitdiff
path: root/src/gc/gcload.cpp
blob: 419183392e0665c73ab949e27048a55426459be8 (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
// 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.

/*
 * gcload.cpp
 * 
 * Code for loading and initializing the GC. The code in this file
 * is used in the startup path of both a standalone and non-standalone GC.
 */

#include "common.h"
#include "gcenv.h"
#include "gc.h"

#ifdef BUILD_AS_STANDALONE
#ifndef DLLEXPORT
#ifdef _MSC_VER
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __attribute__ ((visibility ("default")))
#endif // _MSC_VER
#endif // DLLEXPORT

#define GC_EXPORT extern "C" DLLEXPORT
#else
#define GC_EXPORT extern "C"
#endif

// These symbols are defined in gc.cpp and populate the GcDacVars
// structure with the addresses of DAC variables within the GC.
namespace WKS 
{
    extern void PopulateDacVars(GcDacVars* dacVars);
}

namespace SVR
{
    extern void PopulateDacVars(GcDacVars* dacVars);
}

// This symbol populates GcDacVars with handle table dacvars.
extern void PopulateHandleTableDacVars(GcDacVars* dacVars);

GC_EXPORT
void
GC_VersionInfo(/* Out */ VersionInfo* info)
{
    info->MajorVersion = GC_INTERFACE_MAJOR_VERSION;
    info->MinorVersion = GC_INTERFACE_MINOR_VERSION;
    info->BuildVersion = 0;
    info->Name = "CoreCLR GC";
}

GC_EXPORT
HRESULT
GC_Initialize(
    /* In  */ IGCToCLR* clrToGC,
    /* Out */ IGCHeap** gcHeap,
    /* Out */ IGCHandleManager** gcHandleManager,
    /* Out */ GcDacVars* gcDacVars
)
{
    IGCHeapInternal* heap;
    
    assert(gcDacVars != nullptr);
    assert(gcHeap != nullptr);
    assert(gcHandleManager != nullptr);

#ifdef BUILD_AS_STANDALONE
    assert(clrToGC != nullptr);
    g_theGCToCLR = clrToGC;
#else
    UNREFERENCED_PARAMETER(clrToGC);
    assert(clrToGC == nullptr);
#endif
    
    // Initialize GCConfig before anything else - initialization of our
    // various components may want to query the current configuration.
    GCConfig::Initialize();

    if (!GCToOSInterface::Initialize())
    {
        return E_FAIL;
    }

    IGCHandleManager* handleManager = CreateGCHandleManager();
    if (handleManager == nullptr)
    {
        return E_OUTOFMEMORY;
    }

#ifdef FEATURE_SVR_GC
    if (GCConfig::GetServerGC())
    {
#ifdef WRITE_BARRIER_CHECK
        g_GCShadow = 0;
        g_GCShadowEnd = 0;
#endif // WRITE_BARRIER_CHECK

        g_gc_heap_type = GC_HEAP_SVR;
        heap = SVR::CreateGCHeap();
        SVR::PopulateDacVars(gcDacVars);
    }
    else
#endif
    {
        g_gc_heap_type = GC_HEAP_WKS;
        heap = WKS::CreateGCHeap();
        WKS::PopulateDacVars(gcDacVars);
    }

    PopulateHandleTableDacVars(gcDacVars);
    if (heap == nullptr)
    {
        return E_OUTOFMEMORY;
    }

    g_theGCHeap = heap;
    *gcHandleManager = handleManager;
    *gcHeap = heap;
    return S_OK;
}