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
mono_runtime_set_shutting_down(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
mono_runtime_is_shutting_down(void)49 mono_runtime_is_shutting_down (void)
50 {
51 	return UnlockedReadBool (&shutting_down);
52 }
53 
54 static void
fire_process_exit_event(MonoDomain * domain,gpointer user_data)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
mono_runtime_fire_process_exit_event(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
mono_runtime_try_shutdown(void)93 mono_runtime_try_shutdown (void)
94 {
95 	if (mono_atomic_cas_i32 (&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
mono_runtime_init_tls(void)122 mono_runtime_init_tls (void)
123 {
124 	mono_marshal_init_tls ();
125 }
126 
127 char*
mono_runtime_get_aotid(void)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 }
147