#include <sys/ioctl.h>
#include <linux/fs.h>
// For asynchronous I/O
+#ifdef HAVE_LIBAIO_H
#include <libaio.h>
+#endif
#include <sys/syscall.h>
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) {
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() {
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();
// 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
}
// 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
}
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
}
// 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;
}
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.
// 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",
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",
// 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_])++;
device_sectors_ = 0;
non_destructive_ = 0;
+#ifdef HAVE_LIBAIO_H
aio_ctx_ = 0;
+#endif
block_table_ = block_table;
update_block_table_ = 1;
// 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);
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",
// 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.
}
return true;
+#else // !HAVE_LIBAIO_H
+ return false;
+#endif
}
// Write a block to disk.
}
// 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 "
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"
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, "