Back to index

lightning-sunbird  0.9+nobinonly
jsd_lock.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039  * JavaScript Debugging support - Locking and threading support
00040  */
00041 
00042 /*                                                                           
00043 * ifdef JSD_USE_NSPR_LOCKS then you musat build and run against NSPR2.       
00044 * Otherwise, there are stubs that can be filled in with your own locking     
00045 * code. Also, note that these stubs include a jsd_CurrentThread()            
00046 * implementation that only works on Win32 - this is needed for the inprocess 
00047 * Java-based debugger.                                                       
00048 */                                                                           
00049 
00050 #include "jsd.h"
00051 
00052 #ifdef JSD_THREADSAFE
00053 
00054 #ifdef JSD_USE_NSPR_LOCKS
00055 
00056 #include "prlock.h"
00057 #include "prthread.h"
00058 
00059 #ifdef JSD_ATTACH_THREAD_HACK
00060 #include "pprthred.h"   /* need this as long as JS_AttachThread is needed */
00061 #endif
00062 
00063 struct JSDStaticLock
00064 {
00065     void*     owner;
00066     PRLock*   lock;
00067     int       count;
00068 #ifdef DEBUG
00069     uint16    sig;
00070 #endif
00071 };
00072 
00073 /* 
00074  * This exists to wrap non-NSPR theads (e.g. Java threads) in NSPR wrappers.
00075  * XXX We ignore the memory leak issue.
00076  * It is claimed that future versions of NSPR will automatically wrap on 
00077  * the call to PR_GetCurrentThread.
00078  *
00079  * XXX We ignore the memory leak issue - i.e. we never call PR_DetachThread.
00080  *
00081  */
00082 #undef _CURRENT_THREAD
00083 #ifdef JSD_ATTACH_THREAD_HACK
00084 #define _CURRENT_THREAD(out)                                                  \
00085 JS_BEGIN_MACRO                                                                \
00086     out = (void*) PR_GetCurrentThread();                                      \
00087     if(!out)                                                                  \
00088         out = (void*) JS_AttachThread(PR_USER_THREAD,PR_PRIORITY_NORMAL,NULL);\
00089     JS_ASSERT(out);                                                           \
00090 JS_END_MACRO
00091 #else
00092 #define _CURRENT_THREAD(out)             \
00093 JS_BEGIN_MACRO                           \
00094     out = (void*) PR_GetCurrentThread(); \
00095     JS_ASSERT(out);                      \
00096 JS_END_MACRO
00097 #endif
00098 
00099 #ifdef DEBUG
00100 #define JSD_LOCK_SIG 0x10CC10CC
00101 void ASSERT_VALID_LOCK(JSDStaticLock* lock)
00102 {
00103     JS_ASSERT(lock);
00104     JS_ASSERT(lock->lock);
00105     JS_ASSERT(lock->count >= 0);
00106     JS_ASSERT((! lock->count && ! lock->owner) || (lock->count && lock->owner));
00107     JS_ASSERT(lock->sig == (uint16) JSD_LOCK_SIG);
00108 }    
00109 #else
00110 #define ASSERT_VALID_LOCK(x) ((void)0)
00111 #endif
00112 
00113 void*
00114 jsd_CreateLock()
00115 {
00116     JSDStaticLock* lock;
00117 
00118     if( ! (lock = calloc(1, sizeof(JSDStaticLock))) || 
00119         ! (lock->lock = PR_NewLock()) )
00120     {
00121         if(lock)
00122         {
00123             free(lock);
00124             lock = NULL;
00125         }
00126     }
00127 #ifdef DEBUG
00128     if(lock) lock->sig = (uint16) JSD_LOCK_SIG;
00129 #endif
00130     return lock;
00131 }    
00132 
00133 void
00134 jsd_Lock(JSDStaticLock* lock)
00135 {
00136     void* me;
00137 
00138     _CURRENT_THREAD(me);
00139 
00140     ASSERT_VALID_LOCK(lock);
00141 
00142     if(lock->owner == me)
00143         lock->count++;
00144     else
00145     {
00146         PR_Lock(lock->lock);            /* this can block... */
00147         JS_ASSERT(lock->owner == 0);
00148         lock->count = 1;
00149         lock->owner = me;
00150     }
00151     ASSERT_VALID_LOCK(lock);
00152 }    
00153 
00154 void
00155 jsd_Unlock(JSDStaticLock* lock)
00156 {
00157     void* me;
00158 
00159     ASSERT_VALID_LOCK(lock);
00160     _CURRENT_THREAD(me);
00161 
00162     if(lock->owner != me)
00163     {
00164         JS_ASSERT(0);   /* it's an error to unlock a lock you don't own */
00165         return;
00166     }
00167     if(--lock->count == 0)
00168     {
00169         lock->owner = NULL;
00170         PR_Unlock(lock->lock);
00171     }
00172     ASSERT_VALID_LOCK(lock);
00173 }    
00174 
00175 #ifdef DEBUG
00176 JSBool
00177 jsd_IsLocked(JSDStaticLock* lock)
00178 {
00179     void* me;
00180     ASSERT_VALID_LOCK(lock);
00181     _CURRENT_THREAD(me);
00182     return lock->owner == me ? JS_TRUE : JS_FALSE;
00183 }    
00184 #endif /* DEBUG */
00185 
00186 void*
00187 jsd_CurrentThread()
00188 {
00189     void* me;
00190     _CURRENT_THREAD(me);
00191     return me;
00192 }    
00193 
00194 
00195 #else  /* ! JSD_USE_NSPR_LOCKS */
00196 
00197 #ifdef WIN32    
00198 #pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
00199 #pragma message("!! you are compiling the stubbed version of jsd_lock.c !!")
00200 #pragma message("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!")
00201 #endif
00202 
00203 /*
00204  * NOTE: 'Real' versions of these locks must be reentrant in the sense that 
00205  * they support nested calls to lock and unlock. 
00206  */
00207 
00208 void*
00209 jsd_CreateLock()
00210 {
00211     return (void*)1;
00212 }    
00213 
00214 void
00215 jsd_Lock(void* lock)
00216 {
00217 }    
00218 
00219 void
00220 jsd_Unlock(void* lock)
00221 {
00222 }    
00223 
00224 #ifdef DEBUG
00225 JSBool
00226 jsd_IsLocked(void* lock)
00227 {
00228     return JS_TRUE;
00229 }    
00230 #endif /* DEBUG */
00231 
00232 /* 
00233  * This Windows only thread id code is here to allow the Java-based 
00234  * JSDebugger to work with the single threaded js.c shell (even without 
00235  * real locking and threading support).
00236  */
00237 
00238 #ifdef WIN32    
00239 /* bogus (but good enough) declaration*/
00240 extern void* __stdcall GetCurrentThreadId(void);
00241 #endif
00242 
00243 void*
00244 jsd_CurrentThread()
00245 {
00246 #ifdef WIN32    
00247     return GetCurrentThreadId();
00248 #else
00249     return (void*)1;
00250 #endif
00251 }    
00252 
00253 #endif /* JSD_USE_NSPR_LOCKS */
00254 
00255 #endif /* JSD_THREADSAFE */