hotspot/src/os/windows/vm/attachListener_windows.cpp
author trims
Thu, 27 May 2010 19:08:38 -0700
changeset 5547 f4b087cbb361
parent 1 489c9b5090e2
child 7397 5b173b4ca846
permissions -rw-r--r--
6941466: Oracle rebranding changes for Hotspot repositories Summary: Change all the Sun copyrights to Oracle copyright Reviewed-by: ohair
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
     2
 * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
1
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
 *
5547
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
f4b087cbb361 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1
diff changeset
    21
 * questions.
1
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 "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_attachListener_windows.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
#include <windows.h>
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
#include <signal.h>             // SIGBREAK
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
// The AttachListener thread services a queue of operations. It blocks in the dequeue
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
// function until an operation is enqueued. A client enqueues an operation by creating
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
// a thread in this process using the Win32 CreateRemoteThread function. That thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
// executes a small stub generated by the client. The stub invokes the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
// JVM_EnqueueOperation function which checks the operation parameters and enqueues
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
// the operation to the queue serviced by the attach listener. The thread created by
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
// the client is a native thread and is restricted to a single page of stack. To keep
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
// it simple operations are pre-allocated at initialization time. An enqueue thus
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
// takes a preallocated operation, populates the operation parameters, adds it to
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
// queue and wakes up the attach listener.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
// When an operation has completed the attach listener is required to send the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
// operation result and any result data to the client. In this implementation the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
// client is a pipe server. In the enqueue operation it provides the name of pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
// to this process. When the operation is completed this process opens the pipe and
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
// sends the result and output back to the client. Note that writing to the pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
// (and flushing the output) is a blocking operation. This means that a non-responsive
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
// client could potentially hang the attach listener thread indefinitely. In that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
// case no new operations would be executed but the VM would continue as normal.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
// As only suitably privileged processes can open this process we concluded that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
// this wasn't worth worrying about.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
// forward reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
class Win32AttachOperation;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
class Win32AttachListener: AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
    preallocate_count = 4                   // number of preallocated operations
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
  // protects the preallocated list and the operation list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
  static HANDLE _mutex;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
  // head of preallocated operations list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
  static Win32AttachOperation* _avail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
  // head and tail of enqueue operations list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
  static Win32AttachOperation* _head;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
  static Win32AttachOperation* _tail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
  static Win32AttachOperation* head()                       { return _head; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
  static void set_head(Win32AttachOperation* head)          { _head = head; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
  static Win32AttachOperation* tail()                       { return _tail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
  static void set_tail(Win32AttachOperation* tail)          { _tail = tail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
  // used to wakeup the listener
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
  static HANDLE _wakeup;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
  static HANDLE wakeup()                                    { return _wakeup; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
    ATTACH_ERROR_DISABLED               = 100,              // error codes
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
    ATTACH_ERROR_RESOURCE               = 101,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
    ATTACH_ERROR_ILLEGALARG             = 102,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
    ATTACH_ERROR_INTERNAL               = 103
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
  static int init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  static HANDLE mutex()                                     { return _mutex; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  static Win32AttachOperation* available()                  { return _avail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  static void set_available(Win32AttachOperation* avail)    { _avail = avail; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
  // enqueue an operation to the end of the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  static int enqueue(char* cmd, char* arg1, char* arg2, char* arg3, char* pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
  // dequeue an operation from from head of the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  static Win32AttachOperation* dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
// statics
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
HANDLE Win32AttachListener::_mutex;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
HANDLE Win32AttachListener::_wakeup;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
Win32AttachOperation* Win32AttachListener::_avail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
Win32AttachOperation* Win32AttachListener::_head;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
Win32AttachOperation* Win32AttachListener::_tail;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
// Win32AttachOperation is an AttachOperation that additionally encapsulates the name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
// of a pipe which is used to send the operation reply/output to the client.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
// Win32AttachOperation can also be linked in a list.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
class Win32AttachOperation: public AttachOperation {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
  friend class Win32AttachListener;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
    pipe_name_max = 256             // maximum pipe name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
  char _pipe[pipe_name_max+1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
  const char* pipe() const                              { return _pipe; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
  void set_pipe(const char* pipe) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
    strcpy(_pipe, pipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
  HANDLE open_pipe();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
  static BOOL write_pipe(HANDLE hPipe, char* buf, int len);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
  Win32AttachOperation* _next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  Win32AttachOperation* next() const                    { return _next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
  void set_next(Win32AttachOperation* next)             { _next = next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
  // noarg constructor as operation is preallocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
  Win32AttachOperation() : AttachOperation("<noname>") {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    set_pipe("<nopipe>");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
    set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
  void Win32AttachOperation::complete(jint result, bufferedStream* result_stream);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
// preallocate the required number of operations
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
int Win32AttachListener::init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  _mutex = (void*)::CreateMutex(NULL, FALSE, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
  guarantee(_mutex != (HANDLE)NULL, "mutex creation failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
  _wakeup = ::CreateSemaphore(NULL, 0, 1, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
  guarantee(_wakeup != (HANDLE)NULL, "semaphore creation failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
  set_head(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
  set_tail(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
  // preallocate a few operations
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
  set_available(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
  for (int i=0; i<preallocate_count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    Win32AttachOperation* op = new Win32AttachOperation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
    op->set_next(available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
    set_available(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
  return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
// Enqueue an operation. This is called from a native thread that is not attached to VM.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
// Also we need to be careful not to execute anything that results in more than a 4k stack.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
int Win32AttachListener::enqueue(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
  // listener not running
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
  if (!AttachListener::is_initialized()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
    return ATTACH_ERROR_DISABLED;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
  // check that all paramteres to the operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
  if (strlen(cmd) > AttachOperation::name_length_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
  if (strlen(arg0) > AttachOperation::arg_length_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
  if (strlen(pipename) > Win32AttachOperation::pipe_name_max) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
  // check for a well-formed pipename
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
  if (strstr(pipename, "\\\\.\\pipe\\") != pipename) return ATTACH_ERROR_ILLEGALARG;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
  // grab the lock for the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
  DWORD res = ::WaitForSingleObject(mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
  if (res != WAIT_OBJECT_0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
    return ATTACH_ERROR_INTERNAL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
  // try to get an operation from the available list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
  Win32AttachOperation* op = available();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
  if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    set_available(op->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
    // add to end (tail) of list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
    op->set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
    if (tail() == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
      set_head(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
      tail()->set_next(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
    set_tail(op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
    op->set_name(cmd);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
    op->set_arg(0, arg0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
    op->set_arg(1, arg1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
    op->set_arg(2, arg2);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
    op->set_pipe(pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
    // wakeup the thread waiting for operations
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    ::ReleaseSemaphore(wakeup(), 1, NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  ::ReleaseMutex(mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  return (op != NULL) ? 0 : ATTACH_ERROR_RESOURCE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
// dequeue the operation from the head of the operation list. If
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
Win32AttachOperation* Win32AttachListener::dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
  for (;;) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
    DWORD res = ::WaitForSingleObject(wakeup(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
    guarantee(res == WAIT_OBJECT_0, "wait failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
    res = ::WaitForSingleObject(mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
    guarantee(res == WAIT_OBJECT_0, "wait failed");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
    Win32AttachOperation* op = head();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
      set_head(op->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
      if (head() == NULL) {     // list is empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
        set_tail(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
    ::ReleaseMutex(mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
    if (op != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
      return op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
// open the pipe to the client
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
HANDLE Win32AttachOperation::open_pipe() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
  HANDLE hPipe;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
  hPipe = ::CreateFile( pipe(),  // pipe name
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
                        GENERIC_WRITE,   // write only
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
                        0,              // no sharing
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
                        NULL,           // default security attributes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
                        OPEN_EXISTING,  // opens existing pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
                        0,              // default attributes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
                        NULL);          // no template file
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
  if (hPipe != INVALID_HANDLE_VALUE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
    // shouldn't happen as there is a pipe created per operation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
    if (::GetLastError() == ERROR_PIPE_BUSY) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
      return INVALID_HANDLE_VALUE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  return hPipe;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
// write to the pipe
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
BOOL Win32AttachOperation::write_pipe(HANDLE hPipe, char* buf, int len) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
  do {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    DWORD nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
    BOOL fSuccess = WriteFile(  hPipe,                  // pipe handle
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
                                (LPCVOID)buf,           // message
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
                                (DWORD)len,             // message length
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
                                &nwrote,                // bytes written
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
                                NULL);                  // not overlapped
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
    if (!fSuccess) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
      return fSuccess;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
    buf += nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
    len -= nwrote;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  while (len > 0);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
  return TRUE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
// Complete the operation:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
//   - open the pipe to the client
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
//   - write the operation result (a jint)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
//   - write the operation output (the result stream)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
  JavaThread* thread = JavaThread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
  ThreadBlockInVM tbivm(thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
  thread->set_suspend_equivalent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
  // cleared by handle_special_suspend_equivalent_condition() or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
  // java_suspend_self() via check_and_wait_while_suspended()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
  HANDLE hPipe = open_pipe();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
  if (hPipe != INVALID_HANDLE_VALUE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
    BOOL fSuccess;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
    char msg[32];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
    sprintf(msg, "%d\n", result);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
    fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
    if (fSuccess) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
      write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
    // Need to flush buffers
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
    FlushFileBuffers(hPipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
    CloseHandle(hPipe);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
  DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
  if (res == WAIT_OBJECT_0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
    // put the operation back on the available list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
    set_next(Win32AttachListener::available());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
    Win32AttachListener::set_available(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
    ::ReleaseMutex(Win32AttachListener::mutex());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  // were we externally suspended while we were waiting?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
  thread->check_and_wait_while_suspended();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
// AttachOperation functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
AttachOperation* AttachListener::dequeue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
  JavaThread* thread = JavaThread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
  ThreadBlockInVM tbivm(thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
  thread->set_suspend_equivalent();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
  // cleared by handle_special_suspend_equivalent_condition() or
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
  // java_suspend_self() via check_and_wait_while_suspended()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
  AttachOperation* op = Win32AttachListener::dequeue();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
  // were we externally suspended while we were waiting?
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
  thread->check_and_wait_while_suspended();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
  return op;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
int AttachListener::pd_init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
  return Win32AttachListener::init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
// always startup on Windows NT/2000/XP
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
bool AttachListener::init_at_startup() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
  return os::win32::is_nt();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
// no trigger mechanism on Windows to start Attach Listener lazily
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
bool AttachListener::is_init_trigger() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
void AttachListener::abort() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  // nothing to do
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
void AttachListener::pd_data_dump() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  os::signal_notify(SIGBREAK);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
AttachOperationFunctionInfo* AttachListener::pd_find_operation(const char* n) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
  return NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
jint AttachListener::pd_set_flag(AttachOperation* op, outputStream* out) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
  out->print_cr("flag '%s' cannot be changed", op->arg(0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
  return JNI_ERR;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
void AttachListener::pd_detachall() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
  // do nothing for now
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
// Native thread started by remote client executes this.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
extern "C" {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  JNIEXPORT jint JNICALL
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
    JVM_EnqueueOperation(char* cmd, char* arg0, char* arg1, char* arg2, char* pipename) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
      return (jint)Win32AttachListener::enqueue(cmd, arg0, arg1, arg2, pipename);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
} // extern