aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/cacao/files/cacao-shutdownguard.patch
blob: b89170c780071d0b20d2d1f19090d0241886ab44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
diff -r c7bf150bfa46 src/threads/posix/mutex-posix.hpp
--- a/src/threads/posix/mutex-posix.hpp	Fri Mar 11 23:35:56 2011 +0100
+++ b/src/threads/posix/mutex-posix.hpp	Fri Apr 01 16:16:07 2011 +0200
@@ -53,6 +53,9 @@
 
 	inline void lock();
 	inline void unlock();
+
+private:
+	void abort(int, const char*);
 };
 
 #else
@@ -66,7 +69,6 @@
 // Includes.
 #include "vm/os.hpp"
 
-
 #ifdef __cplusplus
 
 /**
@@ -77,19 +79,19 @@
 	int result = pthread_mutexattr_init(&_attr);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_init failed");
+		abort(result, "Mutex::Mutex(): pthread_mutexattr_init failed");
 	}
 
 	result = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_settype failed");
+		abort(result, "Mutex::Mutex(): pthread_mutexattr_settype failed");
 	}
 
 	result = pthread_mutex_init(&_mutex, &_attr);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+		abort(result, "Mutex::Mutex(): pthread_mutex_init failed");
 	}
 }
 
@@ -102,13 +104,13 @@
 	int result = pthread_mutexattr_destroy(&_attr);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutexattr_destroy failed");
+		abort(result, "Mutex::~Mutex(): pthread_mutexattr_destroy failed");
 	}
 
 	result = pthread_mutex_destroy(&_mutex);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+		abort(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
 	}
 }
 
@@ -127,7 +129,7 @@
 	int result = pthread_mutex_lock(&_mutex);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+		abort(result, "Mutex::lock(): pthread_mutex_lock failed");
 	}
 }
 
@@ -141,10 +143,11 @@
 	int result = pthread_mutex_unlock(&_mutex);
 
 	if (result != 0) {
-		os::abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
+		abort(result, "Mutex::unlock: pthread_mutex_unlock failed");
 	}
 }
 
+
 #else
 
 // This structure must have the same layout as the class above.
diff -r c7bf150bfa46 src/threads/posix/thread-posix.cpp
--- a/src/threads/posix/thread-posix.cpp	Fri Mar 11 23:35:56 2011 +0100
+++ b/src/threads/posix/thread-posix.cpp	Fri Apr 01 16:16:07 2011 +0200
@@ -74,6 +74,23 @@
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
 
+/**
+ * Handle the case that a mutex related pthread function failed.
+ *
+ * During normal execution of the VM it will make it abort. However if the
+ * VM is in its last stages of shutting down (where nothing pthread related works
+ * anymore), it will silently end the calling thread.
+ */ 
+void Mutex::abort(int errnum, const char* text)
+{
+	if (VM::get_current()->is_shutdown())
+	{
+		pthread_exit(NULL);
+	}
+
+	os::abort_errnum(errnum, text);
+}
+
 #if defined(ENABLE_STATISTICS)
 # include "vm/statistics.h"
 #endif
diff -r c7bf150bfa46 src/vm/vm.cpp
--- a/src/vm/vm.cpp	Fri Mar 11 23:35:56 2011 +0100
+++ b/src/vm/vm.cpp	Fri Apr 01 16:16:07 2011 +0200
@@ -52,6 +52,7 @@
 
 #include "native/vm/nativevm.hpp"
 
+#include "threads/atomic.hpp"
 #include "threads/lock.hpp"
 #include "threads/thread.hpp"
 
@@ -1585,6 +1586,22 @@
 	return true;
 }
 
+/**
+ * Checks whether a shutdown process has to be guarded.
+ *
+ * Returning true means the caller must not continue
+ * doing any shutdown operations.
+ */
+bool VM::shutdown_guard()
+{
+	return Atomic::generic_compare_and_swap(&_shuttingdown, 0, 1) == 1;
+}
+
+bool VM::is_shutdown()
+{
+	Atomic::generic_memory_barrier();
+	return _shuttingdown == 1;
+}
 
 /* vm_run **********************************************************************
 
@@ -1865,6 +1882,15 @@
 
 void vm_shutdown(s4 status)
 {
+	log_println("vm_shutdown");
+
+	if (VM::get_current()->shutdown_guard())
+	{
+		/* Shutdown in progress by another thread already.
+		 Silently not do it another time. */
+		return;
+	}
+
 	if (opt_verbose 
 #if defined(ENABLE_STATISTICS)
 		|| opt_getcompilingtime || opt_stat
diff -r c7bf150bfa46 src/vm/vm.hpp
--- a/src/vm/vm.hpp	Fri Mar 11 23:35:56 2011 +0100
+++ b/src/vm/vm.hpp	Fri Apr 01 16:16:07 2011 +0200
@@ -64,6 +64,7 @@
 	bool    _initializing;
 	bool    _created;
 	bool    _exiting;
+	uint32_t _shuttingdown;
 	int64_t _starttime;
 	int64_t _inittime;
 
@@ -104,6 +105,9 @@
 	int64_t get_starttime()   { return _starttime; }
 	int64_t get_inittime()    { return _inittime; }
 
+	bool	shutdown_guard();
+	bool	is_shutdown();
+
 	Properties&      get_properties     () { return _properties; }
 	Recompiler&      get_recompiler     () { return _recompiler; } // REMOVEME
 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)