Thu, 15 Jan 2015 15:55:04 +0100
Back out 97036ab72558 which inappropriately compared turds to third parties.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * JavaScript Debugging support - Locking and threading support
9 */
11 /*
12 * ifdef JSD_USE_NSPR_LOCKS then you must build and run against NSPR2.
13 * Otherwise, there are stubs that can be filled in with your own locking
14 * code. Also, note that these stubs include a jsd_CurrentThread()
15 * implementation that only works on Win32 - this is needed for the inprocess
16 * Java-based debugger.
17 */
19 #include "jsd.h"
21 #include "js/Utility.h"
23 #ifdef JSD_THREADSAFE
25 #ifdef JSD_USE_NSPR_LOCKS
27 #include "prlock.h"
28 #include "prthread.h"
30 #ifdef JSD_ATTACH_THREAD_HACK
31 #include "pprthred.h" /* need this as long as JS_AttachThread is needed */
32 #endif
34 struct JSDStaticLock
35 {
36 void* owner;
37 PRLock* lock;
38 int count;
39 #ifdef DEBUG
40 uint16_t sig;
41 #endif
42 };
44 /*
45 * This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers.
46 * XXX We ignore the memory leak issue.
47 * It is claimed that future versions of NSPR will automatically wrap on
48 * the call to PR_GetCurrentThread.
49 *
50 * XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread.
51 *
52 */
53 #undef _CURRENT_THREAD
54 #ifdef JSD_ATTACH_THREAD_HACK
55 #define _CURRENT_THREAD(out) \
56 JS_BEGIN_MACRO \
57 out = (void*) PR_GetCurrentThread(); \
58 if(!out) \
59 out = (void*) JS_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, \
60 nullptr); \
61 MOZ_ASSERT(out); \
62 JS_END_MACRO
63 #else
64 #define _CURRENT_THREAD(out) \
65 JS_BEGIN_MACRO \
66 out = (void*) PR_GetCurrentThread(); \
67 MOZ_ASSERT(out); \
68 JS_END_MACRO
69 #endif
71 #ifdef DEBUG
72 #define JSD_LOCK_SIG 0x10CC10CC
73 void ASSERT_VALID_LOCK(JSDStaticLock* lock)
74 {
75 MOZ_ASSERT(lock);
76 MOZ_ASSERT(lock->lock);
77 MOZ_ASSERT(lock->count >= 0);
78 MOZ_ASSERT(lock->sig == (uint16_t) JSD_LOCK_SIG);
79 }
80 #else
81 #define ASSERT_VALID_LOCK(x) ((void)0)
82 #endif
84 JSDStaticLock*
85 jsd_CreateLock()
86 {
87 JSDStaticLock* lock;
89 if( ! (lock = js_pod_calloc<JSDStaticLock>()) ||
90 ! (lock->lock = PR_NewLock()) )
91 {
92 if(lock)
93 {
94 free(lock);
95 lock = nullptr;
96 }
97 }
98 #ifdef DEBUG
99 if(lock) lock->sig = (uint16_t) JSD_LOCK_SIG;
100 #endif
101 return lock;
102 }
104 void
105 jsd_Lock(JSDStaticLock* lock)
106 {
107 void* me;
108 ASSERT_VALID_LOCK(lock);
109 _CURRENT_THREAD(me);
111 if(lock->owner == me)
112 {
113 lock->count++;
114 MOZ_ASSERT(lock->count > 1);
115 }
116 else
117 {
118 PR_Lock(lock->lock); /* this can block... */
119 MOZ_ASSERT(lock->owner == 0);
120 MOZ_ASSERT(lock->count == 0);
121 lock->count = 1;
122 lock->owner = me;
123 }
124 }
126 void
127 jsd_Unlock(JSDStaticLock* lock)
128 {
129 void* me;
130 ASSERT_VALID_LOCK(lock);
131 _CURRENT_THREAD(me);
133 /* it's an error to unlock a lock you don't own */
134 MOZ_ASSERT(lock->owner == me);
135 if(lock->owner != me)
136 return;
138 if(--lock->count == 0)
139 {
140 lock->owner = nullptr;
141 PR_Unlock(lock->lock);
142 }
143 }
145 #ifdef DEBUG
146 bool
147 jsd_IsLocked(JSDStaticLock* lock)
148 {
149 void* me;
150 ASSERT_VALID_LOCK(lock);
151 _CURRENT_THREAD(me);
152 if (lock->owner != me)
153 return false;
154 MOZ_ASSERT(lock->count > 0);
155 return true;
156 }
157 #endif /* DEBUG */
159 void*
160 jsd_CurrentThread()
161 {
162 void* me;
163 _CURRENT_THREAD(me);
164 return me;
165 }
168 #else /* ! JSD_USE_NSPR_LOCKS */
170 #ifdef WIN32
171 #pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
172 #pragma message("!! you are compiling the stubbed version of jsd_lock.c !!")
173 #pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
174 #endif
176 /*
177 * NOTE: 'Real' versions of these locks must be reentrant in the sense that
178 * they support nested calls to lock and unlock.
179 */
181 void*
182 jsd_CreateLock()
183 {
184 return (void*)1;
185 }
187 void
188 jsd_Lock(void* lock)
189 {
190 }
192 void
193 jsd_Unlock(void* lock)
194 {
195 }
197 #ifdef DEBUG
198 bool
199 jsd_IsLocked(void* lock)
200 {
201 return true;
202 }
203 #endif /* DEBUG */
205 /*
206 * This Windows only thread id code is here to allow the Java-based
207 * JSDebugger to work with the single threaded js.c shell (even without
208 * real locking and threading support).
209 */
211 #ifdef WIN32
212 /* bogus (but good enough) declaration*/
213 extern void* __stdcall GetCurrentThreadId(void);
214 #endif
216 void*
217 jsd_CurrentThread()
218 {
219 #ifdef WIN32
220 return GetCurrentThreadId();
221 #else
222 return (void*)1;
223 #endif
224 }
226 #endif /* JSD_USE_NSPR_LOCKS */
228 #endif /* JSD_THREADSAFE */