Mercurial > hg > graal-compiler
diff src/os/windows/vm/threadCritical_windows.cpp @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | c18cbe5936b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/windows/vm/threadCritical_windows.cpp Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright 2001-2003 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +# include "incls/_precompiled.incl" +# include "incls/_threadCritical_windows.cpp.incl" + +// OS-includes here +# include <windows.h> +# include <winbase.h> + +// +// See threadCritical.hpp for details of this class. +// + +static bool initialized = false; +static volatile jint lock_count = -1; +static HANDLE lock_event; +static DWORD lock_owner = -1; + +// +// Note that Microsoft's critical region code contains a race +// condition, and is not suitable for use. A thread holding the +// critical section cannot safely suspend a thread attempting +// to enter the critical region. The failure mode is that both +// threads are permanently suspended. +// +// I experiemented with the use of ordinary windows mutex objects +// and found them ~30 times slower than the critical region code. +// + +void ThreadCritical::initialize() { +} + +void ThreadCritical::release() { + assert(lock_owner == -1, "Mutex being deleted while owned."); + assert(lock_count == -1, "Mutex being deleted while recursively locked"); + assert(lock_event != NULL, "Sanity check"); + CloseHandle(lock_event); +} + +ThreadCritical::ThreadCritical() { + DWORD current_thread = GetCurrentThreadId(); + + if (lock_owner != current_thread) { + // Grab the lock before doing anything. + while (Atomic::cmpxchg(0, &lock_count, -1) != -1) { + if (initialized) { + DWORD ret = WaitForSingleObject(lock_event, INFINITE); + assert(ret == WAIT_OBJECT_0, "unexpected return value from WaitForSingleObject"); + } + } + + // Make sure the event object is allocated. + if (!initialized) { + // Locking will not work correctly unless this is autoreset. + lock_event = CreateEvent(NULL, false, false, NULL); + initialized = true; + } + + assert(lock_owner == -1, "Lock acquired illegally."); + lock_owner = current_thread; + } else { + // Atomicity isn't required. Bump the recursion count. + lock_count++; + } + + assert(lock_owner == GetCurrentThreadId(), "Lock acquired illegally."); +} + +ThreadCritical::~ThreadCritical() { + assert(lock_owner == GetCurrentThreadId(), "unlock attempt by wrong thread"); + assert(lock_count >= 0, "Attempt to unlock when already unlocked"); + + if (lock_count == 0) { + // We're going to unlock + lock_owner = -1; + lock_count = -1; + // No lost wakeups, lock_event stays signaled until reset. + DWORD ret = SetEvent(lock_event); + assert(ret != 0, "unexpected return value from SetEvent"); + } else { + // Just unwinding a recursive lock; + lock_count--; + } +}