提交 c05e897a 编写于 作者: A asaha

Merge

...@@ -950,4 +950,6 @@ c0a1ba0df20fda10ddb8599e888eb56ad98b3874 jdk8u131-b00 ...@@ -950,4 +950,6 @@ c0a1ba0df20fda10ddb8599e888eb56ad98b3874 jdk8u131-b00
ef90c721a4e59b01ca36f25619010a1afe9ed4d5 jdk8u131-b02 ef90c721a4e59b01ca36f25619010a1afe9ed4d5 jdk8u131-b02
0ca47d0811b01ecf8651b6045a1e33a4a9bed0ee jdk8u131-b03 0ca47d0811b01ecf8651b6045a1e33a4a9bed0ee jdk8u131-b03
dab1d597165207e14b6886b1823c1e990bc776a3 jdk8u131-b04 dab1d597165207e14b6886b1823c1e990bc776a3 jdk8u131-b04
c965fc1aa840a0903709ad69aa0e2100330ccd84 jdk8u131-b05
6e4cfbc7534f83902692132efb61683528c04a59 jdk8u131-b06
692bc6b674dcab72453de08ee9da0856a7e41c0f jdk8u141-b00 692bc6b674dcab72453de08ee9da0856a7e41c0f jdk8u141-b00
/* /*
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -47,7 +47,10 @@ ...@@ -47,7 +47,10 @@
"Load DLLs with executable-stack attribute in the VM Thread") \ "Load DLLs with executable-stack attribute in the VM Thread") \
\ \
product(bool, UseSHM, false, \ product(bool, UseSHM, false, \
"Use SYSV shared memory for large pages") "Use SYSV shared memory for large pages") \
\
diagnostic(bool, PrintActiveCpus, false, \
"Print the number of CPUs detected in os::active_processor_count")
// //
// Defines Linux-specific default values. The flags are available on all // Defines Linux-specific default values. The flags are available on all
......
/* /*
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -104,6 +104,14 @@ ...@@ -104,6 +104,14 @@
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <sched.h>
#undef _GNU_SOURCE
#else
#include <sched.h>
#endif
// if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling // if RUSAGE_THREAD for getrusage() has not been defined, do it here. The code calling
// getrusage() is prepared to handle the associated failure. // getrusage() is prepared to handle the associated failure.
#ifndef RUSAGE_THREAD #ifndef RUSAGE_THREAD
...@@ -1067,29 +1075,30 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) { ...@@ -1067,29 +1075,30 @@ static bool find_vma(address addr, address* vma_low, address* vma_high) {
// Locate initial thread stack. This special handling of initial thread stack // Locate initial thread stack. This special handling of initial thread stack
// is needed because pthread_getattr_np() on most (all?) Linux distros returns // is needed because pthread_getattr_np() on most (all?) Linux distros returns
// bogus value for initial thread. // bogus value for the primordial process thread. While the launcher has created
// the VM in a new thread since JDK 6, we still have to allow for the use of the
// JNI invocation API from a primordial thread.
void os::Linux::capture_initial_stack(size_t max_size) { void os::Linux::capture_initial_stack(size_t max_size) {
// stack size is the easy part, get it from RLIMIT_STACK
size_t stack_size; // max_size is either 0 (which means accept OS default for thread stacks) or
// a user-specified value known to be at least the minimum needed. If we
// are actually on the primordial thread we can make it appear that we have a
// smaller max_size stack by inserting the guard pages at that location. But we
// cannot do anything to emulate a larger stack than what has been provided by
// the OS or threading library. In fact if we try to use a stack greater than
// what is set by rlimit then we will crash the hosting process.
// Maximum stack size is the easy part, get it from RLIMIT_STACK.
// If this is "unlimited" then it will be a huge value.
struct rlimit rlim; struct rlimit rlim;
getrlimit(RLIMIT_STACK, &rlim); getrlimit(RLIMIT_STACK, &rlim);
stack_size = rlim.rlim_cur; size_t stack_size = rlim.rlim_cur;
// 6308388: a bug in ld.so will relocate its own .data section to the // 6308388: a bug in ld.so will relocate its own .data section to the
// lower end of primordial stack; reduce ulimit -s value a little bit // lower end of primordial stack; reduce ulimit -s value a little bit
// so we won't install guard page on ld.so's data section. // so we won't install guard page on ld.so's data section.
stack_size -= 2 * page_size(); stack_size -= 2 * page_size();
// 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat
// 7.1, in both cases we will get 2G in return value.
// 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0,
// SuSE 7.2, Debian) can not handle alternate signal stack correctly
// for initial thread if its stack size exceeds 6M. Cap it at 2M,
// in case other parts in glibc still assumes 2M max stack size.
// FIXME: alt signal stack is gone, maybe we can relax this constraint?
// Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
if (stack_size > 2 * K * K IA64_ONLY(*2))
stack_size = 2 * K * K IA64_ONLY(*2);
// Try to figure out where the stack base (top) is. This is harder. // Try to figure out where the stack base (top) is. This is harder.
// //
// When an application is started, glibc saves the initial stack pointer in // When an application is started, glibc saves the initial stack pointer in
...@@ -1249,14 +1258,18 @@ void os::Linux::capture_initial_stack(size_t max_size) { ...@@ -1249,14 +1258,18 @@ void os::Linux::capture_initial_stack(size_t max_size) {
// stack_top could be partially down the page so align it // stack_top could be partially down the page so align it
stack_top = align_size_up(stack_top, page_size()); stack_top = align_size_up(stack_top, page_size());
if (max_size && stack_size > max_size) { // Allowed stack value is minimum of max_size and what we derived from rlimit
_initial_thread_stack_size = max_size; if (max_size > 0) {
_initial_thread_stack_size = MIN2(max_size, stack_size);
} else { } else {
_initial_thread_stack_size = stack_size; // Accept the rlimit max, but if stack is unlimited then it will be huge, so
// clamp it at 8MB as we do on Solaris
_initial_thread_stack_size = MIN2(stack_size, 8*M);
} }
_initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size()); _initial_thread_stack_size = align_size_down(_initial_thread_stack_size, page_size());
_initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size; _initial_thread_stack_bottom = (address)stack_top - _initial_thread_stack_size;
assert(_initial_thread_stack_bottom < (address)stack_top, "overflow!");
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -5016,12 +5029,42 @@ void os::make_polling_page_readable(void) { ...@@ -5016,12 +5029,42 @@ void os::make_polling_page_readable(void) {
} }
}; };
static int os_cpu_count(const cpu_set_t* cpus) {
int count = 0;
// only look up to the number of configured processors
for (int i = 0; i < os::processor_count(); i++) {
if (CPU_ISSET(i, cpus)) {
count++;
}
}
return count;
}
// Get the current number of available processors for this process.
// This value can change at any time during a process's lifetime.
// sched_getaffinity gives an accurate answer as it accounts for cpusets.
// If anything goes wrong we fallback to returning the number of online
// processors - which can be greater than the number available to the process.
int os::active_processor_count() { int os::active_processor_count() {
// Linux doesn't yet have a (official) notion of processor sets, cpu_set_t cpus; // can represent at most 1024 (CPU_SETSIZE) processors
// so just return the number of online processors. int cpus_size = sizeof(cpu_set_t);
int online_cpus = ::sysconf(_SC_NPROCESSORS_ONLN); int cpu_count = 0;
assert(online_cpus > 0 && online_cpus <= processor_count(), "sanity check");
return online_cpus; // pid 0 means the current thread - which we have to assume represents the process
if (sched_getaffinity(0, cpus_size, &cpus) == 0) {
cpu_count = os_cpu_count(&cpus);
if (PrintActiveCpus) {
tty->print_cr("active_processor_count: sched_getaffinity processor count: %d", cpu_count);
}
}
else {
cpu_count = ::sysconf(_SC_NPROCESSORS_ONLN);
warning("sched_getaffinity failed (%s)- using online processor count (%d) "
"which may exceed available processors", strerror(errno), cpu_count);
}
assert(cpu_count > 0 && cpu_count <= processor_count(), "sanity check");
return cpu_count;
} }
void os::set_native_thread_name(const char *name) { void os::set_native_thread_name(const char *name) {
......
/* /*
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -631,11 +631,10 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev ...@@ -631,11 +631,10 @@ ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev
double overall_cm_overhead = double overall_cm_overhead =
(double) MaxGCPauseMillis * marking_overhead / (double) MaxGCPauseMillis * marking_overhead /
(double) GCPauseIntervalMillis; (double) GCPauseIntervalMillis;
double cpu_ratio = 1.0 / (double) os::processor_count(); double cpu_ratio = 1.0 / os::initial_active_processor_count();
double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio); double marking_thread_num = ceil(overall_cm_overhead / cpu_ratio);
double marking_task_overhead = double marking_task_overhead =
overall_cm_overhead / marking_thread_num * overall_cm_overhead / marking_thread_num * os::initial_active_processor_count();
(double) os::processor_count();
double sleep_factor = double sleep_factor =
(1.0 - marking_task_overhead) / marking_task_overhead; (1.0 - marking_task_overhead) / marking_task_overhead;
......
/* /*
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -80,7 +80,7 @@ DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) : ...@@ -80,7 +80,7 @@ DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
// Determines how many mutator threads can process the buffers in parallel. // Determines how many mutator threads can process the buffers in parallel.
uint DirtyCardQueueSet::num_par_ids() { uint DirtyCardQueueSet::num_par_ids() {
return (uint)os::processor_count(); return (uint)os::initial_active_processor_count();
} }
void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock, void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1768,10 +1768,39 @@ void Arguments::set_heap_size() { ...@@ -1768,10 +1768,39 @@ void Arguments::set_heap_size() {
FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction); FLAG_SET_CMDLINE(uintx, MaxRAMFraction, DefaultMaxRAMFraction);
} }
const julong phys_mem = julong phys_mem =
FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM) FLAG_IS_DEFAULT(MaxRAM) ? MIN2(os::physical_memory(), (julong)MaxRAM)
: (julong)MaxRAM; : (julong)MaxRAM;
// Experimental support for CGroup memory limits
if (UseCGroupMemoryLimitForHeap) {
// This is a rough indicator that a CGroup limit may be in force
// for this process
const char* lim_file = "/sys/fs/cgroup/memory/memory.limit_in_bytes";
FILE *fp = fopen(lim_file, "r");
if (fp != NULL) {
julong cgroup_max = 0;
int ret = fscanf(fp, JULONG_FORMAT, &cgroup_max);
if (ret == 1 && cgroup_max > 0) {
// If unlimited, cgroup_max will be a very large, but unspecified
// value, so use initial phys_mem as a limit
if (PrintGCDetails && Verbose) {
// Cannot use gclog_or_tty yet.
tty->print_cr("Setting phys_mem to the min of cgroup limit ("
JULONG_FORMAT "MB) and initial phys_mem ("
JULONG_FORMAT "MB)", cgroup_max/M, phys_mem/M);
}
phys_mem = MIN2(cgroup_max, phys_mem);
} else {
warning("Unable to read/parse cgroup memory limit from %s: %s",
lim_file, errno != 0 ? strerror(errno) : "unknown error");
}
fclose(fp);
} else {
warning("Unable to open cgroup memory limit file %s (%s)", lim_file, strerror(errno));
}
}
// If the maximum heap size has not been set with -Xmx, // If the maximum heap size has not been set with -Xmx,
// then set it as fraction of the size of physical memory, // then set it as fraction of the size of physical memory,
// respecting the maximum and minimum sizes of the heap. // respecting the maximum and minimum sizes of the heap.
......
/* /*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -2068,6 +2068,10 @@ class CommandLineFlags { ...@@ -2068,6 +2068,10 @@ class CommandLineFlags {
"Maximum ergonomically set heap size (in bytes); zero means use " \ "Maximum ergonomically set heap size (in bytes); zero means use " \
"MaxRAM / MaxRAMFraction") \ "MaxRAM / MaxRAMFraction") \
\ \
experimental(bool, UseCGroupMemoryLimitForHeap, false, \
"Use CGroup memory limit as physical memory limit for heap " \
"sizing") \
\
product(uintx, MaxRAMFraction, 4, \ product(uintx, MaxRAMFraction, 4, \
"Maximum fraction (1/n) of real memory used for maximum heap " \ "Maximum fraction (1/n) of real memory used for maximum heap " \
"size") \ "size") \
......
/* /*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -78,6 +78,7 @@ volatile int32_t* os::_mem_serialize_page = NULL; ...@@ -78,6 +78,7 @@ volatile int32_t* os::_mem_serialize_page = NULL;
uintptr_t os::_serialize_page_mask = 0; uintptr_t os::_serialize_page_mask = 0;
long os::_rand_seed = 1; long os::_rand_seed = 1;
int os::_processor_count = 0; int os::_processor_count = 0;
int os::_initial_active_processor_count = 0;
size_t os::_page_sizes[os::page_sizes_max]; size_t os::_page_sizes[os::page_sizes_max];
#ifndef PRODUCT #ifndef PRODUCT
...@@ -322,6 +323,7 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { ...@@ -322,6 +323,7 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) {
} }
void os::init_before_ergo() { void os::init_before_ergo() {
initialize_initial_active_processor_count();
// We need to initialize large page support here because ergonomics takes some // We need to initialize large page support here because ergonomics takes some
// decisions depending on large page support and the calculated large page size. // decisions depending on large page support and the calculated large page size.
large_page_init(); large_page_init();
...@@ -835,7 +837,11 @@ void os::print_cpu_info(outputStream* st) { ...@@ -835,7 +837,11 @@ void os::print_cpu_info(outputStream* st) {
st->print("CPU:"); st->print("CPU:");
st->print("total %d", os::processor_count()); st->print("total %d", os::processor_count());
// It's not safe to query number of active processors after crash // It's not safe to query number of active processors after crash
// st->print("(active %d)", os::active_processor_count()); // st->print("(active %d)", os::active_processor_count()); but we can
// print the initial number of active processors.
// We access the raw value here because the assert in the accessor will
// fail if the crash occurs before initialization of this value.
st->print(" (initial active %d)", _initial_active_processor_count);
st->print(" %s", VM_Version::cpu_features()); st->print(" %s", VM_Version::cpu_features());
st->cr(); st->cr();
pd_print_cpu_info(st); pd_print_cpu_info(st);
...@@ -1418,6 +1424,11 @@ bool os::is_server_class_machine() { ...@@ -1418,6 +1424,11 @@ bool os::is_server_class_machine() {
return result; return result;
} }
void os::initialize_initial_active_processor_count() {
assert(_initial_active_processor_count == 0, "Initial active processor count already set.");
_initial_active_processor_count = active_processor_count();
}
void os::SuspendedThreadTask::run() { void os::SuspendedThreadTask::run() {
assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this"); assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this");
internal_do_task(); internal_do_task();
......
...@@ -151,6 +151,7 @@ class os: AllStatic { ...@@ -151,6 +151,7 @@ class os: AllStatic {
static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
static void initialize_initial_active_processor_count();
public: public:
static void init(void); // Called before command line parsing static void init(void); // Called before command line parsing
static void init_before_ergo(void); // Called after command line parsing static void init_before_ergo(void); // Called after command line parsing
...@@ -238,6 +239,13 @@ class os: AllStatic { ...@@ -238,6 +239,13 @@ class os: AllStatic {
// Note that on some OSes this can change dynamically. // Note that on some OSes this can change dynamically.
static int active_processor_count(); static int active_processor_count();
// At startup the number of active CPUs this process is allowed to run on.
// This value does not change dynamically. May be different from active_processor_count().
static int initial_active_processor_count() {
assert(_initial_active_processor_count > 0, "Initial active processor count not set yet.");
return _initial_active_processor_count;
}
// Bind processes to processors. // Bind processes to processors.
// This is a two step procedure: // This is a two step procedure:
// first you generate a distribution of processes to processors, // first you generate a distribution of processes to processors,
...@@ -975,8 +983,9 @@ class os: AllStatic { ...@@ -975,8 +983,9 @@ class os: AllStatic {
protected: protected:
static long _rand_seed; // seed for random number generator static long _rand_seed; // seed for random number generator
static int _processor_count; // number of processors static int _processor_count; // number of processors
static int _initial_active_processor_count; // number of active processors during initialization.
static char* format_boot_path(const char* format_string, static char* format_boot_path(const char* format_string,
const char* home, const char* home,
......
/* /*
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -296,7 +296,7 @@ unsigned int Abstract_VM_Version::nof_parallel_worker_threads( ...@@ -296,7 +296,7 @@ unsigned int Abstract_VM_Version::nof_parallel_worker_threads(
// processor after the first 8. For example, on a 72 cpu machine // processor after the first 8. For example, on a 72 cpu machine
// and a chosen fraction of 5/8 // and a chosen fraction of 5/8
// use 8 + (72 - 8) * (5/8) == 48 worker threads. // use 8 + (72 - 8) * (5/8) == 48 worker threads.
unsigned int ncpus = (unsigned int) os::active_processor_count(); unsigned int ncpus = (unsigned int) os::initial_active_processor_count();
return (ncpus <= switch_pt) ? return (ncpus <= switch_pt) ?
ncpus : ncpus :
(switch_pt + ((ncpus - switch_pt) * num) / den); (switch_pt + ((ncpus - switch_pt) * num) / den);
......
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.File;
import com.oracle.java.testlibrary.ProcessTools;
import com.oracle.java.testlibrary.OutputAnalyzer;
import java.util.ArrayList;
/*
* @test
* @bug 6515172
* @summary Check that availableProcessors reports the correct value when running in a cpuset on linux
* @requires os.family == "linux"
* @library /testlibrary
* @build com.oracle.java.testlibrary.*
* @run driver AvailableProcessors
*/
public class AvailableProcessors {
static final String SUCCESS_STRING = "Found expected processors: ";
public static void main(String[] args) throws Throwable {
if (args.length > 0)
checkProcessors(Integer.parseInt(args[0]));
else {
// run ourselves under different cpu configurations
// using the taskset command
String taskset;
final String taskset1 = "/bin/taskset";
final String taskset2 = "/usr/bin/taskset";
if (new File(taskset1).exists())
taskset = taskset1;
else if (new File(taskset2).exists())
taskset = taskset2;
else {
System.out.println("Skipping test: could not find taskset command");
return;
}
int available = Runtime.getRuntime().availableProcessors();
if (available == 1) {
System.out.println("Skipping test: only one processor available");
return;
}
// Get the java command we want to execute
// Enable logging for easier failure diagnosis
ProcessBuilder master =
ProcessTools.createJavaProcessBuilder(false,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+PrintActiveCpus",
"AvailableProcessors");
int[] expected = new int[] { 1, available/2, available-1, available };
for (int i : expected) {
System.out.println("Testing for " + i + " processors ...");
int max = i - 1;
ArrayList<String> cmdline = new ArrayList<>(master.command());
// prepend taskset command
cmdline.add(0, "0-" + max);
cmdline.add(0, "-c");
cmdline.add(0, taskset);
// append expected processor count
cmdline.add(String.valueOf(i));
ProcessBuilder pb = new ProcessBuilder(cmdline);
System.out.println("Final command line: " +
ProcessTools.getCommandLine(pb));
OutputAnalyzer output = ProcessTools.executeProcess(pb);
output.shouldContain(SUCCESS_STRING);
}
}
}
static void checkProcessors(int expected) {
int available = Runtime.getRuntime().availableProcessors();
if (available != expected)
throw new Error("Expected " + expected + " processors, but found "
+ available);
else
System.out.println(SUCCESS_STRING + available);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册