84fe0d1469e742909ed3a12722d2d4168fa9564a
[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
26 static gboolean shutting_down_inited = FALSE;
27 static gboolean shutting_down = FALSE;
28
29 /** 
30  * mono_runtime_set_shutting_down:
31  * \deprecated This function can break the shutdown sequence.
32  *
33  * Invoked by \c System.Environment.Exit to flag that the runtime
34  * is shutting down.
35  */
36 void
37 mono_runtime_set_shutting_down (void)
38 {
39         shutting_down = TRUE;
40 }
41
42 /**
43  * mono_runtime_is_shutting_down:
44  * This is consumed by the \c P:System.Environment.HasShutdownStarted property.
45  * \returns whether the runtime has been flagged for shutdown.
46  */
47 gboolean
48 mono_runtime_is_shutting_down (void)
49 {
50         return shutting_down;
51 }
52
53 static void
54 fire_process_exit_event (MonoDomain *domain, gpointer user_data)
55 {
56         MonoError error;
57         MonoClassField *field;
58         gpointer pa [2];
59         MonoObject *delegate, *exc;
60
61         field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
62         g_assert (field);
63
64         delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
65         if (delegate == NULL)
66                 return;
67
68         pa [0] = domain;
69         pa [1] = NULL;
70         mono_runtime_delegate_try_invoke (delegate, pa, &exc, &error);
71         mono_error_cleanup (&error);
72 }
73
74 static void
75 mono_runtime_fire_process_exit_event (void)
76 {
77 #ifndef MONO_CROSS_COMPILE
78         mono_domain_foreach (fire_process_exit_event, NULL);
79 #endif
80 }
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         shutting_down = TRUE;
101
102         mono_threads_set_shutting_down ();
103
104         /* No new threads will be created after this point */
105
106         mono_runtime_set_shutting_down ();
107
108         /*TODO move the follow to here:
109         mono_thread_suspend_all_other_threads (); OR  mono_thread_wait_all_other_threads
110
111         mono_runtime_quit ();
112         */
113
114         return TRUE;
115 }
116
117
118 gboolean
119 mono_runtime_is_critical_method (MonoMethod *method)
120 {
121         return FALSE;
122 }
123
124 /*
125 Coordinate the creation of all remaining TLS slots in the runtime.
126 No further TLS slots should be created after this function finishes.
127 This restriction exists because AOT requires offsets to be constant
128 across runs.
129 */
130 void
131 mono_runtime_init_tls (void)
132 {
133         mono_marshal_init_tls ();
134 }
135
136 char*
137 mono_runtime_get_aotid (void)
138 {
139         int i;
140         guint8 aotid_sum = 0;
141         MonoDomain* domain = mono_domain_get ();
142
143         if (!domain->entry_assembly || !domain->entry_assembly->image)
144                 return NULL;
145
146         guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
147
148         for (i = 0; i < 16; ++i)
149                 aotid_sum |= (*aotid)[i];
150
151         if (aotid_sum == 0)
152                 return NULL;
153
154         return mono_guid_to_string ((guint8*) aotid);
155 }