js/jsd/jsd_lock.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial