chiark / gitweb /
Add better ARM/Android support, support a wider variety of configure options.
[stressapptest] / src / worker.cc
index 2fab28eac4f9eb40f068f04f009b529a92042b13..dcf4dcb6e6370ab18cfab6eafec1c21c64e41e9b 100644 (file)
@@ -44,7 +44,9 @@
 #include <sys/ioctl.h>
 #include <linux/fs.h>
 // For asynchronous I/O
+#ifdef HAVE_LIBAIO_H
 #include <libaio.h>
+#endif
 
 #include <sys/syscall.h>
 
@@ -75,11 +77,6 @@ _syscall3(int, sched_setaffinity, pid_t, pid,
           unsigned int, len, cpu_set_t*, mask)
 #endif
 
-// Linux aio syscalls.
-#if !defined(__NR_io_setup)
-#error "No aio headers inculded, please install libaio."
-#endif
-
 namespace {
   // Get HW core ID from cpuid instruction.
   inline int apicid(void) {
@@ -147,14 +144,18 @@ static void *ThreadSpawnerGeneric(void *ptr) {
 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
   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
   sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
+#endif
 }
 
 void WorkerStatus::PauseWorkers() {
@@ -219,8 +220,10 @@ void WorkerStatus::RemoveSelf() {
   AcquireNumWorkersLock();
   // Decrement num_workers_ and reinitialize pause_barrier_, which we know isn't
   // in use because (status != PAUSE).
+#ifdef _POSIX_BARRIERS
   sat_assert(0 == pthread_barrier_destroy(&pause_barrier_));
   sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL, num_workers_));
+#endif
   --num_workers_;
   ReleaseNumWorkersLock();
 
@@ -399,7 +402,11 @@ bool WorkerThread::Work() {
 //   mask = 13 (1101b): cpu0, 2, 3
 bool WorkerThread::AvailableCpus(cpu_set_t *cpuset) {
   CPU_ZERO(cpuset);
+#ifdef HAVE_SCHED_GETAFFINITY
   return sched_getaffinity(getppid(), sizeof(*cpuset), cpuset) == 0;
+#else
+  return 0;
+#endif
 }
 
 
@@ -409,7 +416,11 @@ bool WorkerThread::AvailableCpus(cpu_set_t *cpuset) {
 //   mask = 13 (1101b): cpu0, 2, 3
 bool WorkerThread::CurrentCpus(cpu_set_t *cpuset) {
   CPU_ZERO(cpuset);
+#ifdef HAVE_SCHED_GETAFFINITY
   return sched_getaffinity(0, sizeof(*cpuset), cpuset) == 0;
+#else
+  return 0;
+#endif
 }
 
 
@@ -436,7 +447,11 @@ bool WorkerThread::BindToCpus(const cpu_set_t *thread_mask) {
               cpuset_format(&process_mask).c_str());
     return false;
   }
+#ifdef HAVE_SCHED_GETAFFINITY
   return (sched_setaffinity(gettid(), sizeof(*thread_mask), thread_mask) == 0);
+#else
+  return 0;
+#endif
 }
 
 
@@ -1585,15 +1600,21 @@ void FileThread::SetFile(const char *filename_init) {
 
 // Open the file for access.
 bool FileThread::OpenFile(int *pfile) {
-  int fd = open(filename_.c_str(),
-                O_RDWR | O_CREAT | O_SYNC | O_DIRECT,
-                0644);
+  bool no_O_DIRECT = false;
+  int flags = O_RDWR | O_CREAT | O_SYNC;
+  int fd = open(filename_.c_str(), flags | O_DIRECT, 0644);
+  if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) {
+    no_O_DIRECT = true;
+    fd = open(filename_.c_str(), flags, 0644); // Try without O_DIRECT
+  }
   if (fd < 0) {
     logprintf(0, "Process Error: Failed to create file %s!!\n",
               filename_.c_str());
     pages_copied_ = 0;
     return false;
   }
+  if (no_O_DIRECT)
+    os_->ActivateFlushPageCache(); // Not using O_DIRECT fixed EINVAL
   *pfile = fd;
   return true;
 }
@@ -1664,7 +1685,7 @@ bool FileThread::WritePages(int fd) {
     if (!result)
       return false;
   }
-  return true;
+  return os_->FlushPageCache(); // If O_DIRECT worked, this will be a NOP.
 }
 
 // Copy data from file into memory block.
@@ -1791,7 +1812,12 @@ bool FileThread::PagePrepare() {
 
   // Init a local buffer if we need it.
   if (!page_io_) {
+#ifdef HAVE_POSIX_MEMALIGN
     int result = posix_memalign(&local_page_, 512, sat_->page_length());
+#else
+    local_page_ = memalign(512, sat_->page_length());
+    int result = (local_page_ == 0);
+#endif
     if (result) {
       logprintf(0, "Process Error: disk thread posix_memalign "
                    "returned %d (fail)\n",
@@ -2358,7 +2384,12 @@ bool NetworkSlaveThread::Work() {
   int64 loops = 0;
   // Init a local buffer for storing data.
   void *local_page = NULL;
+#ifdef HAVE_POSIX_MEMALIGN
   int result = posix_memalign(&local_page, 512, sat_->page_length());
+#else
+  local_page = memalign(512, sat_->page_length());
+  int result = (local_page == 0);
+#endif
   if (result) {
     logprintf(0, "Process Error: net slave posix_memalign "
                  "returned %d (fail)\n",
@@ -2459,7 +2490,11 @@ bool CpuCacheCoherencyThread::Work() {
       // Choose a datastructure in random and increment the appropriate
       // member in that according to the offset (which is the same as the
       // thread number.
+#ifdef HAVE_RAND_R
       int r = rand_r(&seed);
+#else
+      int r = rand();
+#endif
       r = cc_cacheline_count_ * (r / (RAND_MAX + 1.0));
       // Increment the member of the randomely selected structure.
       (cc_cacheline_data_[r].num[cc_thread_num_])++;
@@ -2521,7 +2556,9 @@ DiskThread::DiskThread(DiskBlockTable *block_table) {
   device_sectors_ = 0;
   non_destructive_ = 0;
 
+#ifdef HAVE_LIBAIO_H
   aio_ctx_ = 0;
+#endif
   block_table_ = block_table;
   update_block_table_ = 1;
 
@@ -2660,14 +2697,20 @@ bool DiskThread::SetParameters(int read_block_size,
 
 // Open a device, return false on failure.
 bool DiskThread::OpenDevice(int *pfile) {
-  int fd = open(device_name_.c_str(),
-                O_RDWR | O_SYNC | O_DIRECT | O_LARGEFILE,
-                0);
+  bool no_O_DIRECT = false;
+  int flags = O_RDWR | O_SYNC | O_LARGEFILE;
+  int fd = open(device_name_.c_str(), flags | O_DIRECT, 0);
+  if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) {
+    no_O_DIRECT = true;
+    fd = open(device_name_.c_str(), flags, 0); // Try without O_DIRECT
+  }
   if (fd < 0) {
     logprintf(0, "Process Error: Failed to open device %s (thread %d)!!\n",
               device_name_.c_str(), thread_num_);
     return false;
   }
+  if (no_O_DIRECT)
+    os_->ActivateFlushPageCache();
   *pfile = fd;
 
   return GetDiskSize(fd);
@@ -2827,6 +2870,8 @@ bool DiskThread::DoWork(int fd) {
 
       in_flight_sectors_.push(block);
     }
+    if (!os_->FlushPageCache()) // If O_DIRECT worked, this will be a NOP.
+      return false;
 
     // Verify blocks on disk.
     logprintf(20, "Log: Read phase for disk %s (thread %d).\n",
@@ -2849,6 +2894,7 @@ bool DiskThread::DoWork(int fd) {
 // Return false if the IO is not set up.
 bool DiskThread::AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
                             int64 offset, int64 timeout) {
+#ifdef HAVE_LIBAIO_H
   // Use the Linux native asynchronous I/O interface for reading/writing.
   // A read/write consists of three basic steps:
   //    1. create an io context.
@@ -2957,6 +3003,9 @@ bool DiskThread::AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
   }
 
   return true;
+#else // !HAVE_LIBAIO_H
+  return false;
+#endif
 }
 
 // Write a block to disk.
@@ -3104,9 +3153,14 @@ bool DiskThread::Work() {
   }
 
   // Allocate a block buffer aligned to 512 bytes since the kernel requires it
-  // when using direst IO.
+  // when using direct IO.
+#ifdef HAVE_POSIX_MEMALIGN
   int memalign_result = posix_memalign(&block_buffer_, kBufferAlignment,
                               sat_->page_length());
+#else
+  block_buffer_ = memalign(kBufferAlignment, sat_->page_length());
+  int memalign_result = (block_buffer_ == 0);
+#endif
   if (memalign_result) {
     CloseDevice(fd);
     logprintf(0, "Process Error: Unable to allocate memory for buffers "
@@ -3116,6 +3170,7 @@ bool DiskThread::Work() {
     return false;
   }
 
+#ifdef HAVE_LIBAIO_H
   if (io_setup(5, &aio_ctx_)) {
     CloseDevice(fd);
     logprintf(0, "Process Error: Unable to create aio context for disk %s"
@@ -3124,12 +3179,15 @@ bool DiskThread::Work() {
     status_ = false;
     return false;
   }
+#endif
 
   bool result = DoWork(fd);
 
   status_ = result;
 
+#ifdef HAVE_LIBAIO_H
   io_destroy(aio_ctx_);
+#endif
   CloseDevice(fd);
 
   logprintf(9, "Log: Completed %d (disk %s): disk thread status %d, "