Merge pull request #631 from kebby/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/utils/atomic.h>
22
23 static gboolean shutting_down_inited = FALSE;
24 static gboolean shutting_down = FALSE;
25
26 /** 
27  * mono_runtime_set_shutting_down:
28  *
29  * Invoked by System.Environment.Exit to flag that the runtime
30  * is shutting down.
31  *
32  * Deprecated. This function can break the shutdown sequence.
33  */
34 void
35 mono_runtime_set_shutting_down (void)
36 {
37         shutting_down = TRUE;
38 }
39
40 /**
41  * mono_runtime_is_shutting_down:
42  *
43  * Returns whether the runtime has been flagged for shutdown.
44  *
45  * This is consumed by the P:System.Environment.HasShutdownStarted
46  * property.
47  *
48  */
49 gboolean
50 mono_runtime_is_shutting_down (void)
51 {
52         return shutting_down;
53 }
54
55 static void
56 fire_process_exit_event (MonoDomain *domain, gpointer user_data)
57 {
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_invoke (delegate, pa, &exc);
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  * Try to initialize runtime shutdown.
85  * After this call completes the thread pool will stop accepting new jobs and no further threads will be created.
86  *
87  * @return true if shutdown was initiated by this call or false is other thread beat this one
88  */
89 gboolean
90 mono_runtime_try_shutdown (void)
91 {
92         if (InterlockedCompareExchange (&shutting_down_inited, TRUE, FALSE))
93                 return FALSE;
94
95         mono_runtime_fire_process_exit_event ();
96
97         shutting_down = TRUE;
98
99         mono_threads_set_shutting_down ();
100
101         /* No new threads will be created after this point */
102
103         mono_runtime_set_shutting_down ();
104
105         /* This will kill the tp threads which cannot be suspended */
106         mono_thread_pool_cleanup ();
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         if (mono_monitor_is_il_fastpath_wrapper (method))
122                 return TRUE;
123         return FALSE;
124 }