#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.65 for stressapptest 1.0.4_autoconf.
+# Generated by GNU Autoconf 2.65 for stressapptest 1.0.6_autoconf.
#
# Report bugs to <opensource@google.com>.
#
# Identity of this package.
PACKAGE_NAME='stressapptest'
PACKAGE_TARNAME='stressapptest'
-PACKAGE_VERSION='1.0.4_autoconf'
-PACKAGE_STRING='stressapptest 1.0.4_autoconf'
+PACKAGE_VERSION='1.0.6_autoconf'
+PACKAGE_STRING='stressapptest 1.0.6_autoconf'
PACKAGE_BUGREPORT='opensource@google.com'
PACKAGE_URL=''
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures stressapptest 1.0.4_autoconf to adapt to many kinds of systems.
+\`configure' configures stressapptest 1.0.6_autoconf to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of stressapptest 1.0.4_autoconf:";;
+ short | recursive ) echo "Configuration of stressapptest 1.0.6_autoconf:";;
esac
cat <<\_ACEOF
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-stressapptest configure 1.0.4_autoconf
+stressapptest configure 1.0.6_autoconf
generated by GNU Autoconf 2.65
Copyright (C) 2009 Free Software Foundation, Inc.
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by stressapptest $as_me 1.0.4_autoconf, which was
+It was created by stressapptest $as_me 1.0.6_autoconf, which was
generated by GNU Autoconf 2.65. Invocation command line was
$ $0 $@
# Define the identity of the package.
PACKAGE='stressapptest'
- VERSION='1.0.4_autoconf'
+ VERSION='1.0.6_autoconf'
cat >>confdefs.h <<_ACEOF
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_barrier" >&5
+$as_echo_n "checking for pthread_barrier... " >&6; }
+if test "${ac_cv_func_pthread_barrier+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error "cannot run test program while cross compiling
+See \`config.log' for more details." "$LINENO" 5; }
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <pthread.h>
+ int main(void)
+ {
+ pthread_barrier_t t;
+ return 0;
+ }
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_pthread_barrier=yes
+else
+ ac_cv_func_pthread_barrier=no
+
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_pthread_barrier" >&5
+$as_echo "$ac_cv_func_pthread_barrier" >&6; }
+if test "$ac_cv_func_pthread_barrier" = "yes"; then
+
+$as_echo "#define HAVE_PTHREAD_BARRIER 1" >>confdefs.h
+
+fi
+
# Checks for typedefs, structures, and compiler characteristics.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by stressapptest $as_me 1.0.4_autoconf, which was
+This file was extended by stressapptest $as_me 1.0.6_autoconf, which was
generated by GNU Autoconf 2.65. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-stressapptest config.status 1.0.4_autoconf
+stressapptest config.status 1.0.6_autoconf
configured by $0, generated by GNU Autoconf 2.65,
with options \\"\$ac_cs_config\\"
AC_PREREQ(2.61)
-AC_INIT([stressapptest], [1.0.5_autoconf], [opensource@google.com])
+AC_INIT([stressapptest], [1.0.6_autoconf], [opensource@google.com])
AC_ARG_WITH(static, [ --with-static enable static linking])
AC_CHECK_HEADERS([sys/shm.h])
AC_SEARCH_LIBS([shm_open], [rt])
+AC_MSG_CHECKING(for pthread_barrier)
+AC_CACHE_VAL(
+ ac_cv_func_pthread_barrier,
+ AC_TRY_RUN(
+ [
+ #include <pthread.h>
+ int main(void)
+ {
+ pthread_barrier_t t;
+ return 0;
+ }
+ ],
+ ac_cv_func_pthread_barrier=yes,
+ ac_cv_func_pthread_barrier=no
+ )
+)
+AC_MSG_RESULT($ac_cv_func_pthread_barrier)
+if test "$ac_cv_func_pthread_barrier" = "yes"; then
+ AC_DEFINE(HAVE_PTHREAD_BARRIER, [1], [Define to 1 if the system has `pthread_barrier'.])
+fi
+
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
AC_C_CONST
uint64 frame, shift;
off64_t off = ((uintptr_t)vaddr) / getpagesize() * 8;
int fd = open(kPagemapPath, O_RDONLY);
- if (fd < 0 || lseek64(fd, off, SEEK_SET) != off || read(fd, &frame, 8) != 8) {
+ // /proc/self/pagemap is available in kernel >= 2.6.25
+ if (fd < 0)
+ return 0;
+
+ if (lseek64(fd, off, SEEK_SET) != off || read(fd, &frame, 8) != 8) {
int err = errno;
string errtxt = ErrorString(err);
- logprintf(0, "Error: failed to access %s with errno %d (%s)\n",
+ logprintf(0, "Process Error: failed to access %s with errno %d (%s)\n",
kPagemapPath, err, errtxt.c_str());
if (fd >= 0)
close(fd);
}
-// Translate user virtual to physical address.
+// Translate physical address to memory module name.
+// Assumes simple round-robin interleaving between memory channels of
+// 'interleave_size_' sized chunks, with repeated 'channel_width_'
+// blocks with bits distributed from each chip in that channel.
int OsLayer::FindDimm(uint64 addr, char *buf, int len) {
- char tmpbuf[256];
- snprintf(tmpbuf, sizeof(tmpbuf), "DIMM Unknown");
- snprintf(buf, len, "%s", tmpbuf);
- return 0;
+ static const string unknown = "DIMM Unknown";
+ if (!modules_) {
+ snprintf(buf, len, "%s", unknown.c_str());
+ return 0;
+ }
+
+ // Find channel by counting interleave units (typically cachelines),
+ // and mod by number of channels.
+ vector<string>& channel = (*modules_)[
+ (addr / interleave_size_) % modules_->size()];
+
+ // Find dram chip by finding which byte within the channel
+ // by address mod channel width, then divide the channel
+ // evenly among the listed dram chips. Note, this will not work
+ // with x4 dram.
+ int chip = (addr % (channel_width_ / 8)) /
+ ((channel_width_ / 8) / channel.size());
+ string name = channel[chip];
+ snprintf(buf, len, "%s", name.c_str());
+ return 1;
}
min_hugepages_bytes_ = min_bytes;
}
+ // Set parameters needed to translate physical address to memory module.
+ void SetDramMappingParams(int interleave_size, int channel_width,
+ vector< vector<string> > *modules) {
+ interleave_size_ = interleave_size;
+ channel_width_ = channel_width;
+ modules_ = modules;
+ }
+
// Initializes data strctures and open files.
// Returns false on error.
virtual bool Initialize();
bool use_posix_shm_; // Use 4k page shmem?
bool dynamic_mapped_shmem_; // Conserve virtual address space.
int shmid_; // Handle to shmem
+ vector< vector<string> > *modules_; // Memory module names per channel.
+ int interleave_size_; // Channel interleaving chunk size.
+ int channel_width_; // Channel width in bits.
int64 regionsize_; // Size of memory "regions"
int regioncount_; // Number of memory "regions"
for (int64 i = 0; i < pages_; i++) {
struct page_entry pe;
// Only get valid pages with uninitialized tags here.
- char buf[256];
if (GetValid(&pe, kInvalidTag)) {
int64 paddr = os_->VirtualToPhysical(pe.addr);
int32 region = os_->FindRegion(paddr);
- os_->FindDimm(paddr, buf, sizeof(buf));
if (i < 256) {
+ char buf[256];
+ os_->FindDimm(paddr, buf, sizeof(buf));
logprintf(12, "Log: address: %#llx, %s\n", paddr, buf);
}
region_[region]++;
if (min_hugepages_mbytes_ > 0)
os_->SetMinimumHugepagesSize(min_hugepages_mbytes_ * kMegabyte);
+ if (modules_.size() > 0) {
+ logprintf(6, "Log: Decoding memory: %dx%d bit channels,"
+ " %d byte burst size, %d modules per channel (x%d)\n",
+ modules_.size(), channel_width_, interleave_size_, modules_[0].size(),
+ channel_width_/modules_[0].size());
+ os_->SetDramMappingParams(interleave_size_, channel_width_, &modules_);
+ }
if (!os_->Initialize()) {
logprintf(0, "Process Error: Failed to initialize OS layer\n");
min_hugepages_mbytes_ = 0;
freepages_ = 0;
paddr_base_ = 0;
+ interleave_size_ = kCacheLineSize;
+ channel_width_ = 64;
user_break_ = false;
verbosity_ = 8;
continue;
}
+ ARG_IVALUE("--interleave_size", interleave_size_);
+ ARG_IVALUE("--channel_width", channel_width_);
+
+ if (!strcmp(argv[i], "--memory_channel")) {
+ i++;
+ if (i < argc) {
+ char *module = argv[i];
+ modules_.push_back(vector<string>());
+ while (char* next = strchr(module, ',')) {
+ modules_.back().push_back(string(module, next - module));
+ module = next + 1;
+ }
+ modules_.back().push_back(string(module));
+ }
+ continue;
+ }
+
// Default:
PrintVersion();
PrintHelp();
disk_pages_ = 1;
}
+ // Validate memory channel parameters if supplied
+ if (modules_.size()) {
+ if (interleave_size_ <= 0 ||
+ interleave_size_ & (interleave_size_ - 1)) {
+ logprintf(6, "Process Error: "
+ "Interleave size %d is not a power of 2.\n", interleave_size_);
+ bad_status();
+ return false;
+ }
+ for (uint i = 0; i < modules_.size(); i++)
+ if (modules_[i].size() != modules_[0].size()) {
+ logprintf(6, "Process Error: "
+ "Channels 0 and %d have a different amount of modules.\n",i);
+ bad_status();
+ return false;
+ }
+ if (modules_[0].size() & (modules_[0].size() - 1)) {
+ logprintf(6, "Process Error: "
+ "Amount of modules per memory channel is not a power of 2.\n");
+ bad_status();
+ return false;
+ }
+ if (channel_width_ < 16
+ || channel_width_ & (channel_width_ - 1)) {
+ logprintf(6, "Process Error: "
+ "Channel width %d is invalid.\n", channel_width_);
+ bad_status();
+ return false;
+ }
+ if (channel_width_ / modules_[0].size() < 8) {
+ logprintf(6, "Process Error: "
+ "Chip width x%d must be x8 or greater.\n", channel_width_ / modules_[0].size());
+ bad_status();
+ return false;
+ }
+ }
+
+
// Print each argument.
for (int i = 0; i < argc; i++) {
if (i)
" --paddr_base allocate memory starting from this address\n"
" --pause_delay delay (in seconds) between power spikes\n"
" --pause_duration duration (in seconds) of each pause\n"
- " --local_numa : choose memory regions associated with "
+ " --local_numa choose memory regions associated with "
+ "each CPU to be tested by that CPU\n"
+ " --remote_numa choose memory regions not associated with "
"each CPU to be tested by that CPU\n"
- " --remote_numa : choose memory regions not associated with "
- "each CPU to be tested by that CPU\n");
+ " --interleave_size bytes size in bytes of each channel's data as interleaved "
+ "between memory channels\n"
+ " --channel_width bits width in bits of each memory channel\n"
+ " --memory_channel u1,u2 defines a comma-separated list of names\n"
+ " for dram packages in a memory channel.\n"
+ " Use multiple times to define multiple channels.\n");
}
bool Sat::CheckGoogleSpecificArgs(int argc, char **argv, int *i) {
int64 freepages_; // How many invalid pages we need.
int disk_pages_; // Number of pages per temp file.
uint64 paddr_base_; // Physical address base.
+ vector< vector<string> > modules_; // Memory module names per channel.
+ int interleave_size_; // Channel interleaving chunk size in bytes.
+ // Usually cacheline sized.
+ int channel_width_; // Channel width in bits.
// Control flags.
volatile sig_atomic_t user_break_; // User has signalled early exit. Used as
void WorkerStatus::Initialize() {
sat_assert(0 == pthread_mutex_init(&num_workers_mutex_, NULL));
sat_assert(0 == pthread_rwlock_init(&status_rwlock_, NULL));
-#ifdef _POSIX_BARRIERS
+#ifdef HAVE_PTHREAD_BARRIERS
sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL,
num_workers_ + 1));
#endif
void WorkerStatus::Destroy() {
sat_assert(0 == pthread_mutex_destroy(&num_workers_mutex_));
sat_assert(0 == pthread_rwlock_destroy(&status_rwlock_));
-#ifdef _POSIX_BARRIERS
+#ifdef HAVE_PTHREAD_BARRIERS
sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
#endif
}
AcquireNumWorkersLock();
// Decrement num_workers_ and reinitialize pause_barrier_, which we know isn't
// in use because (status != PAUSE).
-#ifdef _POSIX_BARRIERS
+#ifdef HAVE_PTHREAD_BARRIERS
sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL, num_workers_));
#endif
enum Status { RUN, PAUSE, STOP };
void WaitOnPauseBarrier() {
-#ifdef _POSIX_BARRIERS
+#ifdef HAVE_PTHREAD_BARRIERS
int error = pthread_barrier_wait(&pause_barrier_);
if (error != PTHREAD_BARRIER_SERIAL_THREAD)
sat_assert(error == 0);
pthread_rwlock_t status_rwlock_;
Status status_;
-#ifdef _POSIX_BARRIERS
+#ifdef HAVE_PTHREAD_BARRIERS
// Guaranteed to not be in use when (status_ != PAUSE).
pthread_barrier_t pause_barrier_;
#endif