src/hotspot/os/linux/waitBarrier_linux.cpp
author michaelm
Thu, 14 Nov 2019 12:40:13 +0000
branchunixdomainchannels
changeset 59079 7893d1012580
parent 53254 47bc06170313
permissions -rw-r--r--
Merge
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53254
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     1
/*
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     4
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     7
 * published by the Free Software Foundation.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     8
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    13
 * accompanied this code).
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    14
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    18
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    21
 * questions.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    22
 *
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    23
 */
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    24
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    25
#include "precompiled/precompiled.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    26
#include "runtime/orderAccess.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    27
#include "runtime/os.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    28
#include "waitBarrier_linux.hpp"
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    29
#include <sys/syscall.h>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    30
#include <linux/futex.h>
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    31
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    32
#define check_with_errno(check_type, cond, msg)                             \
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    33
  do {                                                                      \
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    34
    int err = errno;                                                        \
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    35
    check_type(cond, "%s: error='%s' (errno=%s)", msg, os::strerror(err),   \
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    36
               os::errno_name(err));                                        \
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    37
} while (false)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    38
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    39
#define guarantee_with_errno(cond, msg) check_with_errno(guarantee, cond, msg)
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    40
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    41
static int futex(volatile int *addr, int futex_op, int op_arg) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    42
  return syscall(SYS_futex, addr, futex_op, op_arg, NULL, NULL, 0);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    43
}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    44
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    45
void LinuxWaitBarrier::arm(int barrier_tag) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    46
  assert(_futex_barrier == 0, "Should not be already armed: "
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    47
         "_futex_barrier=%d", _futex_barrier);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    48
  _futex_barrier = barrier_tag;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    49
  OrderAccess::fence();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    50
}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    51
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    52
void LinuxWaitBarrier::disarm() {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    53
  assert(_futex_barrier != 0, "Should be armed/non-zero.");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    54
  _futex_barrier = 0;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    55
  int s = futex(&_futex_barrier,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    56
                FUTEX_WAKE_PRIVATE,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    57
                INT_MAX /* wake a max of this many threads */);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    58
  guarantee_with_errno(s > -1, "futex FUTEX_WAKE failed");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    59
}
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    60
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    61
void LinuxWaitBarrier::wait(int barrier_tag) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    62
  assert(barrier_tag != 0, "Trying to wait on disarmed value");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    63
  if (barrier_tag == 0 ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    64
      barrier_tag != _futex_barrier) {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    65
    OrderAccess::fence();
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    66
    return;
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    67
  }
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    68
  do {
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    69
    int s = futex(&_futex_barrier,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    70
                  FUTEX_WAIT_PRIVATE,
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    71
                  barrier_tag /* should be this tag */);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    72
    guarantee_with_errno((s == 0) ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    73
                         (s == -1 && errno == EAGAIN) ||
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    74
                         (s == -1 && errno == EINTR),
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    75
                         "futex FUTEX_WAIT failed");
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    76
    // Return value 0: woken up, but re-check in case of spurious wakeup.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    77
    // Error EINTR: woken by signal, so re-check and re-wait if necessary.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    78
    // Error EAGAIN: we are already disarmed and so will pass the check.
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    79
  } while (barrier_tag == _futex_barrier);
47bc06170313 8214271: Fast primitive to wake many threads
rehn
parents:
diff changeset
    80
}