1b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copyright 2006 Google Inc. All Rights Reserved. 2b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Licensed under the Apache License, Version 2.0 (the "License"); 4b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// you may not use this file except in compliance with the License. 5b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// You may obtain a copy of the License at 6b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 7b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// http://www.apache.org/licenses/LICENSE-2.0 8b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 9b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Unless required by applicable law or agreed to in writing, software 10b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// distributed under the License is distributed on an "AS IS" BASIS, 11b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// See the License for the specific language governing permissions and 13b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// limitations under the License. 14b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 15b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// worker.cc : individual tasks that can be run in combination to 16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// stress the system 17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <errno.h> 19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <pthread.h> 20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sched.h> 21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <signal.h> 22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdlib.h> 23b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdio.h> 24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdint.h> 25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string.h> 26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <time.h> 27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <unistd.h> 28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 29b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/select.h> 30b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/stat.h> 31b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/types.h> 32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/times.h> 33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// These are necessary, but on by default 35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// #define __USE_GNU 36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// #define __USE_LARGEFILE64 37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <fcntl.h> 38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/socket.h> 39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <netdb.h> 40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <arpa/inet.h> 41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <linux/unistd.h> // for gettid 42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// For size of block device 44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/ioctl.h> 45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <linux/fs.h> 46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// For asynchronous I/O 478f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H 48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <libaio.h> 498f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/syscall.h> 52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <set> 54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string> 55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version, 57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct. 58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "error_diag.h" // NOLINT 59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "os.h" // NOLINT 60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "pattern.h" // NOLINT 61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "queue.h" // NOLINT 62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sat.h" // NOLINT 63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sattypes.h" // NOLINT 64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "worker.h" // NOLINT 65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Syscalls 67b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Why ubuntu, do you hate gettid so bad? 68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if !defined(__NR_gettid) 69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson #define __NR_gettid 224 70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif 71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define gettid() syscall(__NR_gettid) 73b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if !defined(CPU_SETSIZE) 74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson_syscall3(int, sched_getaffinity, pid_t, pid, 75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int, len, cpu_set_t*, mask) 76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson_syscall3(int, sched_setaffinity, pid_t, pid, 77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int, len, cpu_set_t*, mask) 78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif 79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonnamespace { 81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Get HW core ID from cpuid instruction. 82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson inline int apicid(void) { 83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int cpu; 84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if defined(STRESSAPPTEST_CPU_X86_64) || defined(STRESSAPPTEST_CPU_I686) 85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson __asm __volatile("cpuid" : "=b" (cpu) : "a" (1) : "cx", "dx"); 86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#elif defined(STRESSAPPTEST_CPU_ARMV7A) 87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson #warning "Unsupported CPU type ARMV7A: unable to determine core ID." 88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpu = 0; 89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#else 90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson #warning "Unsupported CPU type: unable to determine core ID." 91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpu = 0; 92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif 93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (cpu >> 24); 94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Work around the sad fact that there are two (gnu, xsi) incompatible 97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // versions of strerror_r floating around google. Awesome. 98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool sat_strerror(int err, char *buf, int len) { 99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buf[0] = 0; 100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *errmsg = reinterpret_cast<char*>(strerror_r(err, buf, len)); 101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int retval = reinterpret_cast<int64>(errmsg); 102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (retval == 0) 103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (retval == -1) 105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errmsg != buf) { 107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson strncpy(buf, errmsg, len); 108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buf[len - 1] = 0; 109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson inline uint64 addr_to_tag(void *address) { 115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return reinterpret_cast<uint64>(address); 116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if !defined(O_DIRECT) 120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Sometimes this isn't available. 121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Disregard if it's not defined. 122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson #define O_DIRECT 0 123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif 124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// A struct to hold captured errors, for later reporting. 126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonstruct ErrorRecord { 127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 actual; // This is the actual value read. 128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 reread; // This is the actual value, reread. 129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 expected; // This is what it should have been. 130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *vaddr; // This is where it was (or wasn't). 131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *vbyteaddr; // This is byte specific where the data was (or wasn't). 132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 paddr; // This is the bus address, if available. 133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *tagvaddr; // This holds the tag value if this data was tagged. 134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 tagpaddr; // This holds the physical address corresponding to the tag. 135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}; 136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This is a helper function to create new threads with pthreads. 138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonstatic void *ThreadSpawnerGeneric(void *ptr) { 139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WorkerThread *worker = static_cast<WorkerThread*>(ptr); 140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson worker->StartRoutine(); 141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return NULL; 142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::Initialize() { 145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_mutex_init(&num_workers_mutex_, NULL)); 146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_rwlock_init(&status_rwlock_, NULL)); 1478f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef _POSIX_BARRIERS 148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL, 149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_workers_ + 1)); 1508f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::Destroy() { 154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_mutex_destroy(&num_workers_mutex_)); 155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_rwlock_destroy(&status_rwlock_)); 1568f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef _POSIX_BARRIERS 157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_barrier_destroy(&pause_barrier_)); 1588f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::PauseWorkers() { 162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (SetStatus(PAUSE) != PAUSE) 163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::ResumeWorkers() { 167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (SetStatus(RUN) == PAUSE) 168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::StopWorkers() { 172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (SetStatus(STOP) == PAUSE) 173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerStatus::ContinueRunning() { 177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This loop is an optimization. We use it to immediately re-check the status 178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // after resuming from a pause, instead of returning and waiting for the next 179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // call to this function. 180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (;;) { 181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson switch (GetStatus()) { 182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson case RUN: 183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson case PAUSE: 185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait for the other workers to call this function so that 186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // PauseWorkers() can return. 187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait for ResumeWorkers() to be called. 189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson case STOP: 192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerStatus::ContinueRunningNoPause() { 198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (GetStatus() != STOP); 199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerStatus::RemoveSelf() { 202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Acquire a read lock on status_rwlock_ while (status_ != PAUSE). 203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (;;) { 204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AcquireStatusReadLock(); 205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (status_ != PAUSE) 206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We need to obey PauseWorkers() just like ContinueRunning() would, so that 208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // the other threads won't wait on pause_barrier_ forever. 209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReleaseStatusLock(); 210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait for the other workers to call this function so that PauseWorkers() 211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // can return. 212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait for ResumeWorkers() to be called. 214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WaitOnPauseBarrier(); 215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This lock would be unnecessary if we held a write lock instead of a read 218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // lock on status_rwlock_, but that would also force all threads calling 219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // ContinueRunning() to wait on this one. Using a separate lock avoids that. 220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AcquireNumWorkersLock(); 221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Decrement num_workers_ and reinitialize pause_barrier_, which we know isn't 222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // in use because (status != PAUSE). 2238f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef _POSIX_BARRIERS 224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_barrier_destroy(&pause_barrier_)); 225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(0 == pthread_barrier_init(&pause_barrier_, NULL, num_workers_)); 2268f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson --num_workers_; 228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReleaseNumWorkersLock(); 229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Release status_rwlock_. 231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReleaseStatusLock(); 232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Parent thread class. 236b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonWorkerThread::WorkerThread() { 237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ = 0; 240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson runduration_usec_ = 1; 241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson priority_ = Normal; 242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson worker_status_ = NULL; 243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_spawner_ = &ThreadSpawnerGeneric; 244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag_mode_ = false; 245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 247b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonWorkerThread::~WorkerThread() {} 248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Constructors. Just init some default values. 250b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonFillThread::FillThread() { 251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_pages_to_fill_ = 0; 252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initialize file name to empty. 255b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonFileThread::FileThread() { 256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_ = ""; 257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson devicename_ = ""; 258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pass_ = 0; 259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_io_ = true; 260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc_page_ = -1; 261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson local_page_ = NULL; 262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// If file thread used bounce buffer in memory, account for the extra 265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// copy for memory bandwidth calculation. 266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonfloat FileThread::GetMemoryCopiedData() { 267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!os_->normal_mem()) 268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return GetCopiedData(); 269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else 270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initialize target hostname to be invalid. 274b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonNetworkThread::NetworkThread() { 275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson snprintf(ipaddr_, sizeof(ipaddr_), "Unknown"); 276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sock_ = 0; 277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initialize? 280b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonNetworkSlaveThread::NetworkSlaveThread() { 281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initialize? 284b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonNetworkListenThread::NetworkListenThread() { 285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Init member variables. 288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerThread::InitThread(int thread_num_init, 289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class Sat *sat_init, 290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class OsLayer *os_init, 291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class PatternList *patternlist_init, 292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WorkerStatus *worker_status) { 293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(worker_status); 294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson worker_status->AddWorkers(1); 295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_ = thread_num_init; 297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_ = sat_init; 298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_ = os_init; 299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson patternlist_ = patternlist_init; 300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson worker_status_ = worker_status; 301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AvailableCpus(&cpu_mask_); 303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag_ = 0xffffffff; 304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag_mode_ = sat_->tag_mode(); 306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Use pthreads to prioritize a system thread. 310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::InitPriority() { 311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This doesn't affect performance that much, and may not be too safe. 312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool ret = BindToCpus(&cpu_mask_); 314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!ret) 315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: Bind to %s failed.\n", 316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpuset_format(&cpu_mask_).c_str()); 317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: Thread %d running on apic ID %d mask %s (%s).\n", 319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, apicid(), 320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CurrentCpusFormat().c_str(), 321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpuset_format(&cpu_mask_).c_str()); 322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if 0 323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (priority_ == High) { 324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sched_param param; 325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson param.sched_priority = 1; 326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Set the priority; others are unchanged. 327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: Changing priority to SCHED_FIFO %d\n", 328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson param.sched_priority); 329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sched_setscheduler(0, SCHED_FIFO, ¶m)) { 330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256]; 331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(errno, buf, sizeof(buf)); 332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: sched_setscheduler " 333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "failed - error %d %s\n", 334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errno, buf); 335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif 338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Use pthreads to create a system thread. 342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint WorkerThread::SpawnThread() { 343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Create the new thread. 344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int result = pthread_create(&thread_, NULL, thread_spawner_, this); 345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (result) { 346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256]; 347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(result, buf, sizeof(buf)); 348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: pthread_create " 349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "failed - error %d %s\n", result, 350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buf); 351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 0 is pthreads success. 356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Kill the worker thread with SIGINT. 360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::KillThread() { 361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (pthread_kill(thread_, SIGINT) == 0); 362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Block until thread has exited. 365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::JoinThread() { 366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int result = pthread_join(thread_, NULL); 367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (result) { 369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: pthread_join failed - error %d\n", result); 370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 0 is pthreads success. 374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (!result); 375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerThread::StartRoutine() { 379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InitPriority(); 380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson StartThreadTimer(); 381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson Work(); 382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson StopThreadTimer(); 383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson worker_status_->RemoveSelf(); 384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Thread work loop. Execute until marked finished. 388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::Work() { 389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson do { 390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: ...\n"); 391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Sleep for 1 second. 392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_sleep(1); 393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } while (IsReadyToRun()); 394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns CPU mask of CPUs available to this process, 400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Conceptually, each bit represents a logical CPU, ie: 401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 3 (11b): cpu0, 1 402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 13 (1101b): cpu0, 2, 3 403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::AvailableCpus(cpu_set_t *cpuset) { 404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CPU_ZERO(cpuset); 4058f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_SCHED_GETAFFINITY 406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return sched_getaffinity(getppid(), sizeof(*cpuset), cpuset) == 0; 4078f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 4088f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson return 0; 4098f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns CPU mask of CPUs this thread is bound to, 414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Conceptually, each bit represents a logical CPU, ie: 415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 3 (11b): cpu0, 1 416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 13 (1101b): cpu0, 2, 3 417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::CurrentCpus(cpu_set_t *cpuset) { 418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CPU_ZERO(cpuset); 4198f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_SCHED_GETAFFINITY 420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return sched_getaffinity(0, sizeof(*cpuset), cpuset) == 0; 4218f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 4228f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson return 0; 4238f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Bind worker thread to specified CPU(s) 428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Args: 429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// thread_mask: cpu_set_t representing CPUs, ie 430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 1 (01b): cpu0 431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 3 (11b): cpu0, 1 432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// mask = 13 (1101b): cpu0, 2, 3 433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// 434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns true on success, false otherwise. 435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::BindToCpus(const cpu_set_t *thread_mask) { 436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpu_set_t process_mask; 437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AvailableCpus(&process_mask); 438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (cpuset_isequal(thread_mask, &process_mask)) 439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: available CPU mask - %s\n", 442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpuset_format(&process_mask).c_str()); 443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!cpuset_issubset(thread_mask, &process_mask)) { 444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Invalid cpu_mask, ie cpu not allocated to this process or doesn't exist. 445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: requested CPUs %s not a subset of available %s\n", 446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpuset_format(thread_mask).c_str(), 447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cpuset_format(&process_mask).c_str()); 448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 4508f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_SCHED_GETAFFINITY 451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (sched_setaffinity(gettid(), sizeof(*thread_mask), thread_mask) == 0); 4528f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 4538f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson return 0; 4548f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// A worker thread can yield itself to give up CPU until it's scheduled again. 459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns true on success, false on error. 460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::YieldSelf() { 461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (sched_yield() == 0); 462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Fill this page with its pattern. 466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::FillPage(struct page_entry *pe) { 467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error check arguments. 468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pe == 0) { 469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Fill Page entry null\n"); 470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Mask is the bitmask of indexes used by the pattern. 474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // It is the pattern size -1. Size is always a power of 2. 475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *memwords = static_cast<uint64*>(pe->addr); 476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int length = sat_->page_length(); 477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_) { 479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Select tag or data as appropriate. 480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length / wordsize_; i++) { 481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((i & 0x7) == 0) { 484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = addr_to_tag(&memwords[i]); 485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pe->pattern->pattern(i << 1); 487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pe->pattern->pattern((i << 1) + 1); 488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memwords[i] = data.l64; 490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Just fill in untagged data directly. 493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length / wordsize_; i++) { 494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pe->pattern->pattern(i << 1); 497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pe->pattern->pattern((i << 1) + 1); 498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memwords[i] = data.l64; 499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 1; 503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Tell the thread how many pages to fill. 507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid FillThread::SetFillPages(int64 num_pages_to_fill_init) { 508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_pages_to_fill_ = num_pages_to_fill_init; 509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Fill this page with a random pattern. 512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FillThread::FillPageRandom(struct page_entry *pe) { 513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error check arguments. 514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pe == 0) { 515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Fill Page entry null\n"); 516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((patternlist_ == 0) || (patternlist_->Size() == 0)) { 519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: No data patterns available\n"); 520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Choose a random pattern for this block. 524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pe->pattern = patternlist_->GetRandomPattern(); 525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pe->pattern == 0) { 526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Null data pattern\n"); 527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Actually fill the page. 531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return FillPage(pe); 532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Memory fill work loop. Execute until alloted pages filled. 536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FillThread::Work() { 537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting fill thread %d\n", thread_num_); 540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We want to fill num_pages_to_fill pages, and 542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // stop when we've filled that many. 543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We also want to capture early break 544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry pe; 545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun() && (loops < num_pages_to_fill_)) { 547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetEmpty(&pe); 548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: fill_thread failed to pop pages, " 550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Fill the page with pattern 555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && FillPageRandom(&pe); 556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) break; 557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Put the page back on the queue. 559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&pe); 560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: fill_thread failed to push pages, " 562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Fill in thread status. 569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: Fill thread. Status %d, %d pages filled\n", 572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print error information about a data miscompare. 578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerThread::ProcessError(struct ErrorRecord *error, 579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int priority, 580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *message) { 581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char dimm_string[256] = ""; 582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int apic_id = apicid(); 584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine if this is a write or read error. 586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread = *(error->vaddr); 588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *good = reinterpret_cast<char*>(&(error->expected)); 590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *bad = reinterpret_cast<char*>(&(error->actual)); 591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(error->expected != error->actual); 593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int offset = 0; 594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) { 595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (good[offset] != bad[offset]) 596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset; 600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Find physical address if possible. 602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr = os_->VirtualToPhysical(error->vbyteaddr); 603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pretty print DIMM mapping if available. 605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string)); 606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Report parseable error. 608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (priority < 5) { 609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Run miscompare error through diagnoser for logging and reporting. 610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->error_diagnoser_->AddMiscompareError(dimm_string, 611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson reinterpret_cast<uint64> 612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (error->vaddr), 1); 613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(priority, 615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%s: miscompare on CPU %d(0x%s) at %p(0x%llx:%s): " 616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "read:0x%016llx, reread:0x%016llx expected:0x%016llx\n", 617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson message, 618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson apic_id, 619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CurrentCpusFormat().c_str(), 620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vaddr, 621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr, 622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dimm_string, 623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->actual, 624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread, 625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->expected); 626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Overwrite incorrect data with correct data to prevent 630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // future miscompares when this data is reused. 631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *(error->vaddr) = error->expected; 632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print error information about a data miscompare. 638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid FileThread::ProcessError(struct ErrorRecord *error, 639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int priority, 640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *message) { 641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char dimm_string[256] = ""; 642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine if this is a write or read error. 644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread = *(error->vaddr); 646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *good = reinterpret_cast<char*>(&(error->expected)); 648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *bad = reinterpret_cast<char*>(&(error->actual)); 649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(error->expected != error->actual); 651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int offset = 0; 652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) { 653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (good[offset] != bad[offset]) 654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset; 658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Find physical address if possible. 660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr = os_->VirtualToPhysical(error->vbyteaddr); 661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pretty print DIMM mapping if available. 663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string)); 664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If crc_page_ is valid, ie checking content read back from file, 666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // track src/dst memory addresses. Otherwise catagorize as general 667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // mememory miscompare for CRC checking everywhere else. 668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (crc_page_ != -1) { 669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int miscompare_byteoffset = static_cast<char*>(error->vbyteaddr) - 670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson static_cast<char*>(page_recs_[crc_page_].dst); 671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->error_diagnoser_->AddHDDMiscompareError(devicename_, 672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc_page_, 673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson miscompare_byteoffset, 674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[crc_page_].src, 675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[crc_page_].dst); 676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->error_diagnoser_->AddMiscompareError(dimm_string, 678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson reinterpret_cast<uint64> 679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (error->vaddr), 1); 680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(priority, 683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%s: miscompare on %s at %p(0x%llx:%s): read:0x%016llx, " 684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "reread:0x%016llx expected:0x%016llx\n", 685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson message, 686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson devicename_.c_str(), 687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vaddr, 688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr, 689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dimm_string, 690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->actual, 691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread, 692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->expected); 693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Overwrite incorrect data with correct data to prevent 695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // future miscompares when this data is reused. 696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *(error->vaddr) = error->expected; 697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Do a word by word result check of a region. 702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print errors on mismatches. 703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint WorkerThread::CheckRegion(void *addr, 704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class Pattern *pattern, 705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 length, 706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int offset, 707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 pattern_offset) { 708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *memblock = static_cast<uint64*>(addr); 709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int kErrorLimit = 128; 710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errors = 0; 711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int overflowerrors = 0; // Count of overflowed errors. 712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool page_error = false; 713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson string errormessage("Hardware Error"); 714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct ErrorRecord 715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson recorded[kErrorLimit]; // Queued errors for later printing. 716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For each word in the data region. 718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length / wordsize_; i++) { 719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 actual = memblock[i]; 720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 expected; 721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine the value that should be there. 723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int index = 2 * i + pattern_offset; 725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pattern->pattern(index); 726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pattern->pattern(index + 1); 727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected = data.l64; 728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check tags if necessary. 729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_ && ((reinterpret_cast<uint64>(&memblock[i]) & 0x3f) == 0)) { 730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected = addr_to_tag(&memblock[i]); 731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If the value is incorrect, save an error record for later printing. 735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (actual != expected) { 736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errors < kErrorLimit) { 737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson recorded[errors].actual = actual; 738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson recorded[errors].expected = expected; 739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson recorded[errors].vaddr = &memblock[i]; 740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors++; 741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_error = true; 743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If we have overflowed the error queue, just print the errors now. 744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(10, "Log: Error record overflow, too many miscompares!\n"); 745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errormessage = "Page Error"; 746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Find if this is a whole block corruption. 752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_error && !tag_mode_) { 753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int patsize = patternlist_->Size(); 754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int pat = 0; pat < patsize; pat++) { 755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class Pattern *altpattern = patternlist_->GetPattern(pat); 756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int kGood = 0; 757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int kBad = 1; 758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int kGoodAgain = 2; 759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int kNoMatch = 3; 760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int state = kGood; 761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int badstart = 0; 762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int badend = 0; 763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Don't match against ourself! 765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pattern == altpattern) 766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length / wordsize_; i++) { 769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 actual = memblock[i]; 770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t expected; 771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t possible; 772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine the value that should be there. 774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int index = 2 * i + pattern_offset; 775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected.l32.l = pattern->pattern(index); 777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected.l32.h = pattern->pattern(index + 1); 778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson possible.l32.l = pattern->pattern(index); 780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson possible.l32.h = pattern->pattern(index + 1); 781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (state == kGood) { 783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (actual == expected.l64) { 784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (actual == possible.l64) { 786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson badstart = i; 787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson badend = i; 788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson state = kBad; 789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson state = kNoMatch; 792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (state == kBad) { 795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (actual == possible.l64) { 796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson badend = i; 797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (actual == expected.l64) { 799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson state = kGoodAgain; 800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson state = kNoMatch; 803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (state == kGoodAgain) { 806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (actual == expected.l64) { 807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson continue; 808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson state = kNoMatch; 810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((state == kGoodAgain) || (state == kBad)) { 816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int blockerrors = badend - badstart + 1; 817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errormessage = "Block Error"; 818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessError(&recorded[0], 0, errormessage.c_str()); 819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Block Error: (%p) pattern %s instead of %s, " 820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%d bytes from offset 0x%x to 0x%x\n", 821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson &memblock[badstart], 822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson altpattern->name(), pattern->name(), 823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blockerrors * wordsize_, 824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset + badstart * wordsize_, 825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset + badend * wordsize_); 826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += blockerrors; 827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return blockerrors; 828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Process error queue after all errors have been recorded. 834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int err = 0; err < errors; err++) { 835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int priority = 5; 836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount_ + err < 30) 837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson priority = 0; // Bump up the priority for the first few errors. 838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessError(&recorded[err], priority, errormessage.c_str()); 839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_error) { 842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For each word in the data region. 843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int error_recount = 0; 844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length / wordsize_; i++) { 845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 actual = memblock[i]; 846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 expected; 847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine the value that should be there. 849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int index = 2 * i + pattern_offset; 850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pattern->pattern(index); 852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pattern->pattern(index + 1); 853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected = data.l64; 854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check tags if necessary. 856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_ && ((reinterpret_cast<uint64>(&memblock[i]) & 0x3f) == 0)) { 857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expected = addr_to_tag(&memblock[i]); 858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If the value is incorrect, save an error record for later printing. 861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (actual != expected) { 862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (error_recount < kErrorLimit) { 863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We already reported these. 864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error_recount++; 865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If we have overflowed the error queue, print the errors now. 867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct ErrorRecord er; 868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.actual = actual; 869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.expected = expected; 870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.vaddr = &memblock[i]; 871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the error printout. This will take a long time and 873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // likely change the machine state. 874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessError(&er, 12, errormessage.c_str()); 875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson overflowerrors++; 876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Keep track of observed errors. 882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += errors + overflowerrors; 883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return errors + overflowerrors; 884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonfloat WorkerThread::GetCopiedData() { 887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return pages_copied_ * sat_->page_length() / kMegabyte; 888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Calculate the CRC of a region. 891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Result check if the CRC mismatches. 892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint WorkerThread::CrcCheckPage(struct page_entry *srcpe) { 893b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blocksize = 4096; 894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blockwords = blocksize / wordsize_; 895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errors = 0; 896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 897b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const AdlerChecksum *expectedcrc = srcpe->pattern->crc(); 898b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *memblock = static_cast<uint64*>(srcpe->addr); 899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks = sat_->page_length() / blocksize; 900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int currentblock = 0; currentblock < blocks; currentblock++) { 901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *memslice = memblock + currentblock * blockwords; 902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum crc; 904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_) { 905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerAddrCrcC(memslice, blocksize, &crc, srcpe); 906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CalculateAdlerChecksum(memslice, blocksize, &crc); 908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If the CRC does not match, we'd better look closer. 911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!crc.Equals(*expectedcrc)) { 912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: CrcCheckPage Falling through to slow compare, " 913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "CRC mismatch %s != %s\n", 914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errorcount = CheckRegion(memslice, 917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocksize, 919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson currentblock * blocksize, 0); 920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount == 0) { 921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: CrcCheckPage CRC mismatch %s != %s, " 922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "but no miscompares found.\n", 923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += errorcount; 927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For odd length transfers, we should never hit this. 931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int leftovers = sat_->page_length() % blocksize; 932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (leftovers) { 933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *memslice = memblock + blocks * blockwords; 934b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += CheckRegion(memslice, 935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson leftovers, 937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks * blocksize, 0); 938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return errors; 940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print error information about a data miscompare. 944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid WorkerThread::ProcessTagError(struct ErrorRecord *error, 945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int priority, 946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *message) { 947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char dimm_string[256] = ""; 948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char tag_dimm_string[256] = ""; 949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool read_error = false; 950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int apic_id = apicid(); 952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine if this is a write or read error. 954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread = *(error->vaddr); 956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Distinguish read and write errors. 958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (error->actual != error->reread) { 959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_error = true; 960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(error->expected != error->actual); 963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vbyteaddr = reinterpret_cast<char*>(error->vaddr); 965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Find physical address if possible. 967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr = os_->VirtualToPhysical(error->vbyteaddr); 968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->tagpaddr = os_->VirtualToPhysical(error->tagvaddr); 969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pretty print DIMM mapping if available. 971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FindDimm(error->paddr, dimm_string, sizeof(dimm_string)); 972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pretty print DIMM mapping if available. 973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FindDimm(error->tagpaddr, tag_dimm_string, sizeof(tag_dimm_string)); 974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Report parseable error. 976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (priority < 5) { 977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(priority, 978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%s: Tag from %p(0x%llx:%s) (%s) " 979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "miscompare on CPU %d(0x%s) at %p(0x%llx:%s): " 980b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "read:0x%016llx, reread:0x%016llx expected:0x%016llx\n", 981b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson message, 982b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->tagvaddr, error->tagpaddr, 983b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag_dimm_string, 984b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_error ? "read error" : "write error", 985b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson apic_id, 986b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CurrentCpusFormat().c_str(), 987b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vaddr, 988b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr, 989b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dimm_string, 990b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->actual, 991b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread, 992b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->expected); 993b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 994b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 995b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += 1; 996b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Overwrite incorrect data with correct data to prevent 998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // future miscompares when this data is reused. 999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *(error->vaddr) = error->expected; 1000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 1001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print out and log a tag error. 1005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::ReportTagError( 1006b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *mem64, 1007b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 actual, 1008b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 tag) { 1009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct ErrorRecord er; 1010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.actual = actual; 1011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.expected = tag; 1013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.vaddr = mem64; 1014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Generate vaddr from tag. 1016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.tagvaddr = reinterpret_cast<uint64*>(actual); 1017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessTagError(&er, 0, "Hardware Error"); 1019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// C implementation of Adler memory copy, with memory tagging. 1023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::AdlerAddrMemcpyC(uint64 *dstmem64, 1024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *srcmem64, 1025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int size_in_bytes, 1026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum *checksum, 1027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *pe) { 1028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Use this data wrapper to access memory with 64bit read/write. 1029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 1030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t dstdata; 1031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int count = size_in_bytes / sizeof(data); 1032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (count > ((1U) << 19)) { 1034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Size is too large, must be strictly less than 512 KB. 1035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 a1 = 1; 1039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 a2 = 1; 1040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 b1 = 0; 1041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 b2 = 0; 1042b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1043b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class Pattern *pattern = pe->pattern; 1044b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1045b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int i = 0; 1046b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (i < count) { 1047b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Process 64 bits at a time. 1048b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((i & 0x7) == 0) { 1049b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1050b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstdata.l64 = dstmem64[i]; 1051b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 src_tag = addr_to_tag(&srcmem64[i]); 1052b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 dst_tag = addr_to_tag(&dstmem64[i]); 1053b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Detect if tags have been corrupted. 1054b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (data.l64 != src_tag) 1055b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReportTagError(&srcmem64[i], data.l64, src_tag); 1056b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (dstdata.l64 != dst_tag) 1057b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReportTagError(&dstmem64[i], dstdata.l64, dst_tag); 1058b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1059b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pattern->pattern(i << 1); 1060b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pattern->pattern((i << 1) + 1); 1061b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.l; 1062b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1063b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.h; 1064b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1065b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1066b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = dst_tag; 1067b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstmem64[i] = data.l64; 1068b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1069b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1070b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1071b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.l; 1072b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1073b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.h; 1074b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1075b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstmem64[i] = data.l64; 1076b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1077b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson i++; 1078b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1079b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1080b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a2 = a2 + data.l32.l; 1081b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b2 = b2 + a2; 1082b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a2 = a2 + data.l32.h; 1083b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b2 = b2 + a2; 1084b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstmem64[i] = data.l64; 1085b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson i++; 1086b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1087b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson checksum->Set(a1, a2, b1, b2); 1088b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1089b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1090b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1091b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// x86_64 SSE2 assembly implementation of Adler memory copy, with address 1092b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// tagging added as a second step. This is useful for debugging failures 1093b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// that only occur when SSE / nontemporal writes are used. 1094b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::AdlerAddrMemcpyWarm(uint64 *dstmem64, 1095b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *srcmem64, 1096b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int size_in_bytes, 1097b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum *checksum, 1098b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *pe) { 1099b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do ASM copy, ignore checksum. 1100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum ignored_checksum; 1101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->AdlerMemcpyWarm(dstmem64, srcmem64, size_in_bytes, &ignored_checksum); 1102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Force cache flush. 1104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int length = size_in_bytes / sizeof(*dstmem64); 1105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length; i += sizeof(*dstmem64)) { 1106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FastFlush(dstmem64 + i); 1107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->FastFlush(srcmem64 + i); 1108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check results. 1110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerAddrCrcC(srcmem64, size_in_bytes, checksum, pe); 1111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Patch up address tags. 1112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson TagAddrC(dstmem64, size_in_bytes); 1113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Retag pages.. 1117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::TagAddrC(uint64 *memwords, 1118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int size_in_bytes) { 1119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Mask is the bitmask of indexes used by the pattern. 1120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // It is the pattern size -1. Size is always a power of 2. 1121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Select tag or data as appropriate. 1123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int length = size_in_bytes / wordsize_; 1124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length; i += 8) { 1125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 1126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = addr_to_tag(&memwords[i]); 1127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memwords[i] = data.l64; 1128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// C implementation of Adler memory crc. 1133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool WorkerThread::AdlerAddrCrcC(uint64 *srcmem64, 1134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int size_in_bytes, 1135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum *checksum, 1136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *pe) { 1137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Use this data wrapper to access memory with 64bit read/write. 1138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson datacast_t data; 1139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int count = size_in_bytes / sizeof(data); 1140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (count > ((1U) << 19)) { 1142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Size is too large, must be strictly less than 512 KB. 1143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 a1 = 1; 1147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 a2 = 1; 1148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 b1 = 0; 1149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 b2 = 0; 1150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson class Pattern *pattern = pe->pattern; 1152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int i = 0; 1154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (i < count) { 1155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Process 64 bits at a time. 1156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((i & 0x7) == 0) { 1157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 src_tag = addr_to_tag(&srcmem64[i]); 1159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check that tags match expected. 1160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (data.l64 != src_tag) 1161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReportTagError(&srcmem64[i], data.l64, src_tag); 1162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.l = pattern->pattern(i << 1); 1164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l32.h = pattern->pattern((i << 1) + 1); 1165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.l; 1166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.h; 1168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.l; 1172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a1 = a1 + data.l32.h; 1174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b1 = b1 + a1; 1175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson i++; 1177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data.l64 = srcmem64[i]; 1179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a2 = a2 + data.l32.l; 1180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b2 = b2 + a2; 1181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson a2 = a2 + data.l32.h; 1182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson b2 = b2 + a2; 1183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson i++; 1184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson checksum->Set(a1, a2, b1, b2); 1186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copy a block of memory quickly, while keeping a CRC of the data. 1190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Result check if the CRC mismatches. 1191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint WorkerThread::CrcCopyPage(struct page_entry *dstpe, 1192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *srcpe) { 1193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errors = 0; 1194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blocksize = 4096; 1195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blockwords = blocksize / wordsize_; 1196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks = sat_->page_length() / blocksize; 1197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Base addresses for memory copy 1199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmembase = static_cast<uint64*>(dstpe->addr); 1200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemembase = static_cast<uint64*>(srcpe->addr); 1201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Remember the expected CRC 1202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const AdlerChecksum *expectedcrc = srcpe->pattern->crc(); 1203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int currentblock = 0; currentblock < blocks; currentblock++) { 1205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmem = targetmembase + currentblock * blockwords; 1206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemem = sourcemembase + currentblock * blockwords; 1207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum crc; 1209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_) { 1210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerAddrMemcpyC(targetmem, sourcemem, blocksize, &crc, srcpe); 1211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerMemcpyC(targetmem, sourcemem, blocksize, &crc); 1213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Investigate miscompares. 1216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!crc.Equals(*expectedcrc)) { 1217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: CrcCopyPage Falling through to slow compare, " 1218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "CRC mismatch %s != %s\n", crc.ToHexString().c_str(), 1219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errorcount = CheckRegion(sourcemem, 1221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocksize, 1223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson currentblock * blocksize, 0); 1224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount == 0) { 1225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: CrcCopyPage CRC mismatch %s != %s, " 1226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "but no miscompares found. Retrying with fresh data.\n", 1227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 1228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!tag_mode_) { 1230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Copy the data originally read from this region back again. 1231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This data should have any corruption read originally while 1232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // calculating the CRC. 1233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memcpy(sourcemem, targetmem, blocksize); 1234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount = CheckRegion(sourcemem, 1235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocksize, 1237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson currentblock * blocksize, 0); 1238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount == 0) { 1239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int apic_id = apicid(); 1240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: CPU %d(0x%s) CrcCopyPage " 1241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "CRC mismatch %s != %s, " 1242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "but no miscompares found on second pass.\n", 1243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson apic_id, CurrentCpusFormat().c_str(), 1244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 1245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct ErrorRecord er; 1247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.actual = sourcemem[0]; 1248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.expected = 0x0; 1249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.vaddr = sourcemem; 1250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessError(&er, 0, "Hardware Error"); 1251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += errorcount; 1255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For odd length transfers, we should never hit this. 1259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int leftovers = sat_->page_length() % blocksize; 1260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (leftovers) { 1261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmem = targetmembase + blocks * blockwords; 1262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemem = sourcemembase + blocks * blockwords; 1263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += CheckRegion(sourcemem, 1265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson leftovers, 1267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks * blocksize, 0); 1268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int leftoverwords = leftovers / wordsize_; 1269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < leftoverwords; i++) { 1270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson targetmem[i] = sourcemem[i]; 1271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Update pattern reference to reflect new contents. 1275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstpe->pattern = srcpe->pattern; 1276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Clean clean clean the errors away. 1278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errors) { 1279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // TODO(nsanders): Maybe we should patch rather than fill? Filling may 1280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // cause bad data to be propogated across the page. 1281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson FillPage(dstpe); 1282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return errors; 1284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Invert a block of memory quickly, traversing downwards. 1289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint InvertThread::InvertPageDown(struct page_entry *srcpe) { 1290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blocksize = 4096; 1291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blockwords = blocksize / wordsize_; 1292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks = sat_->page_length() / blocksize; 1293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Base addresses for memory copy 1295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *sourcemembase = static_cast<unsigned int *>(srcpe->addr); 1296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int currentblock = blocks-1; currentblock >= 0; currentblock--) { 1298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *sourcemem = sourcemembase + currentblock * blockwords; 1299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = blockwords - 32; i >= 0; i -= 32) { 1300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int index = i + 31; index >= i; --index) { 1301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int actual = sourcemem[index]; 1302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sourcemem[index] = ~actual; 1303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson OsLayer::FastFlush(&sourcemem[i]); 1305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 1309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Invert a block of memory, traversing upwards. 1312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint InvertThread::InvertPageUp(struct page_entry *srcpe) { 1313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blocksize = 4096; 1314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blockwords = blocksize / wordsize_; 1315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks = sat_->page_length() / blocksize; 1316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Base addresses for memory copy 1318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *sourcemembase = static_cast<unsigned int *>(srcpe->addr); 1319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int currentblock = 0; currentblock < blocks; currentblock++) { 1321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *sourcemem = sourcemembase + currentblock * blockwords; 1322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < blockwords; i += 32) { 1323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int index = i; index <= i + 31; ++index) { 1324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int actual = sourcemem[index]; 1325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sourcemem[index] = ~actual; 1326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson OsLayer::FastFlush(&sourcemem[i]); 1328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return 0; 1331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copy a block of memory quickly, while keeping a CRC of the data. 1334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Result check if the CRC mismatches. Warm the CPU while running 1335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint WorkerThread::CrcWarmCopyPage(struct page_entry *dstpe, 1336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *srcpe) { 1337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errors = 0; 1338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blocksize = 4096; 1339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int blockwords = blocksize / wordsize_; 1340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks = sat_->page_length() / blocksize; 1341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Base addresses for memory copy 1343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmembase = static_cast<uint64*>(dstpe->addr); 1344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemembase = static_cast<uint64*>(srcpe->addr); 1345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Remember the expected CRC 1346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const AdlerChecksum *expectedcrc = srcpe->pattern->crc(); 1347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int currentblock = 0; currentblock < blocks; currentblock++) { 1349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmem = targetmembase + currentblock * blockwords; 1350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemem = sourcemembase + currentblock * blockwords; 1351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerChecksum crc; 1353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag_mode_) { 1354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson AdlerAddrMemcpyWarm(targetmem, sourcemem, blocksize, &crc, srcpe); 1355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->AdlerMemcpyWarm(targetmem, sourcemem, blocksize, &crc); 1357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Investigate miscompares. 1360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!crc.Equals(*expectedcrc)) { 1361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: CrcWarmCopyPage Falling through to slow compare, " 1362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "CRC mismatch %s != %s\n", crc.ToHexString().c_str(), 1363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errorcount = CheckRegion(sourcemem, 1365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocksize, 1367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson currentblock * blocksize, 0); 1368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount == 0) { 1369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: CrcWarmCopyPage CRC mismatch %s != %s, " 1370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "but no miscompares found. Retrying with fresh data.\n", 1371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 1372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!tag_mode_) { 1374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Copy the data originally read from this region back again. 1375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This data should have any corruption read originally while 1376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // calculating the CRC. 1377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memcpy(sourcemem, targetmem, blocksize); 1378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount = CheckRegion(sourcemem, 1379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocksize, 1381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson currentblock * blocksize, 0); 1382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errorcount == 0) { 1383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int apic_id = apicid(); 1384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: CPU %d(0x%s) CrciWarmCopyPage " 1385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "CRC mismatch %s != %s, " 1386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "but no miscompares found on second pass.\n", 1387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson apic_id, CurrentCpusFormat().c_str(), 1388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc.ToHexString().c_str(), 1389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson expectedcrc->ToHexString().c_str()); 1390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct ErrorRecord er; 1391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.actual = sourcemem[0]; 1392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.expected = 0x0; 1393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson er.vaddr = sourcemem; 1394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ProcessError(&er, 0, "Hardware Error"); 1395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += errorcount; 1399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For odd length transfers, we should never hit this. 1403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int leftovers = sat_->page_length() % blocksize; 1404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (leftovers) { 1405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *targetmem = targetmembase + blocks * blockwords; 1406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 *sourcemem = sourcemembase + blocks * blockwords; 1407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errors += CheckRegion(sourcemem, 1409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srcpe->pattern, 1410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson leftovers, 1411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks * blocksize, 0); 1412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int leftoverwords = leftovers / wordsize_; 1413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < leftoverwords; i++) { 1414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson targetmem[i] = sourcemem[i]; 1415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Update pattern reference to reflect new contents. 1419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dstpe->pattern = srcpe->pattern; 1420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Clean clean clean the errors away. 1422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errors) { 1423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // TODO(nsanders): Maybe we should patch rather than fill? Filling may 1424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // cause bad data to be propogated across the page. 1425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson FillPage(dstpe); 1426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return errors; 1428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Memory check work loop. Execute until done, then exhaust pages. 1433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool CheckThread::Work() { 1434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry pe; 1435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 1436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 1437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting Check thread %d\n", thread_num_); 1439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We want to check all the pages, and 1441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // stop when there aren't any left. 1442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (true) { 1443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetValid(&pe); 1444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (IsReadyToRunNoPause()) 1446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: check_thread failed to pop pages, " 1447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else 1449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = true; 1450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the result check. 1454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&pe); 1455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Push pages back on the valid queue if we are still going, 1457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // throw them out otherwise. 1458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (IsReadyToRunNoPause()) 1459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&pe); 1460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else 1461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutEmpty(&pe); 1462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: check_thread failed to push pages, " 1464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 1468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 1471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 1472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: Check thread. Status %d, %d pages checked\n", 1473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 1474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 1475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Memory copy work loop. Execute until marked done. 1479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool CopyThread::Work() { 1480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry src; 1481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry dst; 1482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 1483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 1484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting copy thread %d: cpu %s, mem %x\n", 1486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, cpuset_format(&cpu_mask_).c_str(), tag_); 1487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 1489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pop the needed pages. 1490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetValid(&src, tag_); 1491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetEmpty(&dst, tag_); 1492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: copy_thread failed to pop pages, " 1494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Force errors for unittests. 1499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->error_injection()) { 1500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (loops == 8) { 1501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *addr = reinterpret_cast<char*>(src.addr); 1502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int offset = random() % sat_->page_length(); 1503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr[offset] = 0xba; 1504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We can use memcpy, or CRC check while we copy. 1508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->warm()) { 1509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcWarmCopyPage(&dst, &src); 1510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (sat_->strict()) { 1511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCopyPage(&dst, &src); 1512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memcpy(dst.addr, src.addr, sat_->page_length()); 1514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst.pattern = src.pattern; 1515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&dst); 1518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutEmpty(&src); 1519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Copy worker-threads yield themselves at the end of each copy loop, 1521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // to avoid threads from preempting each other in the middle of the inner 1522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // copy-loop. Cooperations between Copy worker-threads results in less 1523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // unnecessary cache thrashing (which happens when context-switching in the 1524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // middle of the inner copy-loop). 1525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 1526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: copy_thread failed to push pages, " 1529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 1533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 1536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 1537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: Copy thread. Status %d, %d pages copied\n", 1538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 1539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 1540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Memory invert work loop. Execute until marked done. 1543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool InvertThread::Work() { 1544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry src; 1545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 1546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 1547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting invert thread %d\n", thread_num_); 1549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 1551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Pop the needed pages. 1552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetValid(&src); 1553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: invert_thread failed to pop pages, " 1555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->strict()) 1560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&src); 1561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For the same reason CopyThread yields itself (see YieldSelf comment 1563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // in CopyThread::Work(), InvertThread yields itself after each invert 1564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // operation to improve cooperation between different worker threads 1565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // stressing the memory/cache. 1566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InvertPageUp(&src); 1567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 1568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InvertPageDown(&src); 1569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 1570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InvertPageDown(&src); 1571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 1572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson InvertPageUp(&src); 1573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 1574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->strict()) 1576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&src); 1577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&src); 1579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 1580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: invert_thread failed to push pages, " 1581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 1585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops * 2; 1588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 1589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: Copy thread. Status %d, %d pages copied\n", 1590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 1591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 1592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set file name to use for File IO. 1596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid FileThread::SetFile(const char *filename_init) { 1597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_ = filename_init; 1598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson devicename_ = os_->FindFileDevice(filename_); 1599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Open the file for access. 1602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::OpenFile(int *pfile) { 1603613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson bool no_O_DIRECT = false; 1604613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson int flags = O_RDWR | O_CREAT | O_SYNC; 1605613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson int fd = open(filename_.c_str(), flags | O_DIRECT, 0644); 1606613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) { 1607613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson no_O_DIRECT = true; 1608613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson fd = open(filename_.c_str(), flags, 0644); // Try without O_DIRECT 1609613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson } 1610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (fd < 0) { 1611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Failed to create file %s!!\n", 1612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_.c_str()); 1613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 1614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1616613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson if (no_O_DIRECT) 1617613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson os_->ActivateFlushPageCache(); // Not using O_DIRECT fixed EINVAL 1618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *pfile = fd; 1619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Close the file. 1623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::CloseFile(int fd) { 1624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson close(fd); 1625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Check sector tagging. 1629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::SectorTagPage(struct page_entry *src, int block) { 1630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 1631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct FileThread::SectorTag *tag = 1632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (struct FileThread::SectorTag *)(src->addr); 1633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Tag each sector. 1635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned char magic = ((0xba + thread_num_) & 0xff); 1636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int sec = 0; sec < page_length / 512; sec++) { 1637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[sec].magic = magic; 1638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[sec].block = block & 0xff; 1639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[sec].sector = sec & 0xff; 1640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[sec].pass = pass_ & 0xff; 1641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::WritePageToFile(int fd, struct page_entry *src) { 1646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 1647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Fill the file with our data. 1648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 size = write(fd, src->addr, page_length); 1649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (size != page_length) { 1651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(devicename_.c_str(), "write-error", 1); 1652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_++; 1653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Block Error: file_thread failed to write, " 1654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Write the data to the file. 1661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::WritePages(int fd) { 1662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int strict = sat_->strict(); 1663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Start fresh at beginning of file for each batch of pages. 1665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson lseek64(fd, 0, SEEK_SET); 1666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < sat_->disk_pages(); i++) { 1667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry src; 1668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!GetValidPage(&src)) 1669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Save expected pattern. 1671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[i].pattern = src.pattern; 1672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[i].src = src.addr; 1673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check data correctness. 1675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (strict) 1676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&src); 1677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson SectorTagPage(&src, i); 1679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = WritePageToFile(fd, &src); 1681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!PutEmptyPage(&src)) 1683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) 1686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1688613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson return os_->FlushPageCache(); // If O_DIRECT worked, this will be a NOP. 1689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copy data from file into memory block. 1692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::ReadPageFromFile(int fd, struct page_entry *dst) { 1693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 1694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the actual read. 1696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 size = read(fd, dst->addr, page_length); 1697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (size != page_length) { 1698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(devicename_.c_str(), "read-error", 1); 1699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Block Error: file_thread failed to read, " 1700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 1701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_++; 1702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Check sector tagging. 1708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::SectorValidatePage(const struct PageRec &page, 1709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry *dst, int block) { 1710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error injection. 1711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson static int calls = 0; 1712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson calls++; 1713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do sector tag compare. 1715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int firstsector = -1; 1716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int lastsector = -1; 1717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool badsector = false; 1718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 1719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Cast data block into an array of tagged sectors. 1721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct FileThread::SectorTag *tag = 1722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (struct FileThread::SectorTag *)(dst->addr); 1723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(sizeof(*tag) == 512); 1725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error injection. 1727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->error_injection()) { 1728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (calls == 2) { 1729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int badsec = 8; badsec < 17; badsec++) 1730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[badsec].pass = 27; 1731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (calls == 18) { 1733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (static_cast<int32*>(dst->addr))[27] = 0xbadda7a; 1734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check each sector for the correct tag we added earlier, 1738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // then revert the tag to the to normal data pattern. 1739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned char magic = ((0xba + thread_num_) & 0xff); 1740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int sec = 0; sec < page_length / 512; sec++) { 1741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check magic tag. 1742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((tag[sec].magic != magic) || 1743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (tag[sec].block != (block & 0xff)) || 1744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (tag[sec].sector != (sec & 0xff)) || 1745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (tag[sec].pass != (pass_ & 0xff))) { 1746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Offset calculation for tag location. 1747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int offset = sec * sizeof(SectorTag); 1748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (tag[sec].block != (block & 0xff)) 1749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset += 1 * sizeof(uint8); 1750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else if (tag[sec].sector != (sec & 0xff)) 1751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset += 2 * sizeof(uint8); 1752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson else if (tag[sec].pass != (pass_ & 0xff)) 1753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset += 3 * sizeof(uint8); 1754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Run sector tag error through diagnoser for logging and reporting. 1756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += 1; 1757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->error_diagnoser_->AddHDDSectorTagError(devicename_, tag[sec].block, 1758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset, 1759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tag[sec].sector, 1760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page.src, page.dst); 1761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Sector Error: Sector tag @ 0x%x, pass %d/%d. " 1763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "sec %x/%x, block %d/%d, magic %x/%x, File: %s \n", 1764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block * page_length + 512 * sec, 1765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (pass_ & 0xff), (unsigned int)tag[sec].pass, 1766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sec, (unsigned int)tag[sec].sector, 1767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block, (unsigned int)tag[sec].block, 1768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson magic, (unsigned int)tag[sec].magic, 1769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_.c_str()); 1770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Keep track of first and last bad sector. 1772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (firstsector == -1) 1773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson firstsector = (block * page_length / 512) + sec; 1774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson lastsector = (block * page_length / 512) + sec; 1775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson badsector = true; 1776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Patch tag back to proper pattern. 1778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *addr = (unsigned int *)(&tag[sec]); 1779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *addr = dst->pattern->pattern(512 * sec / sizeof(*addr)); 1780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If we found sector errors: 1783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (badsector == true) { 1784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: file sector miscompare at offset %x-%x. File: %s\n", 1785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson firstsector * 512, 1786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ((lastsector + 1) * 512) - 1, 1787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_.c_str()); 1788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Either exit immediately, or patch the data up and continue. 1790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->stop_on_error()) { 1791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson exit(1); 1792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Patch up bad pages. 1794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int block = (firstsector * 512) / page_length; 1795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block <= (lastsector * 512) / page_length; 1796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block++) { 1797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *memblock = static_cast<unsigned int *>(dst->addr); 1798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int length = page_length / wordsize_; 1799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < length; i++) { 1800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memblock[i] = dst->pattern->pattern(i); 1801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get memory for an incoming data transfer.. 1809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::PagePrepare() { 1810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We can only do direct IO to SAT pages if it is normal mem. 1811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_io_ = os_->normal_mem(); 1812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Init a local buffer if we need it. 1814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!page_io_) { 18158f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_POSIX_MEMALIGN 1816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int result = posix_memalign(&local_page_, 512, sat_->page_length()); 18178f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 18188f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson local_page_ = memalign(512, sat_->page_length()); 18198f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson int result = (local_page_ == 0); 18208f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 1821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (result) { 1822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: disk thread posix_memalign " 1823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "returned %d (fail)\n", 1824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result); 1825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 1826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Remove memory allocated for data transfer. 1834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::PageTeardown() { 1835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Free a local buffer if we need to. 1836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!page_io_) { 1837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson free(local_page_); 1838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get memory for an incoming data transfer.. 1845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::GetEmptyPage(struct page_entry *dst) { 1846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_io_) { 1847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->GetEmpty(dst)) 1848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst->addr = local_page_; 1851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst->offset = 0; 1852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst->pattern = 0; 1853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get memory for an outgoing data transfer.. 1858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::GetValidPage(struct page_entry *src) { 1859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry tmp; 1860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->GetValid(&tmp)) 1861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_io_) { 1863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *src = tmp; 1864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 1866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson src->addr = local_page_; 1867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson src->offset = 0; 1868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCopyPage(src, &tmp); 1869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->PutValid(&tmp)) 1870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Throw out a used empty page. 1877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::PutEmptyPage(struct page_entry *src) { 1878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_io_) { 1879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->PutEmpty(src)) 1880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Throw out a used, filled page. 1886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::PutValidPage(struct page_entry *src) { 1887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (page_io_) { 1888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->PutValid(src)) 1889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1893b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copy data from file into memory blocks. 1895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::ReadPages(int fd) { 1896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 1897b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int strict = sat_->strict(); 1898b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 1899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Read our data back out of the file, into it's new location. 1901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson lseek64(fd, 0, SEEK_SET); 1902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < sat_->disk_pages(); i++) { 1903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry dst; 1904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!GetEmptyPage(&dst)) 1905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Retrieve expected pattern. 1907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst.pattern = page_recs_[i].pattern; 1908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Update page recordpage record. 1909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[i].dst = dst.addr; 1910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Read from the file into destination page. 1912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!ReadPageFromFile(fd, &dst)) { 1913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson PutEmptyPage(&dst); 1914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson SectorValidatePage(page_recs_[i], &dst, i); 1918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Ensure that the transfer ended up with correct data. 1920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (strict) { 1921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Record page index currently CRC checked. 1922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc_page_ = i; 1923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int errors = CrcCheckPage(&dst); 1924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (errors) { 1925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: file miscompare at block %d, " 1926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "offset %x-%x. File: %s\n", 1927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson i, i * page_length, ((i + 1) * page_length) - 1, 1928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_.c_str()); 1929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = false; 1930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson crc_page_ = -1; 1932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += errors; 1933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1934b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!PutValidPage(&dst)) 1935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 1938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// File IO work loop. Execute until marked done. 1941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool FileThread::Work() { 1942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 1943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 1944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting file thread %d, file %s, device %s\n", 1946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, 1947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson filename_.c_str(), 1948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson devicename_.c_str()); 1949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!PagePrepare()) { 1951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 1952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Open the data IO file. 1956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int fd = 0; 1957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!OpenFile(&fd)) { 1958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 1959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 1960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pass_ = 0; 1963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Load patterns into page records. 1965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_ = new struct PageRec[sat_->disk_pages()]; 1966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < sat_->disk_pages(); i++) { 1967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_recs_[i].pattern = new struct Pattern(); 1968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Loop until done. 1971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 1972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the file write. 1973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!(result = result && WritePages(fd))) 1974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the file read. 1977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!(result = result && ReadPages(fd))) 1978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 1979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1980b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 1981b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pass_ = loops; 1982b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 1983b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1984b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops * sat_->disk_pages(); 1985b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1986b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Clean up. 1987b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseFile(fd); 1988b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson PageTeardown(); 1989b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1990b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: file thread status %d, %d pages copied\n", 1991b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 1992b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Failure to read from device indicates hardware, 1993b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // rather than procedural SW error. 1994b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 1995b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 1996b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 1997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 1998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::IsNetworkStopSet() { 1999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return !IsReadyToRunNoPause(); 2000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkSlaveThread::IsNetworkStopSet() { 2003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This thread has no completion status. 2004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // It finishes whever there is no more data to be 2005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // passed back. 2006b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2007b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2008b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set ip name to use for Network IO. 2010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid NetworkThread::SetIP(const char *ipaddr_init) { 2011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson strncpy(ipaddr_, ipaddr_init, 256); 2012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Create a socket. 2015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return 0 on error. 2016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::CreateSocket(int *psocket) { 2017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int sock = socket(AF_INET, SOCK_STREAM, 0); 2018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sock == -1) { 2019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Cannot open socket\n"); 2020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 2021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *psocket = sock; 2025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Close the socket. 2029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::CloseSocket(int sock) { 2030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson close(sock); 2031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initiate the tcp connection. 2035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::Connect(int sock) { 2036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct sockaddr_in dest_addr; 2037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dest_addr.sin_family = AF_INET; 2038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dest_addr.sin_port = htons(kNetworkPort); 2039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(&(dest_addr.sin_zero), '\0', sizeof(dest_addr.sin_zero)); 2040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Translate dot notation to u32. 2042b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (inet_aton(ipaddr_, &dest_addr.sin_addr) == 0) { 2043b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Cannot resolve %s\n", ipaddr_); 2044b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 2045b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2046b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2047b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2048b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2049b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (-1 == connect(sock, reinterpret_cast<struct sockaddr *>(&dest_addr), 2050b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sizeof(struct sockaddr))) { 2051b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Cannot connect %s\n", ipaddr_); 2052b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 2053b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2054b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2055b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2056b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2057b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2058b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2059b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initiate the tcp connection. 2060b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::Listen() { 2061b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct sockaddr_in sa; 2062b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2063b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(&(sa.sin_zero), '\0', sizeof(sa.sin_zero)); 2064b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2065b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sa.sin_family = AF_INET; 2066b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sa.sin_addr.s_addr = INADDR_ANY; 2067b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sa.sin_port = htons(kNetworkPort); 2068b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2069b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (-1 == bind(sock_, (struct sockaddr*)&sa, sizeof(struct sockaddr))) { 2070b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256]; 2071b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(errno, buf, sizeof(buf)); 2072b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Cannot bind socket: %s\n", buf); 2073b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 2074b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2075b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2076b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2077b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson listen(sock_, 3); 2078b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2079b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2080b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2081b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Wait for a connection from a network traffic generation thread. 2082b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::Wait() { 2083b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson fd_set rfds; 2084b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timeval tv; 2085b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int retval; 2086b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2087b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Watch sock_ to see when it has input. 2088b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson FD_ZERO(&rfds); 2089b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson FD_SET(sock_, &rfds); 2090b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait up to five seconds. 2091b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tv.tv_sec = 5; 2092b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tv.tv_usec = 0; 2093b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2094b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson retval = select(sock_ + 1, &rfds, NULL, NULL, &tv); 2095b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2096b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return (retval > 0); 2097b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2098b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2099b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Wait for a connection from a network traffic generation thread. 2100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::GetConnection(int *pnewsock) { 2101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct sockaddr_in sa; 2102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson socklen_t size = sizeof(struct sockaddr_in); 2103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int newsock = accept(sock_, reinterpret_cast<struct sockaddr *>(&sa), &size); 2105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (newsock < 0) { 2106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Did not receive connection\n"); 2107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = 0; 2108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *pnewsock = newsock; 2112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Send a page, return false if a page was not sent. 2116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::SendPage(int sock, struct page_entry *src) { 2117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 2118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *address = static_cast<char*>(src->addr); 2119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Send our data over the network. 2121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int size = page_length; 2122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (size) { 2123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int transferred = send(sock, address + (page_length - size), size, 0); 2124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((transferred == 0) || (transferred == -1)) { 2125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!IsNetworkStopSet()) { 2126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256] = ""; 2127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(errno, buf, sizeof(buf)); 2128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Thread %d, " 2129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "Network write failed, bailing. (%s)\n", 2130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, buf); 2131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson size = size - transferred; 2136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Receive a page. Return false if a page was not received. 2141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::ReceivePage(int sock, struct page_entry *dst) { 2142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int page_length = sat_->page_length(); 2143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *address = static_cast<char*>(dst->addr); 2144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Maybe we will get our data back again, maybe not. 2146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int size = page_length; 2147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (size) { 2148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int transferred = recv(sock, address + (page_length - size), size, 0); 2149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((transferred == 0) || (transferred == -1)) { 2150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Typically network slave thread should exit as network master 2151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // thread stops sending data. 2152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (IsNetworkStopSet()) { 2153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int err = errno; 2154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (transferred == 0 && err == 0) { 2155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Two system setups will not sync exactly, 2156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // allow early exit, but log it. 2157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: Net thread did not receive any data, exiting.\n"); 2158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256] = ""; 2160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(err, buf, sizeof(buf)); 2161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Print why we failed. 2162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Thread %d, " 2163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "Network read failed, bailing (%s).\n", 2164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, buf); 2165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Print arguments and results. 2167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: recv(%d, address %x, size %x, 0) == %x, err %d\n", 2168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sock, address + (page_length - size), 2169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson size, transferred, err); 2170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((transferred == 0) && 2171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (page_length - size < 512) && 2172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (page_length - size > 0)) { 2173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Print null terminated data received, to see who's been 2174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // sending us supicious unwanted data. 2175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson address[page_length - size] = 0; 2176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Log: received %d bytes: '%s'\n", 2177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page_length - size, address); 2178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson size = size - transferred; 2184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Network IO work loop. Execute until marked done. 2189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return true if the thread ran as expected. 2190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkThread::Work() { 2191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting network thread %d, ip %s\n", 2192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, 2193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ipaddr_); 2194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Make a socket. 2196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int sock = 0; 2197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!CreateSocket(&sock)) 2198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Network IO loop requires network slave thread to have already initialized. 2201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // We will sleep here for awhile to ensure that the slave thread will be 2202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // listening by the time we connect. 2203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Sleep for 15 seconds. 2204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_sleep(15); 2205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting execution of network thread %d, ip %s\n", 2206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, 2207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ipaddr_); 2208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Connect to a slave thread. 2211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!Connect(sock)) 2212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Loop until done. 2215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 2216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int strict = sat_->strict(); 2217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 2218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 2219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry src; 2220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry dst; 2221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetValid(&src); 2222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetEmpty(&dst); 2223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 2224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: net_thread failed to pop pages, " 2225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 2226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Check data correctness. 2230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (strict) 2231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&src); 2232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the network write. 2234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!(result = result && SendPage(sock, &src))) 2235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Update pattern reference to reflect new contents. 2238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson dst.pattern = src.pattern; 2239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the network read. 2241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!(result = result && ReceivePage(sock, &dst))) 2242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Ensure that the transfer ended up with correct data. 2245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (strict) 2246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&dst); 2247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Return all of our pages to the queue. 2249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&dst); 2250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutEmpty(&src); 2251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 2252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: net_thread failed to push pages, " 2253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "bailing\n"); 2254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 2257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 2260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 2261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Clean up. 2263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseSocket(sock); 2264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: network thread status %d, " 2266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%d pages copied\n", 2267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 2268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 2269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Spawn slave threads for incoming connections. 2272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::SpawnSlave(int newsock, int threadid) { 2273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Listen thread spawning slave\n"); 2274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Spawn slave thread, to reflect network traffic back to sender. 2276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ChildWorker *child_worker = new ChildWorker; 2277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_worker->thread.SetSock(newsock); 2278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_worker->thread.InitThread(threadid, sat_, os_, patternlist_, 2279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson &child_worker->status); 2280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_worker->status.Initialize(); 2281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_worker->thread.SpawnThread(); 2282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_workers_.push_back(child_worker); 2283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Reap slave threads. 2288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::ReapSlaves() { 2289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 2290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Gather status and reap threads. 2291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Joining all outstanding threads\n"); 2292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (size_t i = 0; i < child_workers_.size(); i++) { 2294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson NetworkSlaveThread& child_thread = child_workers_[i]->thread; 2295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Joining slave thread %d\n", i); 2296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_thread.JoinThread(); 2297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (child_thread.GetStatus() != 1) { 2298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Slave Thread %d failed with status %d\n", i, 2299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_thread.GetStatus()); 2300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = false; 2301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += child_thread.GetErrorCount(); 2303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Slave Thread %d found %lld miscompares\n", i, 2304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_thread.GetErrorCount()); 2305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ += child_thread.GetPageCount(); 2306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 2309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Network listener IO work loop. Execute until marked done. 2312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on fatal software error. 2313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkListenThread::Work() { 2314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting network listen thread %d\n", 2315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Make a socket. 2318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sock_ = 0; 2319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!CreateSocket(&sock_)) { 2320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Listen thread created sock\n"); 2324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Allows incoming connections to be queued up by socket library. 2326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int newsock = 0; 2327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson Listen(); 2328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Listen thread waiting for incoming connections\n"); 2329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Wait on incoming connections, and spawn worker threads for them. 2331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int threadcount = 0; 2332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 2333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Poll for connections that we can accept(). 2334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (Wait()) { 2335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Accept those connections. 2336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Listen thread found incoming connection\n"); 2337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (GetConnection(&newsock)) { 2338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson SpawnSlave(newsock, threadcount); 2339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson threadcount++; 2340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Gather status and join spawned threads. 2345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ReapSlaves(); 2346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Delete the child workers. 2348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (ChildVector::iterator it = child_workers_.begin(); 2349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson it != child_workers_.end(); ++it) { 2350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (*it)->status.Destroy(); 2351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete *it; 2352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson child_workers_.clear(); 2354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseSocket(sock_); 2356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 2358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, 2359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "Log: Completed %d: network listen thread status %d, " 2360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%d pages copied\n", 2361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 2362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set network reflector socket struct. 2366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid NetworkSlaveThread::SetSock(int sock) { 2367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sock_ = sock; 2368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Network reflector IO work loop. Execute until marked done. 2371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on fatal software error. 2372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool NetworkSlaveThread::Work() { 2373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting network slave thread %d\n", 2374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Verify that we have a socket. 2377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int sock = sock_; 2378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sock) { 2379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Loop until done. 2384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 2385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Init a local buffer for storing data. 2386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson void *local_page = NULL; 23878f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_POSIX_MEMALIGN 2388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int result = posix_memalign(&local_page, 512, sat_->page_length()); 23898f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 23908f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson local_page = memalign(512, sat_->page_length()); 23918f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson int result = (local_page == 0); 23928f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 2393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (result) { 2394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: net slave posix_memalign " 2395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "returned %d (fail)\n", 2396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result); 2397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 2398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry page; 2402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson page.addr = local_page; 2403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This thread will continue to run as long as the thread on the other end of 2405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // the socket is still sending and receiving data. 2406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (1) { 2407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the network read. 2408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!ReceivePage(sock, &page)) 2409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Do the network write. 2412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!SendPage(sock, &page)) 2413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 2416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 2419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // No results provided from this type of thread. 2420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 2421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Clean up. 2423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseSocket(sock); 2424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, 2426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "Log: Completed %d: network slave thread status %d, " 2427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%d pages copied\n", 2428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, status_, pages_copied_); 2429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Thread work loop. Execute until marked finished. 2433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool ErrorPollThread::Work() { 2434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting system error poll thread %d\n", thread_num_); 2435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This calls a generic error polling function in the Os abstraction layer. 2437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson do { 2438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += os_->ErrorPoll(); 2439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorWait(); 2440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } while (IsReadyToRun()); 2441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Finished system error poll thread %d: %d errors\n", 2443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, errorcount_); 2444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 2445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to heat up CPU. 2449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This thread does not evaluate pass/fail or software error. 2450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool CpuStressThread::Work() { 2451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting CPU stress thread %d\n", thread_num_); 2452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson do { 2454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Run ludloff's platform/CPU-specific assembly workload. 2455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->CpuStressWorkload(); 2456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 2457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } while (IsReadyToRun()); 2458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Finished CPU stress thread %d:\n", 2460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 2462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2465b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonCpuCacheCoherencyThread::CpuCacheCoherencyThread(cc_cacheline_data *data, 2466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int cacheline_count, 2467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int thread_num, 2468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int inc_count) { 2469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_cacheline_data_ = data; 2470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_cacheline_count_ = cacheline_count; 2471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_thread_num_ = thread_num; 2472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_inc_count_ = inc_count; 2473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worked thread to test the cache coherency of the CPUs 2476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on fatal sw error. 2477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool CpuCacheCoherencyThread::Work() { 2478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting the Cache Coherency thread %d\n", 2479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_thread_num_); 2480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 time_start, time_end; 2481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timeval tv; 2482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int seed = static_cast<unsigned int>(gettid()); 2484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson gettimeofday(&tv, NULL); // Get the timestamp before increments. 2485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson time_start = tv.tv_sec * 1000000ULL + tv.tv_usec; 2486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 total_inc = 0; // Total increments done by the thread. 2488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 2489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < cc_inc_count_; i++) { 2490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Choose a datastructure in random and increment the appropriate 2491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // member in that according to the offset (which is the same as the 2492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // thread number. 24938f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_RAND_R 2494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int r = rand_r(&seed); 24958f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 24968f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson int r = rand(); 24978f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 2498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson r = cc_cacheline_count_ * (r / (RAND_MAX + 1.0)); 2499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Increment the member of the randomely selected structure. 2500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (cc_cacheline_data_[r].num[cc_thread_num_])++; 2501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson total_inc += cc_inc_count_; 2504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Calculate if the local counter matches with the global value 2506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // in all the cache line structures for this particular thread. 2507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int cc_global_num = 0; 2508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int cline_num = 0; cline_num < cc_cacheline_count_; cline_num++) { 2509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_global_num += cc_cacheline_data_[cline_num].num[cc_thread_num_]; 2510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Reset the cachline member's value for the next run. 2511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_cacheline_data_[cline_num].num[cc_thread_num_] = 0; 2512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (sat_->error_injection()) 2514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_global_num = -1; 2515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (cc_global_num != cc_inc_count_) { 2517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_++; 2518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: global(%d) and local(%d) do not match\n", 2519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_global_num, cc_inc_count_); 2520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson gettimeofday(&tv, NULL); // Get the timestamp at the end. 2523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson time_end = tv.tv_sec * 1000000ULL + tv.tv_usec; 2524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 us_elapsed = time_end - time_start; 2526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // inc_rate is the no. of increments per second. 2527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson double inc_rate = total_inc * 1e6 / us_elapsed; 2528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(4, "Stats: CC Thread(%d): Time=%llu us," 2530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson " Increments=%llu, Increments/sec = %.6lf\n", 2531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_thread_num_, us_elapsed, total_inc, inc_rate); 2532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Finished CPU Cache Coherency thread %d:\n", 2533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cc_thread_num_); 2534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; 2535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2538b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonDiskThread::DiskThread(DiskBlockTable *block_table) { 2539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_block_size_ = kSectorSize; // default 1 sector (512 bytes) 2540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_block_size_ = kSectorSize; // this assumes read and write block size 2541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // are the same 2542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson segment_size_ = -1; // use the entire disk as one segment 2543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cache_size_ = 16 * 1024 * 1024; // assume 16MiB cache by default 2544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Use a queue such that 3/2 times as much data as the cache can hold 2545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // is written before it is read so that there is little chance the read 2546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // data is in the cache. 2547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson queue_size_ = ((cache_size_ / write_block_size_) * 3) / 2; 2548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_per_segment_ = 32; 2549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_threshold_ = 100000; // 100ms is a reasonable limit for 2551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_threshold_ = 100000; // reading/writing a sector 2552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_timeout_ = 5000000; // 5 seconds should be long enough for a 2554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_timeout_ = 5000000; // timout for reading/writing 2555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_ = 0; 2557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson non_destructive_ = 0; 2558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 25598f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H 2560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson aio_ctx_ = 0; 25618f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 2562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_ = block_table; 2563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson update_block_table_ = 1; 2564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_buffer_ = NULL; 2566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_written_ = 0; 2568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_read_ = 0; 2569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2571b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonDiskThread::~DiskThread() { 2572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (block_buffer_) 2573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson free(block_buffer_); 2574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set filename for device file (in /dev). 2577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid DiskThread::SetDevice(const char *device_name) { 2578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_ = device_name; 2579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set various parameters that control the behaviour of the test. 2582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// -1 is used as a sentinel value on each parameter (except non_destructive) 2583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// to indicate that the parameter not be set. 2584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::SetParameters(int read_block_size, 2585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int write_block_size, 2586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 segment_size, 2587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 cache_size, 2588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int blocks_per_segment, 2589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 read_threshold, 2590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 write_threshold, 2591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int non_destructive) { 2592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (read_block_size != -1) { 2593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Blocks must be aligned to the disk's sector size. 2594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (read_block_size % kSectorSize != 0) { 2595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Block size must be a multiple of %d " 2596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "(thread %d).\n", kSectorSize, thread_num_); 2597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_block_size_ = read_block_size; 2601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_block_size != -1) { 2604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Write blocks must be aligned to the disk's sector size and to the 2605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // block size. 2606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_block_size % kSectorSize != 0) { 2607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Write block size must be a multiple " 2608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "of %d (thread %d).\n", kSectorSize, thread_num_); 2609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_block_size % read_block_size_ != 0) { 2612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Write block size must be a multiple " 2613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "of the read block size, which is %d (thread %d).\n", 2614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_block_size_, thread_num_); 2615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_block_size_ = write_block_size; 2619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Make sure write_block_size_ is still valid. 2622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (read_block_size_ > write_block_size_) { 2623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: Assuming write block size equal to read block size, " 2624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "which is %d (thread %d).\n", read_block_size_, 2625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_block_size_ = read_block_size_; 2627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_block_size_ % read_block_size_ != 0) { 2629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Write block size (defined as %d) must " 2630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "be a multiple of the read block size, which is %d " 2631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "(thread %d).\n", write_block_size_, read_block_size_, 2632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (cache_size != -1) { 2639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cache_size_ = cache_size; 2640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (blocks_per_segment != -1) { 2643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (blocks_per_segment <= 0) { 2644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Blocks per segment must be greater than " 2645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "zero.\n (thread %d)", thread_num_); 2646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_per_segment_ = blocks_per_segment; 2650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (read_threshold != -1) { 2653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (read_threshold <= 0) { 2654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Read threshold must be greater than " 2655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "zero (thread %d).\n", thread_num_); 2656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson read_threshold_ = read_threshold; 2660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_threshold != -1) { 2663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (write_threshold <= 0) { 2664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Write threshold must be greater than " 2665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "zero (thread %d).\n", thread_num_); 2666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_threshold_ = write_threshold; 2670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (segment_size != -1) { 2673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Segments must be aligned to the disk's sector size. 2674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (segment_size % kSectorSize != 0) { 2675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Segment size must be a multiple of %d" 2676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson " (thread %d).\n", kSectorSize, thread_num_); 2677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson segment_size_ = segment_size / kSectorSize; 2681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson non_destructive_ = non_destructive; 2684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Having a queue of 150% of blocks that will fit in the disk's cache 2686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // should be enough to force out the oldest block before it is read and hence, 2687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // making sure the data comes form the disk and not the cache. 2688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson queue_size_ = ((cache_size_ / write_block_size_) * 3) / 2; 2689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Updating DiskBlockTable parameters 2690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (update_block_table_) { 2691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_->SetParameters(kSectorSize, write_block_size_, 2692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_, segment_size_, 2693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_); 2694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Open a device, return false on failure. 2699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::OpenDevice(int *pfile) { 2700613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson bool no_O_DIRECT = false; 2701613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson int flags = O_RDWR | O_SYNC | O_LARGEFILE; 2702613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson int fd = open(device_name_.c_str(), flags | O_DIRECT, 0); 2703613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson if (O_DIRECT != 0 && fd < 0 && errno == EINVAL) { 2704613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson no_O_DIRECT = true; 2705613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson fd = open(device_name_.c_str(), flags, 0); // Try without O_DIRECT 2706613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson } 2707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (fd < 0) { 2708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Failed to open device %s (thread %d)!!\n", 2709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2712613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson if (no_O_DIRECT) 2713613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson os_->ActivateFlushPageCache(); 2714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson *pfile = fd; 2715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return GetDiskSize(fd); 2717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Retrieves the size (in bytes) of the disk/file. 2720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on failure. 2721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::GetDiskSize(int fd) { 2722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct stat device_stat; 2723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (fstat(fd, &device_stat) == -1) { 2724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to fstat disk %s (thread %d).\n", 2725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For a block device, an ioctl is needed to get the size since the size 2730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // of the device file (i.e. /dev/sdb) is 0. 2731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (S_ISBLK(device_stat.st_mode)) { 2732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 block_size = 0; 2733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (ioctl(fd, BLKGETSIZE64, &block_size) == -1) { 2735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to ioctl disk %s (thread %d).\n", 2736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Zero size indicates nonworking device.. 2741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (block_size == 0) { 2742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(device_name_.c_str(), "device-size-zero", 1); 2743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ++errorcount_; 2744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = true; // Avoid a procedural error. 2745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_ = block_size / kSectorSize; 2749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (S_ISREG(device_stat.st_mode)) { 2751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_ = device_stat.st_size / kSectorSize; 2752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: %s is not a regular file or block " 2755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "device (thread %d).\n", device_name_.c_str(), 2756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Device sectors: %lld on disk %s (thread %d).\n", 2761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_, device_name_.c_str(), thread_num_); 2762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (update_block_table_) { 2764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_->SetParameters(kSectorSize, write_block_size_, 2765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_sectors_, segment_size_, 2766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_); 2767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::CloseDevice(int fd) { 2773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson close(fd); 2774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return the time in microseconds. 2778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 DiskThread::GetTime() { 2779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timeval tv; 2780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson gettimeofday(&tv, NULL); 2781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return tv.tv_sec * 1000000 + tv.tv_usec; 2782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Do randomized reads and (possibly) writes on a device. 2785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on fatal SW error, true on SW success, 2786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// regardless of whether HW failed. 2787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::DoWork(int fd) { 2788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 block_num = 0; 2789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 num_segments; 2790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (segment_size_ == -1) { 2792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_segments = 1; 2793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_segments = device_sectors_ / segment_size_; 2795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (device_sectors_ % segment_size_ != 0) 2796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson num_segments++; 2797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Disk size should be at least 3x cache size. See comment later for 2800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // details. 2801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(device_sectors_ * kSectorSize > 3 * cache_size_); 2802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This disk test works by writing blocks with a certain pattern to 2804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // disk, then reading them back and verifying it against the pattern 2805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // at a later time. A failure happens when either the block cannot 2806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // be written/read or when the read block is different than what was 2807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // written. If a block takes too long to write/read, then a warning 2808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // is given instead of an error since taking too long is not 2809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // necessarily an error. 2810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 2811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // To prevent the read blocks from coming from the disk cache, 2812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // enough blocks are written before read such that a block would 2813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // be ejected from the disk cache by the time it is read. 2814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 2815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // TODO(amistry): Implement some sort of read/write throttling. The 2816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // flood of asynchronous I/O requests when a drive is 2817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // unplugged is causing the application and kernel to 2818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // become unresponsive. 2819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 2821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Write blocks to disk. 2822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(16, "Log: Write phase %sfor disk %s (thread %d).\n", 2823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson non_destructive_ ? "(disabled) " : "", 2824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRunNoPause() && 2826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson in_flight_sectors_.size() < 2827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson static_cast<size_t>(queue_size_ + 1)) { 2828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Confine testing to a particular segment of the disk. 2829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 segment = (block_num / blocks_per_segment_) % num_segments; 2830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!non_destructive_ && 2831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (block_num % blocks_per_segment_ == 0)) { 2832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(20, "Log: Starting to write segment %lld out of " 2833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%lld on disk %s (thread %d).\n", 2834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson segment, num_segments, device_name_.c_str(), 2835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_num++; 2838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson BlockData *block = block_table_->GetUnusedBlock(segment); 2840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If an unused sequence of sectors could not be found, skip to the 2842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // next block to process. Soon, a new segment will come and new 2843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // sectors will be able to be allocated. This effectively puts a 2844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // minumim on the disk size at 3x the stated cache size, or 48MiB 2845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // if a cache size is not given (since the cache is set as 16MiB 2846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // by default). Given that todays caches are at the low MiB range 2847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // and drive sizes at the mid GB, this shouldn't pose a problem. 2848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // The 3x minimum comes from the following: 2849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 1. In order to allocate 'y' blocks from a segment, the 2850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // segment must contain at least 2y blocks or else an 2851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // allocation may not succeed. 2852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 2. Assume the entire disk is one segment. 2853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 3. A full write phase consists of writing blocks corresponding to 2854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 3/2 cache size. 2855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 4. Therefore, the one segment must have 2 * 3/2 * cache 2856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // size worth of blocks = 3 * cache size worth of blocks 2857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // to complete. 2858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // In non-destructive mode, don't write anything to disk. 2859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!non_destructive_) { 2860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!WriteBlockToDisk(fd, block)) { 2861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_->RemoveBlock(block); 2862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_written_++; 2865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Block is either initialized by writing, or in nondestructive case, 2868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // initialized by being added into the datastructure for later reading. 2869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->SetBlockAsInitialized(); 2870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson in_flight_sectors_.push(block); 2872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2873613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson if (!os_->FlushPageCache()) // If O_DIRECT worked, this will be a NOP. 2874613ee1f783d25f83aeb9b5ad25c3ceb3da49b163Scott Anderson return false; 2875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Verify blocks on disk. 2877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(20, "Log: Read phase for disk %s (thread %d).\n", 2878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRunNoPause() && !in_flight_sectors_.empty()) { 2880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson BlockData *block = in_flight_sectors_.front(); 2881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson in_flight_sectors_.pop(); 2882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!ValidateBlockOnDisk(fd, block)) 2883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_->RemoveBlock(block); 2885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_read_++; 2886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = blocks_written_ + blocks_read_; 2890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 2891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 2892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2893b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Do an asynchronous disk I/O operation. 2894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false if the IO is not set up. 2895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::AsyncDiskIO(IoOp op, int fd, void *buf, int64 size, 2896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 offset, int64 timeout) { 28978f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H 2898b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Use the Linux native asynchronous I/O interface for reading/writing. 2899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // A read/write consists of three basic steps: 2900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 1. create an io context. 2901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 2. prepare and submit an io request to the context 2902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // 3. wait for an event on the context. 2903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct { 2905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const int opcode; 2906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *op_str; 2907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *error_str; 2908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } operations[2] = { 2909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson { IO_CMD_PREAD, "read", "disk-read-error" }, 2910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson { IO_CMD_PWRITE, "write", "disk-write-error" } 2911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson }; 2912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct iocb cb; 2914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(&cb, 0, sizeof(cb)); 2915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cb.aio_fildes = fd; 2917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cb.aio_lio_opcode = operations[op].opcode; 2918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cb.u.c.buf = buf; 2919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cb.u.c.nbytes = size; 2920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson cb.u.c.offset = offset; 2921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct iocb *cbs[] = { &cb }; 2923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (io_submit(aio_ctx_, 1, cbs) != 1) { 2924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int error = errno; 2925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256]; 2926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(error, buf, sizeof(buf)); 2927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to submit async %s " 2928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "on disk %s (thread %d). Error %d, %s\n", 2929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, device_name_.c_str(), 2930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, error, buf); 2931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2934b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct io_event event; 2935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(&event, 0, sizeof(event)); 2936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct timespec tv; 2937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tv.tv_sec = timeout / 1000000; 2938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson tv.tv_nsec = (timeout % 1000000) * 1000; 2939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (io_getevents(aio_ctx_, 1, 1, &event, &tv) != 1) { 2940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // A ctrl-c from the keyboard will cause io_getevents to fail with an 2941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // EINTR error code. This is not an error and so don't treat it as such, 2942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // but still log it. 2943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int error = errno; 2944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (error == EINTR) { 2945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: %s interrupted on disk %s (thread %d).\n", 2946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, device_name_.c_str(), 2947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 2948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(device_name_.c_str(), operations[op].error_str, 1); 2950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += 1; 2951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: Timeout doing async %s to sectors " 2952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "starting at %lld on disk %s (thread %d).\n", 2953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, offset / kSectorSize, 2954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Don't bother checking return codes since io_cancel seems to always fail. 2958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Since io_cancel is always failing, destroying and recreating an I/O 2959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // context is a workaround for canceling an in-progress I/O operation. 2960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // TODO(amistry): Find out why io_cancel isn't working and make it work. 2961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson io_cancel(aio_ctx_, &cb, &event); 2962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson io_destroy(aio_ctx_); 2963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson aio_ctx_ = 0; 2964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (io_setup(5, &aio_ctx_)) { 2965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int error = errno; 2966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char buf[256]; 2967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_strerror(error, buf, sizeof(buf)); 2968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to create aio context on disk %s" 2969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson " (thread %d) Error %d, %s\n", 2970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_, error, buf); 2971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 2974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // event.res contains the number of bytes written/read or 2977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // error if < 0, I think. 2978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (event.res != static_cast<uint64>(size)) { 2979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_++; 2980b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(device_name_.c_str(), operations[op].error_str, 1); 2981b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 2982b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (event.res < 0) { 2983b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson switch (event.res) { 2984b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson case -EIO: 2985b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: Low-level I/O error while doing %s to " 2986b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "sectors starting at %lld on disk %s (thread %d).\n", 2987b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, offset / kSectorSize, 2988b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2989b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 2990b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson default: 2991b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: Unknown error while doing %s to " 2992b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "sectors starting at %lld on disk %s (thread %d).\n", 2993b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, offset / kSectorSize, 2994b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 2995b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 2996b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 2997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: Unable to %s to sectors starting at " 2998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%lld on disk %s (thread %d).\n", 2999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson operations[op].op_str, offset / kSectorSize, 3000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 30068f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else // !HAVE_LIBAIO_H 30078f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson return false; 30088f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 3009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Write a block to disk. 3012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false if the block is not written. 3013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::WriteBlockToDisk(int fd, BlockData *block) { 3014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(block_buffer_, 0, block->GetSize()); 3015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Fill block buffer with a pattern 3017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry pe; 3018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!sat_->GetValid(&pe)) { 3019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Even though a valid page could not be obatined, it is not an error 3020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // since we can always fill in a pattern directly, albeit slower. 3021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int *memblock = static_cast<unsigned int *>(block_buffer_); 3022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->SetPattern(patternlist_->GetRandomPattern()); 3023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: Warning, using pattern fill fallback in " 3025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "DiskThread::WriteBlockToDisk on disk %s (thread %d).\n", 3026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < block->GetSize()/wordsize_; i++) { 3029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memblock[i] = block->GetPattern()->pattern(i); 3030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 3032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memcpy(block_buffer_, pe.addr, block->GetSize()); 3033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->SetPattern(pe.pattern); 3034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_->PutValid(&pe); 3035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Writing %lld sectors starting at %lld on disk %s" 3038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson " (thread %d).\n", 3039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->GetSize()/kSectorSize, block->GetAddress(), 3040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3042b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 start_time = GetTime(); 3043b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3044b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!AsyncDiskIO(ASYNC_IO_WRITE, fd, block_buffer_, block->GetSize(), 3045b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block->GetAddress() * kSectorSize, write_timeout_)) { 3046b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3047b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3048b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3049b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 end_time = GetTime(); 3050b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: Writing time: %lld us (thread %d).\n", 3051b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson end_time - start_time, thread_num_); 3052b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (end_time - start_time > write_threshold_) { 3053b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: Write took %lld us which is longer than threshold " 3054b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%lld us on disk %s (thread %d).\n", 3055b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson end_time - start_time, write_threshold_, device_name_.c_str(), 3056b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_); 3057b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3058b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3059b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 3060b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3061b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3062b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Verify a block on disk. 3063b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return true if the block was read, also increment errorcount 3064b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// if the block had data errors or performance problems. 3065b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::ValidateBlockOnDisk(int fd, BlockData *block) { 3066b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 blocks = block->GetSize() / read_block_size_; 3067b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 bytes_read = 0; 3068b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 current_blocks; 3069b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 current_bytes; 3070b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint64 address = block->GetAddress(); 3071b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3072b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(20, "Log: Reading sectors starting at %lld on disk %s " 3073b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "(thread %d).\n", 3074b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson address, device_name_.c_str(), thread_num_); 3075b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3076b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Read block from disk and time the read. If it takes longer than the 3077b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // threshold, complain. 3078b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (lseek64(fd, address * kSectorSize, SEEK_SET) == -1) { 3079b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to seek to sector %lld in " 3080b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "DiskThread::ValidateSectorsOnDisk on disk %s " 3081b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "(thread %d).\n", address, device_name_.c_str(), thread_num_); 3082b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3083b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3084b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 start_time = GetTime(); 3085b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3086b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Split a large write-sized block into small read-sized blocks and 3087b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // read them in groups of randomly-sized multiples of read block size. 3088b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // This assures all data written on disk by this particular block 3089b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // will be tested using a random reading pattern. 3090b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (blocks != 0) { 3091b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Test all read blocks in a written block. 3092b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson current_blocks = (random() % blocks) + 1; 3093b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson current_bytes = current_blocks * read_block_size_; 3094b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3095b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memset(block_buffer_, 0, current_bytes); 3096b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3097b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(20, "Log: Reading %lld sectors starting at sector %lld on " 3098b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "disk %s (thread %d)\n", 3099b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson current_bytes / kSectorSize, 3100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson (address * kSectorSize + bytes_read) / kSectorSize, 3101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!AsyncDiskIO(ASYNC_IO_READ, fd, block_buffer_, current_bytes, 3104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson address * kSectorSize + bytes_read, 3105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson write_timeout_)) { 3106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 end_time = GetTime(); 3110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(20, "Log: Reading time: %lld us (thread %d).\n", 3111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson end_time - start_time, thread_num_); 3112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (end_time - start_time > read_threshold_) { 3113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(5, "Log: Read took %lld us which is longer than threshold " 3114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%lld us on disk %s (thread %d).\n", 3115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson end_time - start_time, read_threshold_, 3116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // In non-destructive mode, don't compare the block to the pattern since 3120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // the block was never written to disk in the first place. 3121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!non_destructive_) { 3122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (CheckRegion(block_buffer_, block->GetPattern(), current_bytes, 3123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 0, bytes_read)) { 3124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->ErrorReport(device_name_.c_str(), "disk-pattern-error", 1); 3125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson errorcount_ += 1; 3126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Hardware Error: Pattern mismatch in block starting at " 3127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "sector %lld in DiskThread::ValidateSectorsOnDisk on " 3128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "disk %s (thread %d).\n", 3129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson address, device_name_.c_str(), thread_num_); 3130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bytes_read += current_blocks * read_block_size_; 3134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks -= current_blocks; 3135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 3138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Direct device access thread. 3141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on software error. 3142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool DiskThread::Work() { 3143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int fd; 3144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting disk thread %d, disk %s\n", 3146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, device_name_.c_str()); 3147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson srandom(time(NULL)); 3149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!OpenDevice(&fd)) { 3151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 3152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Allocate a block buffer aligned to 512 bytes since the kernel requires it 31568f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson // when using direct IO. 31578f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_POSIX_MEMALIGN 3158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int memalign_result = posix_memalign(&block_buffer_, kBufferAlignment, 3159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_->page_length()); 31608f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else 31618f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson block_buffer_ = memalign(kBufferAlignment, sat_->page_length()); 31628f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson int memalign_result = (block_buffer_ == 0); 31638f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 3164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (memalign_result) { 3165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseDevice(fd); 3166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to allocate memory for buffers " 3167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "for disk %s (thread %d) posix memalign returned %d.\n", 3168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_, memalign_result); 3169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 3170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 31738f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H 3174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (io_setup(5, &aio_ctx_)) { 3175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseDevice(fd); 3176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: Unable to create aio context for disk %s" 3177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson " (thread %d).\n", 3178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = false; 3180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 31828f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 3183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = DoWork(fd); 3185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 3187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 31888f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H 3189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson io_destroy(aio_ctx_); 31908f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif 3191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CloseDevice(fd); 3192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d (disk %s): disk thread status %d, " 3194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%d pages copied\n", 3195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson thread_num_, device_name_.c_str(), status_, pages_copied_); 3196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 3197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3199b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonRandomDiskThread::RandomDiskThread(DiskBlockTable *block_table) 3200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson : DiskThread(block_table) { 3201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson update_block_table_ = 0; 3202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3204b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonRandomDiskThread::~RandomDiskThread() { 3205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Workload for random disk thread. 3208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool RandomDiskThread::DoWork(int fd) { 3209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(11, "Log: Random phase for disk %s (thread %d).\n", 3210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 3212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson BlockData *block = block_table_->GetRandomBlock(); 3213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (block == NULL) { 3214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(12, "Log: No block available for device %s (thread %d).\n", 3215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson device_name_.c_str(), thread_num_); 3216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 3217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson ValidateBlockOnDisk(fd, block); 3218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson block_table_->ReleaseBlock(block); 3219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson blocks_read_++; 3220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = blocks_read_; 3223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 3224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3226b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonMemoryRegionThread::MemoryRegionThread() { 3227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error_injection_ = false; 3228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_ = NULL; 3229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3231b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonMemoryRegionThread::~MemoryRegionThread() { 3232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pages_ != NULL) 3233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete pages_; 3234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set a region of memory or MMIO to be tested. 3237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false if region could not be mapped. 3238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool MemoryRegionThread::SetRegion(void *region, int64 size) { 3239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int plength = sat_->page_length(); 3240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int npages = size / plength; 3241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (size % plength) { 3242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: region size is not a multiple of SAT " 3243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "page length\n"); 3244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return false; 3245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 3246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (pages_ != NULL) 3247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson delete pages_; 3248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_ = new PageEntryQueue(npages); 3249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *base_addr = reinterpret_cast<char*>(region); 3250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson region_ = base_addr; 3251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (int i = 0; i < npages; i++) { 3252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry pe; 3253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson init_pe(&pe); 3254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pe.addr = reinterpret_cast<void*>(base_addr + i * plength); 3255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pe.offset = i * plength; 3256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_->Push(&pe); 3258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return true; 3260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// More detailed error printout for hardware errors in memory or MMIO 3264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// regions. 3265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid MemoryRegionThread::ProcessError(struct ErrorRecord *error, 3266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int priority, 3267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const char *message) { 3268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson uint32 buffer_offset; 3269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (phase_ == kPhaseCopy) { 3270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // If the error occurred on the Copy Phase, it means that 3271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // the source data (i.e., the main memory) is wrong. so 3272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // just pass it to the original ProcessError to call a 3273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // bad-dimm error 3274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson WorkerThread::ProcessError(error, priority, message); 3275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else if (phase_ == kPhaseCheck) { 3276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // A error on the Check Phase means that the memory region tested 3277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // has an error. Gathering more information and then reporting 3278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // the error. 3279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Determine if this is a write or read error. 3280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson os_->Flush(error->vaddr); 3281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread = *(error->vaddr); 3282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *good = reinterpret_cast<char*>(&(error->expected)); 3283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson char *bad = reinterpret_cast<char*>(&(error->actual)); 3284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson sat_assert(error->expected != error->actual); 3285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson unsigned int offset = 0; 3286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson for (offset = 0; offset < (sizeof(error->expected) - 1); offset++) { 3287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (good[offset] != bad[offset]) 3288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 3289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vbyteaddr = reinterpret_cast<char*>(error->vaddr) + offset; 3292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buffer_offset = error->vbyteaddr - region_; 3294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Find physical address if possible. 3296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr = os_->VirtualToPhysical(error->vbyteaddr); 3297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(priority, 3298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "%s: miscompare on %s, CRC check at %p(0x%llx), " 3299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "offset %llx: read:0x%016llx, reread:0x%016llx " 3300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "expected:0x%016llx\n", 3301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson message, 3302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson identifier_.c_str(), 3303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->vaddr, 3304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->paddr, 3305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson buffer_offset, 3306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->actual, 3307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->reread, 3308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson error->expected); 3309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } else { 3310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: memory region thread raised an " 3311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "unexpected error."); 3312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Workload for testion memory or MMIO regions. 3316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return false on software error. 3317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool MemoryRegionThread::Work() { 3318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry source_pe; 3319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson struct page_entry memregion_pe; 3320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson bool result = true; 3321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 loops = 0; 3322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson const uint64 error_constant = 0x00ba00000000ba00LL; 3323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // For error injection. 3325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 *addr = 0x0; 3326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int offset = 0; 3327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson int64 data = 0; 3328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Starting Memory Region thread %d\n", thread_num_); 3330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson while (IsReadyToRun()) { 3332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Getting pages from SAT and queue. 3333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson phase_ = kPhaseNoPhase; 3334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->GetValid(&source_pe); 3335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 3336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: memory region thread failed to pop " 3337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "pages from SAT, bailing\n"); 3338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 3339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && pages_->PopRandom(&memregion_pe); 3342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 3343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: memory region thread failed to pop " 3344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "pages from queue, bailing\n"); 3345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 3346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error injection for CRC copy. 3349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((sat_->error_injection() || error_injection_) && loops == 1) { 3350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr = reinterpret_cast<int64*>(source_pe.addr); 3351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset = random() % (sat_->page_length() / wordsize_); 3352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data = addr[offset]; 3353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr[offset] = error_constant; 3354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Copying SAT page into memory region. 3357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson phase_ = kPhaseCopy; 3358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCopyPage(&memregion_pe, &source_pe); 3359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson memregion_pe.pattern = source_pe.pattern; 3360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Error injection for CRC Check. 3362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((sat_->error_injection() || error_injection_) && loops == 2) { 3363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr = reinterpret_cast<int64*>(memregion_pe.addr); 3364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson offset = random() % (sat_->page_length() / wordsize_); 3365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson data = addr[offset]; 3366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr[offset] = error_constant; 3367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Checking page content in memory region. 3370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson phase_ = kPhaseCheck; 3371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson CrcCheckPage(&memregion_pe); 3372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson phase_ = kPhaseNoPhase; 3374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson // Storing pages on their proper queues. 3375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && sat_->PutValid(&source_pe); 3376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 3377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: memory region thread failed to push " 3378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "pages into SAT, bailing\n"); 3379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 3380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson result = result && pages_->Push(&memregion_pe); 3382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if (!result) { 3383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(0, "Process Error: memory region thread failed to push " 3384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "pages into queue, bailing\n"); 3385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson break; 3386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson if ((sat_->error_injection() || error_injection_) && 3389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops >= 1 && loops <= 2) { 3390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson addr[offset] = data; 3391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson loops++; 3394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson YieldSelf(); 3395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson } 3396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson 3397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson pages_copied_ = loops; 3398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson status_ = result; 3399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson logprintf(9, "Log: Completed %d: Memory Region thread. Status %d, %d " 3400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson "pages checked\n", thread_num_, status_, pages_copied_); 3401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson return result; 3402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson} 3403