hotspot/agent/src/os/win32/Monitor.cpp
author never
Mon, 04 May 2009 22:06:47 -0700
changeset 2744 57f0579fbe09
parent 1 489c9b5090e2
child 5547 f4b087cbb361
permissions -rw-r--r--
6837224: libsaproc.so on linux needs version of 6799141 Reviewed-by: kvn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
489c9b5090e2 Initial load
duke
parents:
diff changeset
     2
 * Copyright 2001 Sun Microsystems, Inc.  All Rights Reserved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
#include <stdio.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
#include <assert.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
#include "Monitor.hpp"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
Monitor::Monitor() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
  _lock_count = -1;       // No threads have entered the critical section
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
  _owner = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
  _lock_event = CreateEvent(NULL, false, false, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
  _wait_event = CreateEvent(NULL, true, false, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
  _counter = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
  _tickets = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
  _waiters = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
Monitor::~Monitor() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
  assert(_owner == NULL);    // Otherwise, owned monitor being deleted
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
  assert(_lock_count == -1); // Otherwise, monitor being deleted with non -1 lock count
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
  CloseHandle(_lock_event);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
  CloseHandle(_wait_event);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
Monitor::lock() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  if (InterlockedIncrement(&_lock_count) == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
    // Success, we now own the lock
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
    DWORD dwRet = WaitForSingleObject((HANDLE)_lock_event,  INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
    assert(dwRet == WAIT_OBJECT_0); // Unexpected return value from WaitForSingleObject
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  assert(owner() == NULL); // Otherwise, lock count and owner are inconsistent
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  setOwner(GetCurrentThread());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
Monitor::unlock() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  setOwner(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
  if (InterlockedDecrement(&_lock_count) >= 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
    // Wake a waiting thread up
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
    DWORD dwRet = SetEvent(_lock_event);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
    assert(dwRet != 0); // Unexpected return value from SetEvent
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
bool
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
Monitor::wait(long timeout) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  assert(owner() != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  assert(owner() == GetCurrentThread());
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
  // 0 means forever. Convert to Windows specific code.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
  DWORD timeout_value = (timeout == 0) ? INFINITE : timeout;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  DWORD which;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
  long c = _counter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  bool retry = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
  _waiters++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
  // Loop until condition variable is signaled.  The event object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  // set whenever the condition variable is signaled, and tickets will
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  // reflect the number of threads which have been notified. The counter
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  // field is used to make sure we don't respond to notifications that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
  // have occurred *before* we started waiting, and is incremented each
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
  // time the condition variable is signaled.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  while (true) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    // Leave critical region
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
    unlock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
    // If this is a retry, let other low-priority threads have a chance
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    // to run.  Make sure that we sleep outside of the critical section.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
    if (retry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
      Sleep(1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
      retry = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
    which = WaitForSingleObject(_wait_event, timeout_value);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
    // Enter critical section
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
    lock();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
    if (_tickets != 0 && _counter != c) break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
    if (which == WAIT_TIMEOUT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
      --_waiters;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  _waiters--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
  // If this was the last thread to be notified, then we need to reset
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  // the event object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  if (--_tickets == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
    ResetEvent(_wait_event);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
// Notify a single thread waiting on this monitor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
bool
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
Monitor::notify() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
  assert(ownedBySelf()); // Otherwise, notify on unknown thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
  if (_waiters > _tickets) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
    if (!SetEvent(_wait_event)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
    _tickets++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
    _counter++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
// Notify all threads waiting on this monitor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
bool
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
Monitor::notifyAll() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
  assert(ownedBySelf()); // Otherwise, notifyAll on unknown thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
  if (_waiters > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    if (!SetEvent(_wait_event)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
    _tickets = _waiters;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
    _counter++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
HANDLE
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
Monitor::owner() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
  return _owner;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
void
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
Monitor::setOwner(HANDLE owner) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  if (owner != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
    assert(_owner == NULL);                 // Setting owner thread of already owned monitor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
    assert(owner == GetCurrentThread());    // Else should not be doing this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
    HANDLE oldOwner = _owner;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
    assert(oldOwner != NULL);               // Removing the owner thread of an unowned mutex
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    assert(oldOwner == GetCurrentThread());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
  _owner = owner;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
bool
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
Monitor::ownedBySelf() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
  return (_owner == GetCurrentThread());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
}