Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / jslock.h
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  *
3  * ***** BEGIN LICENSE BLOCK *****
4  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5  *
6  * The contents of this file are subject to the Mozilla Public License Version
7  * 1.1 (the "License"); you may not use this file except in compliance with
8  * the License. You may obtain a copy of the License at
9  * http://www.mozilla.org/MPL/
10  *
11  * Software distributed under the License is distributed on an "AS IS" basis,
12  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13  * for the specific language governing rights and limitations under the
14  * License.
15  *
16  * The Original Code is Mozilla Communicator client code, released
17  * March 31, 1998.
18  *
19  * The Initial Developer of the Original Code is
20  * Netscape Communications Corporation.
21  * Portions created by the Initial Developer are Copyright (C) 1998
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Alternatively, the contents of this file may be used under the terms of
27  * either of the GNU General Public License Version 2 or later (the "GPL"),
28  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29  * in which case the provisions of the GPL or the LGPL are applicable instead
30  * of those above. If you wish to allow use of your version of this file only
31  * under the terms of either the GPL or the LGPL, and not to allow others to
32  * use your version of this file under the terms of the MPL, indicate your
33  * decision by deleting the provisions above and replace them with the notice
34  * and other provisions required by the GPL or the LGPL. If you do not delete
35  * the provisions above, a recipient may use your version of this file under
36  * the terms of any one of the MPL, the GPL or the LGPL.
37  *
38  * ***** END LICENSE BLOCK ***** */
39 #ifndef jslock_h__
40 #define jslock_h__
41
42 #include "jstypes.h"
43 #include "jsapi.h"
44 #include "jsprvtd.h"
45
46 #ifdef JS_THREADSAFE
47 # include "pratom.h"
48 # include "prlock.h"
49 # include "prcvar.h"
50 # include "prthread.h"
51 #endif
52
53 JS_BEGIN_EXTERN_C
54
55 #ifdef JS_THREADSAFE
56
57 #if (defined(_WIN32) && defined(_M_IX86)) ||                                  \
58     (defined(_WIN64) && (defined(_M_AMD64) || defined(_M_X64))) ||            \
59     (defined(__i386) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||       \
60     (defined(__x86_64) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||     \
61     (defined(__sparc) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||      \
62     defined(AIX) ||                                                           \
63     defined(USE_ARM_KUSER)
64 # define JS_HAS_NATIVE_COMPARE_AND_SWAP 1
65 #else
66 # define JS_HAS_NATIVE_COMPARE_AND_SWAP 0
67 #endif
68
69 #if defined(JS_USE_ONLY_NSPR_LOCKS) || !JS_HAS_NATIVE_COMPARE_AND_SWAP
70 # define NSPR_LOCK 1
71 #else
72 # undef NSPR_LOCK
73 #endif
74
75 #define Thin_GetWait(W) ((jsword)(W) & 0x1)
76 #define Thin_SetWait(W) ((jsword)(W) | 0x1)
77 #define Thin_RemoveWait(W) ((jsword)(W) & ~0x1)
78
79 typedef struct JSFatLock JSFatLock;
80
81 typedef struct JSThinLock {
82     jsword      owner;
83     JSFatLock   *fat;
84 } JSThinLock;
85
86 #define CX_THINLOCK_ID(cx)       ((jsword)(cx)->thread)
87 #define CURRENT_THREAD_IS_ME(me) (((JSThread *)me)->id == js_CurrentThreadId())
88
89 typedef PRLock JSLock;
90
91 /*
92  * Atomic increment and decrement for a reference counter, given jsrefcount *p.
93  * NB: jsrefcount is int32, aka PRInt32, so that pratom.h functions work.
94  */
95 #define JS_ATOMIC_INCREMENT(p)      PR_AtomicIncrement((PRInt32 *)(p))
96 #define JS_ATOMIC_DECREMENT(p)      PR_AtomicDecrement((PRInt32 *)(p))
97 #define JS_ATOMIC_ADD(p,v)          PR_AtomicAdd((PRInt32 *)(p), (PRInt32)(v))
98 #define JS_ATOMIC_SET(p,v)          PR_AtomicSet((PRInt32 *)(p), (PRInt32)(v))
99
100 #define js_CurrentThreadId()        PR_GetCurrentThread()
101 #define JS_NEW_LOCK()               PR_NewLock()
102 #define JS_DESTROY_LOCK(l)          PR_DestroyLock(l)
103 #define JS_ACQUIRE_LOCK(l)          PR_Lock(l)
104 #define JS_RELEASE_LOCK(l)          PR_Unlock(l)
105
106 #define JS_NEW_CONDVAR(l)           PR_NewCondVar(l)
107 #define JS_DESTROY_CONDVAR(cv)      PR_DestroyCondVar(cv)
108 #define JS_WAIT_CONDVAR(cv,to)      PR_WaitCondVar(cv,to)
109 #define JS_NO_TIMEOUT               PR_INTERVAL_NO_TIMEOUT
110 #define JS_NOTIFY_CONDVAR(cv)       PR_NotifyCondVar(cv)
111 #define JS_NOTIFY_ALL_CONDVAR(cv)   PR_NotifyAllCondVar(cv)
112
113 #define JS_LOCK(cx, tl)             js_Lock(cx, tl)
114 #define JS_UNLOCK(cx, tl)           js_Unlock(cx, tl)
115
116 #define JS_LOCK_RUNTIME(rt)         js_LockRuntime(rt)
117 #define JS_UNLOCK_RUNTIME(rt)       js_UnlockRuntime(rt)
118
119 extern void js_Lock(JSContext *cx, JSThinLock *tl);
120 extern void js_Unlock(JSContext *cx, JSThinLock *tl);
121 extern void js_LockRuntime(JSRuntime *rt);
122 extern void js_UnlockRuntime(JSRuntime *rt);
123 extern int js_SetupLocks(int,int);
124 extern void js_CleanupLocks();
125 extern void js_InitLock(JSThinLock *);
126 extern void js_FinishLock(JSThinLock *);
127
128 #ifdef DEBUG
129
130 #define JS_IS_RUNTIME_LOCKED(rt)        js_IsRuntimeLocked(rt)
131
132 extern JSBool js_IsRuntimeLocked(JSRuntime *rt);
133
134 #else
135
136 #define JS_IS_RUNTIME_LOCKED(rt)        0
137
138 #endif /* DEBUG */
139
140 #else  /* !JS_THREADSAFE */
141
142 #define JS_ATOMIC_INCREMENT(p)      (++*(p))
143 #define JS_ATOMIC_DECREMENT(p)      (--*(p))
144 #define JS_ATOMIC_ADD(p,v)          (*(p) += (v))
145 #define JS_ATOMIC_SET(p,v)          (*(p) = (v))
146
147 #define JS_CurrentThreadId() 0
148 #define JS_NEW_LOCK()               NULL
149 #define JS_DESTROY_LOCK(l)          ((void)0)
150 #define JS_ACQUIRE_LOCK(l)          ((void)0)
151 #define JS_RELEASE_LOCK(l)          ((void)0)
152 #define JS_LOCK(cx, tl)             ((void)0)
153 #define JS_UNLOCK(cx, tl)           ((void)0)
154
155 #define JS_NEW_CONDVAR(l)           NULL
156 #define JS_DESTROY_CONDVAR(cv)      ((void)0)
157 #define JS_WAIT_CONDVAR(cv,to)      ((void)0)
158 #define JS_NOTIFY_CONDVAR(cv)       ((void)0)
159 #define JS_NOTIFY_ALL_CONDVAR(cv)   ((void)0)
160
161 #define JS_LOCK_RUNTIME(rt)         ((void)0)
162 #define JS_UNLOCK_RUNTIME(rt)       ((void)0)
163
164 #define JS_IS_RUNTIME_LOCKED(rt)        1
165
166 #endif /* !JS_THREADSAFE */
167
168 #define JS_LOCK_RUNTIME_VOID(rt,e)                                            \
169     JS_BEGIN_MACRO                                                            \
170         JS_LOCK_RUNTIME(rt);                                                  \
171         e;                                                                    \
172         JS_UNLOCK_RUNTIME(rt);                                                \
173     JS_END_MACRO
174
175 #define JS_LOCK_GC(rt)              JS_ACQUIRE_LOCK((rt)->gcLock)
176 #define JS_UNLOCK_GC(rt)            JS_RELEASE_LOCK((rt)->gcLock)
177 #define JS_AWAIT_GC_DONE(rt)        JS_WAIT_CONDVAR((rt)->gcDone, JS_NO_TIMEOUT)
178 #define JS_NOTIFY_GC_DONE(rt)       JS_NOTIFY_ALL_CONDVAR((rt)->gcDone)
179 #define JS_AWAIT_REQUEST_DONE(rt)   JS_WAIT_CONDVAR((rt)->requestDone,        \
180                                                     JS_NO_TIMEOUT)
181 #define JS_NOTIFY_REQUEST_DONE(rt)  JS_NOTIFY_CONDVAR((rt)->requestDone)
182
183 #ifndef JS_SET_OBJ_INFO
184 #define JS_SET_OBJ_INFO(obj,f,l)        ((void)0)
185 #endif
186 #ifndef JS_SET_TITLE_INFO
187 #define JS_SET_TITLE_INFO(title,f,l)    ((void)0)
188 #endif
189
190 #ifdef JS_THREADSAFE
191
192 extern JSBool
193 js_CompareAndSwap(volatile jsword *w, jsword ov, jsword nv);
194
195 /* Atomically bitwise-or the mask into the word *w using compare and swap. */
196 extern void
197 js_AtomicSetMask(volatile jsword *w, jsword mask);
198
199 /*
200  * Atomically bitwise-and the complement of the mask into the word *w using
201  * compare and swap.
202  */
203 extern void
204 js_AtomicClearMask(volatile jsword *w, jsword mask);
205
206 #define JS_ATOMIC_SET_MASK(w, mask) js_AtomicSetMask(w, mask)
207 #define JS_ATOMIC_CLEAR_MASK(w, mask) js_AtomicClearMask(w, mask)
208
209 #else
210
211 static inline JSBool
212 js_CompareAndSwap(jsword *w, jsword ov, jsword nv)
213 {
214     return (*w == ov) ? *w = nv, JS_TRUE : JS_FALSE;
215 }
216
217 #define JS_ATOMIC_SET_MASK(w, mask) (*(w) |= (mask))
218 #define JS_ATOMIC_CLEAR_MASK(w, mask) (*(w) &= ~(mask))
219
220 #endif /* JS_THREADSAFE */
221
222 JS_END_EXTERN_C
223
224 #if defined JS_THREADSAFE && defined __cplusplus
225 namespace js {
226
227 class AutoLock {
228   private:
229     JSLock *lock;
230
231   public:
232     AutoLock(JSLock *lock) : lock(lock) { JS_ACQUIRE_LOCK(lock); }
233     ~AutoLock() { JS_RELEASE_LOCK(lock); }
234 };
235
236 }
237 #endif
238
239 #endif /* jslock_h___ */