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