1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/jsd/jsd_lock.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,228 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* 1.11 + * JavaScript Debugging support - Locking and threading support 1.12 + */ 1.13 + 1.14 +/* 1.15 +* ifdef JSD_USE_NSPR_LOCKS then you must build and run against NSPR2. 1.16 +* Otherwise, there are stubs that can be filled in with your own locking 1.17 +* code. Also, note that these stubs include a jsd_CurrentThread() 1.18 +* implementation that only works on Win32 - this is needed for the inprocess 1.19 +* Java-based debugger. 1.20 +*/ 1.21 + 1.22 +#include "jsd.h" 1.23 + 1.24 +#include "js/Utility.h" 1.25 + 1.26 +#ifdef JSD_THREADSAFE 1.27 + 1.28 +#ifdef JSD_USE_NSPR_LOCKS 1.29 + 1.30 +#include "prlock.h" 1.31 +#include "prthread.h" 1.32 + 1.33 +#ifdef JSD_ATTACH_THREAD_HACK 1.34 +#include "pprthred.h" /* need this as long as JS_AttachThread is needed */ 1.35 +#endif 1.36 + 1.37 +struct JSDStaticLock 1.38 +{ 1.39 + void* owner; 1.40 + PRLock* lock; 1.41 + int count; 1.42 +#ifdef DEBUG 1.43 + uint16_t sig; 1.44 +#endif 1.45 +}; 1.46 + 1.47 +/* 1.48 + * This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers. 1.49 + * XXX We ignore the memory leak issue. 1.50 + * It is claimed that future versions of NSPR will automatically wrap on 1.51 + * the call to PR_GetCurrentThread. 1.52 + * 1.53 + * XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread. 1.54 + * 1.55 + */ 1.56 +#undef _CURRENT_THREAD 1.57 +#ifdef JSD_ATTACH_THREAD_HACK 1.58 +#define _CURRENT_THREAD(out) \ 1.59 +JS_BEGIN_MACRO \ 1.60 + out = (void*) PR_GetCurrentThread(); \ 1.61 + if(!out) \ 1.62 + out = (void*) JS_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, \ 1.63 + nullptr); \ 1.64 + MOZ_ASSERT(out); \ 1.65 +JS_END_MACRO 1.66 +#else 1.67 +#define _CURRENT_THREAD(out) \ 1.68 +JS_BEGIN_MACRO \ 1.69 + out = (void*) PR_GetCurrentThread(); \ 1.70 + MOZ_ASSERT(out); \ 1.71 +JS_END_MACRO 1.72 +#endif 1.73 + 1.74 +#ifdef DEBUG 1.75 +#define JSD_LOCK_SIG 0x10CC10CC 1.76 +void ASSERT_VALID_LOCK(JSDStaticLock* lock) 1.77 +{ 1.78 + MOZ_ASSERT(lock); 1.79 + MOZ_ASSERT(lock->lock); 1.80 + MOZ_ASSERT(lock->count >= 0); 1.81 + MOZ_ASSERT(lock->sig == (uint16_t) JSD_LOCK_SIG); 1.82 +} 1.83 +#else 1.84 +#define ASSERT_VALID_LOCK(x) ((void)0) 1.85 +#endif 1.86 + 1.87 +JSDStaticLock* 1.88 +jsd_CreateLock() 1.89 +{ 1.90 + JSDStaticLock* lock; 1.91 + 1.92 + if( ! (lock = js_pod_calloc<JSDStaticLock>()) || 1.93 + ! (lock->lock = PR_NewLock()) ) 1.94 + { 1.95 + if(lock) 1.96 + { 1.97 + free(lock); 1.98 + lock = nullptr; 1.99 + } 1.100 + } 1.101 +#ifdef DEBUG 1.102 + if(lock) lock->sig = (uint16_t) JSD_LOCK_SIG; 1.103 +#endif 1.104 + return lock; 1.105 +} 1.106 + 1.107 +void 1.108 +jsd_Lock(JSDStaticLock* lock) 1.109 +{ 1.110 + void* me; 1.111 + ASSERT_VALID_LOCK(lock); 1.112 + _CURRENT_THREAD(me); 1.113 + 1.114 + if(lock->owner == me) 1.115 + { 1.116 + lock->count++; 1.117 + MOZ_ASSERT(lock->count > 1); 1.118 + } 1.119 + else 1.120 + { 1.121 + PR_Lock(lock->lock); /* this can block... */ 1.122 + MOZ_ASSERT(lock->owner == 0); 1.123 + MOZ_ASSERT(lock->count == 0); 1.124 + lock->count = 1; 1.125 + lock->owner = me; 1.126 + } 1.127 +} 1.128 + 1.129 +void 1.130 +jsd_Unlock(JSDStaticLock* lock) 1.131 +{ 1.132 + void* me; 1.133 + ASSERT_VALID_LOCK(lock); 1.134 + _CURRENT_THREAD(me); 1.135 + 1.136 + /* it's an error to unlock a lock you don't own */ 1.137 + MOZ_ASSERT(lock->owner == me); 1.138 + if(lock->owner != me) 1.139 + return; 1.140 + 1.141 + if(--lock->count == 0) 1.142 + { 1.143 + lock->owner = nullptr; 1.144 + PR_Unlock(lock->lock); 1.145 + } 1.146 +} 1.147 + 1.148 +#ifdef DEBUG 1.149 +bool 1.150 +jsd_IsLocked(JSDStaticLock* lock) 1.151 +{ 1.152 + void* me; 1.153 + ASSERT_VALID_LOCK(lock); 1.154 + _CURRENT_THREAD(me); 1.155 + if (lock->owner != me) 1.156 + return false; 1.157 + MOZ_ASSERT(lock->count > 0); 1.158 + return true; 1.159 +} 1.160 +#endif /* DEBUG */ 1.161 + 1.162 +void* 1.163 +jsd_CurrentThread() 1.164 +{ 1.165 + void* me; 1.166 + _CURRENT_THREAD(me); 1.167 + return me; 1.168 +} 1.169 + 1.170 + 1.171 +#else /* ! JSD_USE_NSPR_LOCKS */ 1.172 + 1.173 +#ifdef WIN32 1.174 +#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") 1.175 +#pragma message("!! you are compiling the stubbed version of jsd_lock.c !!") 1.176 +#pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") 1.177 +#endif 1.178 + 1.179 +/* 1.180 + * NOTE: 'Real' versions of these locks must be reentrant in the sense that 1.181 + * they support nested calls to lock and unlock. 1.182 + */ 1.183 + 1.184 +void* 1.185 +jsd_CreateLock() 1.186 +{ 1.187 + return (void*)1; 1.188 +} 1.189 + 1.190 +void 1.191 +jsd_Lock(void* lock) 1.192 +{ 1.193 +} 1.194 + 1.195 +void 1.196 +jsd_Unlock(void* lock) 1.197 +{ 1.198 +} 1.199 + 1.200 +#ifdef DEBUG 1.201 +bool 1.202 +jsd_IsLocked(void* lock) 1.203 +{ 1.204 + return true; 1.205 +} 1.206 +#endif /* DEBUG */ 1.207 + 1.208 +/* 1.209 + * This Windows only thread id code is here to allow the Java-based 1.210 + * JSDebugger to work with the single threaded js.c shell (even without 1.211 + * real locking and threading support). 1.212 + */ 1.213 + 1.214 +#ifdef WIN32 1.215 +/* bogus (but good enough) declaration*/ 1.216 +extern void* __stdcall GetCurrentThreadId(void); 1.217 +#endif 1.218 + 1.219 +void* 1.220 +jsd_CurrentThread() 1.221 +{ 1.222 +#ifdef WIN32 1.223 + return GetCurrentThreadId(); 1.224 +#else 1.225 + return (void*)1; 1.226 +#endif 1.227 +} 1.228 + 1.229 +#endif /* JSD_USE_NSPR_LOCKS */ 1.230 + 1.231 +#endif /* JSD_THREADSAFE */