Merge pull request #823 from DavidKarlas/master
[mono.git] / mono / metadata / runtime.c
1 /*
2  * runtime.c: Runtime functions
3  *
4  * Authors:
5  *  Jonathan Pryor 
6  *
7  * Copyright 2010 Novell, Inc (http://www.novell.com)
8  */
9
10 #include <config.h>
11
12 #include <glib.h>
13
14 #include <mono/metadata/appdomain.h>
15 #include <mono/metadata/class.h>
16 #include <mono/metadata/class-internals.h>
17 #include <mono/metadata/runtime.h>
18 #include <mono/metadata/monitor.h>
19 #include <mono/metadata/threads-types.h>
20 #include <mono/metadata/threadpool.h>
21 #include <mono/metadata/marshal.h>
22 #include <mono/utils/atomic.h>
23
24 static gboolean shutting_down_inited = FALSE;
25 static gboolean shutting_down = FALSE;
26
27 /** 
28  * mono_runtime_set_shutting_down:
29  *
30  * Invoked by System.Environment.Exit to flag that the runtime
31  * is shutting down.
32  *
33  * Deprecated. This function can break the shutdown sequence.
34  */
35 void
36 mono_runtime_set_shutting_down (void)
37 {
38         shutting_down = TRUE;
39 }
40
41 /**
42  * mono_runtime_is_shutting_down:
43  *
44  * Returns whether the runtime has been flagged for shutdown.
45  *
46  * This is consumed by the P:System.Environment.HasShutdownStarted
47  * property.
48  *
49  */
50 gboolean
51 mono_runtime_is_shutting_down (void)
52 {
53         return shutting_down;
54 }
55
56 static void
57 fire_process_exit_event (MonoDomain *domain, gpointer user_data)
58 {
59         MonoClassField *field;
60         gpointer pa [2];
61         MonoObject *delegate, *exc;
62
63         field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
64         g_assert (field);
65
66         delegate = *(MonoObject **)(((char *)domain->domain) + field->offset); 
67         if (delegate == NULL)
68                 return;
69
70         pa [0] = domain;
71         pa [1] = NULL;
72         mono_runtime_delegate_invoke (delegate, pa, &exc);
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 /*
85  * Try to initialize runtime shutdown.
86  * After this call completes the thread pool will stop accepting new jobs and no further threads will be created.
87  *
88  * @return true if shutdown was initiated by this call or false is other thread beat this one
89  */
90 gboolean
91 mono_runtime_try_shutdown (void)
92 {
93         if (InterlockedCompareExchange (&shutting_down_inited, TRUE, FALSE))
94                 return FALSE;
95
96         mono_runtime_fire_process_exit_event ();
97
98         shutting_down = TRUE;
99
100         mono_threads_set_shutting_down ();
101
102         /* No new threads will be created after this point */
103
104         mono_runtime_set_shutting_down ();
105
106         /* This will kill the tp threads which cannot be suspended */
107         mono_thread_pool_cleanup ();
108
109         /*TODO move the follow to here:
110         mono_thread_suspend_all_other_threads (); OR  mono_thread_wait_all_other_threads
111
112         mono_runtime_quit ();
113         */
114
115         return TRUE;
116 }
117
118
119 gboolean
120 mono_runtime_is_critical_method (MonoMethod *method)
121 {
122         if (mono_monitor_is_il_fastpath_wrapper (method))
123                 return TRUE;
124         return FALSE;
125 }
126
127 /*
128 Coordinate the creation of all remaining TLS slots in the runtime.
129 No further TLS slots should be created after this function finishes.
130 This restriction exists because AOT requires offsets to be constant
131 across runs.
132 */
133 void
134 mono_runtime_init_tls (void)
135 {
136         mono_marshal_init_tls ();
137         mono_thread_pool_init_tls ();
138         mono_thread_init_tls ();
139 }