Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / metadata / runtime.c
1 /**
2  * \file
3  * Runtime functions
4  *
5  * Authors:
6  *  Jonathan Pryor
7  *
8  * Copyright 2010 Novell, Inc (http://www.novell.com)
9  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
10  */
11
12 #include <config.h>
13
14 #include <glib.h>
15
16 #include <mono/metadata/appdomain.h>
17 #include <mono/metadata/class.h>
18 #include <mono/metadata/class-internals.h>
19 #include <mono/metadata/runtime.h>
20 #include <mono/metadata/monitor.h>
21 #include <mono/metadata/threads-types.h>
22 #include <mono/metadata/threadpool.h>
23 #include <mono/metadata/marshal.h>
24 #include <mono/utils/atomic.h>
25 #include <mono/utils/unlocked.h>
26
27 static gboolean shutting_down_inited = FALSE;
28 static gboolean shutting_down = FALSE;
29
30 /**
31  * mono_runtime_set_shutting_down:
32  * \deprecated This function can break the shutdown sequence.
33  *
34  * Invoked by \c System.Environment.Exit to flag that the runtime
35  * is shutting down.
36  */
37 void
38 mono_runtime_set_shutting_down (void)
39 {
40         UnlockedWriteBool (&shutting_down, TRUE);
41 }
42
43 /**
44  * mono_runtime_is_shutting_down:
45  * This is consumed by the \c P:System.Environment.HasShutdownStarted property.
46  * \returns whether the runtime has been flagged for shutdown.
47  */
48 gboolean
49 mono_runtime_is_shutting_down (void)
50 {
51         return UnlockedReadBool (&shutting_down);
52 }
53
54 static void
55 fire_process_exit_event (MonoDomain *domain, gpointer user_data)
56 {
57         MonoError error;
58         MonoClassField *field;
59         gpointer pa [2];
60         MonoObject *delegate, *exc;
61
62         field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
63         g_assert (field);
64
65         delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
66         if (delegate == NULL)
67                 return;
68
69         pa [0] = domain;
70         pa [1] = NULL;
71         mono_runtime_delegate_try_invoke (delegate, pa, &exc, &error);
72         mono_error_cleanup (&error);
73 }
74
75 static void
76 mono_runtime_fire_process_exit_event (void)
77 {
78 #ifndef MONO_CROSS_COMPILE
79         mono_domain_foreach (fire_process_exit_event, NULL);
80 #endif
81 }
82
83 /**
84  * mono_runtime_try_shutdown:
85  *
86  * Try to initialize runtime shutdown.
87  *
88  * After this call completes the thread pool will stop accepting new jobs and no further threads will be created.
89  *
90  * Returns: TRUE if shutdown was initiated by this call or false is other thread beat this one.
91  */
92 gboolean
93 mono_runtime_try_shutdown (void)
94 {
95         if (InterlockedCompareExchange (&shutting_down_inited, TRUE, FALSE))
96                 return FALSE;
97
98         mono_runtime_fire_process_exit_event ();
99
100         mono_runtime_set_shutting_down ();
101
102         mono_threads_set_shutting_down ();
103
104         /* No new threads will be created after this point */
105
106         /*TODO move the follow to here:
107         mono_thread_suspend_all_other_threads (); OR  mono_thread_wait_all_other_threads
108
109         mono_runtime_quit ();
110         */
111
112         return TRUE;
113 }
114
115 /*
116 Coordinate the creation of all remaining TLS slots in the runtime.
117 No further TLS slots should be created after this function finishes.
118 This restriction exists because AOT requires offsets to be constant
119 across runs.
120 */
121 void
122 mono_runtime_init_tls (void)
123 {
124         mono_marshal_init_tls ();
125 }
126
127 char*
128 mono_runtime_get_aotid (void)
129 {
130         int i;
131         guint8 aotid_sum = 0;
132         MonoDomain* domain = mono_domain_get ();
133
134         if (!domain->entry_assembly || !domain->entry_assembly->image)
135                 return NULL;
136
137         guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
138
139         for (i = 0; i < 16; ++i)
140                 aotid_sum |= (*aotid)[i];
141
142         if (aotid_sum == 0)
143                 return NULL;
144
145         return mono_guid_to_string ((guint8*) aotid);
146 }