src/os/windows/vm/threadCritical_windows.cpp

changeset 435
a61af66fc99e
child 1907
c18cbe5936b8
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/os/windows/vm/threadCritical_windows.cpp	Sat Dec 01 00:00:00 2007 +0000
     1.3 @@ -0,0 +1,106 @@
     1.4 +/*
     1.5 + * Copyright 2001-2003 Sun Microsystems, Inc.  All Rights Reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    1.24 + * have any questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +# include "incls/_precompiled.incl"
    1.29 +# include "incls/_threadCritical_windows.cpp.incl"
    1.30 +
    1.31 +// OS-includes here
    1.32 +# include <windows.h>
    1.33 +# include <winbase.h>
    1.34 +
    1.35 +//
    1.36 +// See threadCritical.hpp for details of this class.
    1.37 +//
    1.38 +
    1.39 +static bool initialized = false;
    1.40 +static volatile jint lock_count = -1;
    1.41 +static HANDLE lock_event;
    1.42 +static DWORD lock_owner = -1;
    1.43 +
    1.44 +//
    1.45 +// Note that Microsoft's critical region code contains a race
    1.46 +// condition, and is not suitable for use. A thread holding the
    1.47 +// critical section cannot safely suspend a thread attempting
    1.48 +// to enter the critical region. The failure mode is that both
    1.49 +// threads are permanently suspended.
    1.50 +//
    1.51 +// I experiemented with the use of ordinary windows mutex objects
    1.52 +// and found them ~30 times slower than the critical region code.
    1.53 +//
    1.54 +
    1.55 +void ThreadCritical::initialize() {
    1.56 +}
    1.57 +
    1.58 +void ThreadCritical::release() {
    1.59 +  assert(lock_owner == -1, "Mutex being deleted while owned.");
    1.60 +  assert(lock_count == -1, "Mutex being deleted while recursively locked");
    1.61 +  assert(lock_event != NULL, "Sanity check");
    1.62 +  CloseHandle(lock_event);
    1.63 +}
    1.64 +
    1.65 +ThreadCritical::ThreadCritical() {
    1.66 +  DWORD current_thread = GetCurrentThreadId();
    1.67 +
    1.68 +  if (lock_owner != current_thread) {
    1.69 +    // Grab the lock before doing anything.
    1.70 +    while (Atomic::cmpxchg(0, &lock_count, -1) != -1) {
    1.71 +      if (initialized) {
    1.72 +        DWORD ret = WaitForSingleObject(lock_event,  INFINITE);
    1.73 +        assert(ret == WAIT_OBJECT_0, "unexpected return value from WaitForSingleObject");
    1.74 +      }
    1.75 +    }
    1.76 +
    1.77 +    // Make sure the event object is allocated.
    1.78 +    if (!initialized) {
    1.79 +      // Locking will not work correctly unless this is autoreset.
    1.80 +      lock_event = CreateEvent(NULL, false, false, NULL);
    1.81 +      initialized = true;
    1.82 +    }
    1.83 +
    1.84 +    assert(lock_owner == -1, "Lock acquired illegally.");
    1.85 +    lock_owner = current_thread;
    1.86 +  } else {
    1.87 +    // Atomicity isn't required. Bump the recursion count.
    1.88 +    lock_count++;
    1.89 +  }
    1.90 +
    1.91 +  assert(lock_owner == GetCurrentThreadId(), "Lock acquired illegally.");
    1.92 +}
    1.93 +
    1.94 +ThreadCritical::~ThreadCritical() {
    1.95 +  assert(lock_owner == GetCurrentThreadId(), "unlock attempt by wrong thread");
    1.96 +  assert(lock_count >= 0, "Attempt to unlock when already unlocked");
    1.97 +
    1.98 +  if (lock_count == 0) {
    1.99 +    // We're going to unlock
   1.100 +    lock_owner = -1;
   1.101 +    lock_count = -1;
   1.102 +    // No lost wakeups, lock_event stays signaled until reset.
   1.103 +    DWORD ret = SetEvent(lock_event);
   1.104 +    assert(ret != 0, "unexpected return value from SetEvent");
   1.105 +  } else {
   1.106 +    // Just unwinding a recursive lock;
   1.107 +    lock_count--;
   1.108 +  }
   1.109 +}

mercurial