⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jslock.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */#ifdef JS_THREADSAFE/* * JS locking stubs. */#include "jsstddef.h"#include <stdlib.h>#include "jspubtd.h"#include "jsutil.h" /* Added by JSIFY */#include "jstypes.h"#include "jsbit.h"#include "jscntxt.h"#include "jsdtoa.h"#include "jsgc.h"#include "jslock.h"#include "jsscope.h"#include "jsstr.h"#define ReadWord(W) (W)#ifndef NSPR_LOCK#include <memory.h>static PRLock **global_locks;static uint32 global_lock_count = 1;static uint32 global_locks_log2 = 0;static uint32 global_locks_mask = 0;#define GLOBAL_LOCK_INDEX(id)   (((uint32)(id) >> 2) & global_locks_mask)static voidjs_LockGlobal(void *id){    uint32 i = GLOBAL_LOCK_INDEX(id);    PR_Lock(global_locks[i]);}static voidjs_UnlockGlobal(void *id){    uint32 i = GLOBAL_LOCK_INDEX(id);    PR_Unlock(global_locks[i]);}/* Exclude Alpha NT. */#if defined(_WIN32) && defined(_M_IX86)#pragma warning( disable : 4035 )static JS_INLINE intjs_CompareAndSwap(jsword *w, jsword ov, jsword nv){    __asm {        mov eax, ov        mov ecx, nv        mov ebx, w        lock cmpxchg [ebx], ecx        sete al        and eax, 1h    }}#elif defined(__GNUC__) && defined(__i386__)/* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */static JS_INLINE intjs_CompareAndSwap(jsword *w, jsword ov, jsword nv){    unsigned int res;    __asm__ __volatile__ (                          "lock\n"                          "cmpxchgl %2, (%1)\n"                          "sete %%al\n"                          "andl $1, %%eax\n"                          : "=a" (res)                          : "r" (w), "r" (nv), "a" (ov)                          : "cc", "memory");    return (int)res;}#elif (defined(__USLC__) || defined(_SCO_DS)) && defined(i386)/* Note: This fails on 386 cpus, cmpxchgl is a >= 486 instruction */asm intjs_CompareAndSwap(jsword *w, jsword ov, jsword nv){%ureg w, nv;	movl	ov,%eax	lock	cmpxchgl nv,(w)	sete	%al	andl	$1,%eax%ureg w;  mem ov, nv;	movl	ov,%eax	movl	nv,%ecx	lock	cmpxchgl %ecx,(w)	sete	%al	andl	$1,%eax%ureg nv;	movl	ov,%eax	movl	w,%edx	lock	cmpxchgl nv,(%edx)	sete	%al	andl	$1,%eax%mem w, ov, nv;	movl	ov,%eax	movl	nv,%ecx	movl	w,%edx	lock	cmpxchgl %ecx,(%edx)	sete	%al	andl	$1,%eax}#pragma asm full_optimization js_CompareAndSwap#elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC)static JS_INLINE intjs_CompareAndSwap(jsword *w, jsword ov, jsword nv){#if defined(__GNUC__)    unsigned int res;    JS_ASSERT(ov != nv);    asm volatile ("\stbar\n\cas [%1],%2,%3\n\cmp %2,%3\n\be,a 1f\n\mov 1,%0\n\mov 0,%0\n\1:"                  : "=r" (res)                  : "r" (w), "r" (ov), "r" (nv));    return (int)res;#else /* !__GNUC__ */    extern int compare_and_swap(jsword*, jsword, jsword);    JS_ASSERT(ov != nv);    return compare_and_swap(w, ov, nv);#endif}#elif defined(AIX)#include <sys/atomic_op.h>static JS_INLINE intjs_CompareAndSwap(jsword *w, jsword ov, jsword nv){    return !_check_lock((atomic_p)w, ov, nv);}#else#error "Define NSPR_LOCK if your platform lacks a compare-and-swap instruction."#endif /* arch-tests */#endif /* !NSPR_LOCK */voidjs_InitLock(JSThinLock *tl){#ifdef NSPR_LOCK    tl->owner = 0;    tl->fat = (JSFatLock*)JS_NEW_LOCK();#else    memset(tl, 0, sizeof(JSThinLock));#endif}voidjs_FinishLock(JSThinLock *tl){#ifdef NSPR_LOCK    tl->owner = 0xdeadbeef;    if (tl->fat)        JS_DESTROY_LOCK(((JSLock*)tl->fat));#else    JS_ASSERT(tl->owner == 0);    JS_ASSERT(tl->fat == NULL);#endif}static void js_Dequeue(JSThinLock *);#ifdef DEBUG_SCOPE_COUNT#include <stdio.h>#include "jsdhash.h"static FILE *logfp;static JSDHashTable logtbl;typedef struct logentry {    JSDHashEntryStub stub;    char             op;    const char       *file;    int              line;} logentry;static voidlogit(JSScope *scope, char op, const char *file, int line){    logentry *entry;    if (!logfp) {        logfp = fopen("/tmp/scope.log", "w");        if (!logfp)            return;        setvbuf(logfp, NULL, _IONBF, 0);    }    fprintf(logfp, "%p %c %s %d\n", scope, op, file, line);    if (!logtbl.entryStore &&        !JS_DHashTableInit(&logtbl, JS_DHashGetStubOps(), NULL,                           sizeof(logentry), 100)) {        return;    }    entry = (logentry *) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_ADD);    if (!entry)        return;    entry->stub.key = scope;    entry->op = op;    entry->file = file;    entry->line = line;}voidjs_unlog_scope(JSScope *scope){    if (!logtbl.entryStore)        return;    (void) JS_DHashTableOperate(&logtbl, scope, JS_DHASH_REMOVE);}# define LOGIT(scope,op) logit(scope, op, __FILE__, __LINE__)#else# define LOGIT(scope,op) /* nothing */#endif /* DEBUG_SCOPE_COUNT *//* * Return true if scope's ownercx, or the ownercx of a single-threaded scope * for which ownercx is waiting to become multi-threaded and shared, is cx. * That condition implies deadlock in ClaimScope if cx's thread were to wait * to share scope. * * (i) rt->gcLock held */static JSBoolWillDeadlock(JSScope *scope, JSContext *cx){    JSContext *ownercx;    do {        ownercx = scope->ownercx;        if (ownercx == cx) {            JS_RUNTIME_METER(cx->runtime, deadlocksAvoided);            return JS_TRUE;        }    } while (ownercx && (scope = ownercx->scopeToShare) != NULL);    return JS_FALSE;}/* * Make scope multi-threaded, i.e. share its ownership among contexts in rt * using a "thin" or (if necessary due to contention) "fat" lock.  Called only * from ClaimScope, immediately below, when we detect deadlock were we to wait * for scope's lock, because its ownercx is waiting on a scope owned by the * calling cx. * * (i) rt->gcLock held */static voidShareScope(JSRuntime *rt, JSScope *scope){    JSScope **todop;    if (scope->u.link) {        for (todop = &rt->scopeSharingTodo; *todop != scope;             todop = &(*todop)->u.link) {            JS_ASSERT(*todop != NO_SCOPE_SHARING_TODO);        }        *todop = scope->u.link;        scope->u.link = NULL;       /* null u.link for sanity ASAP */        JS_NOTIFY_ALL_CONDVAR(rt->scopeSharingDone);    }    js_InitLock(&scope->lock);    if (scope == rt->setSlotScope) {        /*         * Nesting locks on another thread that's using scope->ownercx: give         * the held lock a reentrancy count of 1 and set its lock.owner field         * directly (no compare-and-swap needed while scope->ownercx is still         * non-null).  See below in ClaimScope, before the ShareScope call,         * for more on why this is necessary.         *         * If NSPR_LOCK is defined, we cannot deadlock holding rt->gcLock and         * acquiring scope->lock.fat here, against another thread holding that         * fat lock and trying to grab rt->gcLock.  This is because no other         * thread can attempt to acquire scope->lock.fat until scope->ownercx         * is null *and* our thread has released rt->gcLock, which interlocks         * scope->ownercx's transition to null against tests of that member         * in ClaimScope.         */        scope->lock.owner = CX_THINLOCK_ID(scope->ownercx);#ifdef NSPR_LOCK        JS_ACQUIRE_LOCK((JSLock*)scope->lock.fat);#endif        scope->u.count = 1;    } else {        scope->u.count = 0;    }    js_FinishSharingScope(rt, scope);}/* * js_FinishSharingScope is the tail part of ShareScope, split out to become a * subroutine of JS_EndRequest too.  The bulk of the work here involves making * mutable strings in the scope's object's slots be immutable.  We have to do * this because such strings will soon be available to multiple threads, so * their buffers can't be realloc'd any longer in js_ConcatStrings, and their * members can't be modified by js_ConcatStrings, js_MinimizeDependentStrings, * or js_UndependString. * * The last bit of work done by js_FinishSharingScope nulls scope->ownercx and * updates rt->sharedScopes. */#define MAKE_STRING_IMMUTABLE(rt, v, vp)                                      \    JS_BEGIN_MACRO                                                            \        JSString *str_ = JSVAL_TO_STRING(v);                                  \        uint8 *flagp_ = js_GetGCThingFlags(str_);                             \        if (*flagp_ & GCF_MUTABLE) {                                          \            if (JSSTRING_IS_DEPENDENT(str_) &&                                \                !js_UndependString(NULL, str_)) {                             \                JS_RUNTIME_METER(rt, badUndependStrings);                     \                *vp = JSVAL_VOID;                                             \            } else {                                                          \                *flagp_ &= ~GCF_MUTABLE;                                      \            }                                                                 \        }                                                                     \    JS_END_MACROvoidjs_FinishSharingScope(JSRuntime *rt, JSScope *scope){    JSObject *obj;    uint32 nslots;    jsval v, *vp, *end;    obj = scope->object;    nslots = JS_MIN(obj->map->freeslot, obj->map->nslots);    for (vp = obj->slots, end = vp + nslots; vp < end; vp++) {        v = *vp;        if (JSVAL_IS_STRING(v))            MAKE_STRING_IMMUTABLE(rt, v, vp);    }    scope->ownercx = NULL;  /* NB: set last, after lock init */    JS_RUNTIME_METER(rt, sharedScopes);}/* * Given a scope with apparently non-null ownercx different from cx, try to * set ownercx to cx, claiming exclusive (single-threaded) ownership of scope. * If we claim ownership, return true.  Otherwise, we wait for ownercx to be * set to null (indicating that scope is multi-threaded); or if waiting would * deadlock, we set ownercx to null ourselves via ShareScope.  In any case, * once ownercx is null we return false. */static JSBoolClaimScope(JSScope *scope, JSContext *cx){    JSRuntime *rt;    JSContext *ownercx;    jsrefcount saveDepth;    PRStatus stat;    rt = cx->runtime;    JS_RUNTIME_METER(rt, claimAttempts);    JS_LOCK_GC(rt);    /* Reload in case ownercx went away while we blocked on the lock. */    while ((ownercx = scope->ownercx) != NULL) {        /*         * Avoid selflock if ownercx is dead, or is not running a request, or         * has the same thread as cx.  Set scope->ownercx to cx so that the         * matching JS_UNLOCK_SCOPE or JS_UNLOCK_OBJ macro call will take the         * fast path around the corresponding js_UnlockScope or js_UnlockObj         * function call.         *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -