void SolarisAttachOperation::complete(jint res, bufferedStream* st) {
  if (this->socket() >= 0) {
    JavaThread* thread = JavaThread::current();
    ThreadBlockInVM tbivm(thread);

    thread->set_suspend_equivalent();
    // cleared by handle_special_suspend_equivalent_condition() or
    // java_suspend_self() via check_and_wait_while_suspended()

    // write operation result
    char msg[32];
    sprintf(msg, "%d\n", res);
    int rc = write_fully(this->socket(), msg, strlen(msg));

    // write any result data
    if (rc == 0) {
      write_fully(this->socket(), (char*) st->base(), st->size());
      ::shutdown(this->socket(), 2);
    }

    // close socket and we're done
    ::close(this->socket());

    // were we externally suspended while we were waiting?
    thread->check_and_wait_while_suspended();
  }
  delete this;
}
AttachOperation* AttachListener::dequeue() {
  JavaThread* thread = JavaThread::current();
  ThreadBlockInVM tbivm(thread);

  thread->set_suspend_equivalent();
  // cleared by handle_special_suspend_equivalent_condition() or
  // java_suspend_self() via check_and_wait_while_suspended()

  AttachOperation* op = Win32AttachListener::dequeue();

  // were we externally suspended while we were waiting?
  thread->check_and_wait_while_suspended();

  return op;
}
int AttachListener::pd_init() {
  JavaThread* thread = JavaThread::current();
  ThreadBlockInVM tbivm(thread);

  thread->set_suspend_equivalent();
  // cleared by handle_special_suspend_equivalent_condition() or
  // java_suspend_self()

  int ret_code = SolarisAttachListener::init();

  // were we externally suspended while we were waiting?
  thread->check_and_wait_while_suspended();

  return ret_code;
}
// Complete the operation:
//   - open the pipe to the client
//   - write the operation result (a jint)
//   - write the operation output (the result stream)
//
void Win32AttachOperation::complete(jint result, bufferedStream* result_stream) {
  JavaThread* thread = JavaThread::current();
  ThreadBlockInVM tbivm(thread);

  thread->set_suspend_equivalent();
  // cleared by handle_special_suspend_equivalent_condition() or
  // java_suspend_self() via check_and_wait_while_suspended()

  HANDLE hPipe = open_pipe();
  if (hPipe != INVALID_HANDLE_VALUE) {
    BOOL fSuccess;

    char msg[32];
    _snprintf(msg, sizeof(msg), "%d\n", result);
    msg[sizeof(msg) - 1] = '\0';

    fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
    if (fSuccess) {
      write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
    }

    // Need to flush buffers
    FlushFileBuffers(hPipe);
    CloseHandle(hPipe);
  }

  DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
  if (res == WAIT_OBJECT_0) {

    // put the operation back on the available list
    set_next(Win32AttachListener::available());
    Win32AttachListener::set_available(this);

    ::ReleaseMutex(Win32AttachListener::mutex());
  }

  // were we externally suspended while we were waiting?
  thread->check_and_wait_while_suspended();
}