1b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Copyright 2006 Google Inc. All Rights Reserved.
2b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
3b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Licensed under the Apache License, Version 2.0 (the "License");
4b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// you may not use this file except in compliance with the License.
5b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// You may obtain a copy of the License at
6b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
7b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//      http://www.apache.org/licenses/LICENSE-2.0
8b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
9b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Unless required by applicable law or agreed to in writing, software
10b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// distributed under the License is distributed on an "AS IS" BASIS,
11b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// See the License for the specific language governing permissions and
13b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// limitations under the License.
14b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
15b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// sat.cc : a stress test for stressful testing
16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// stressapptest (or SAT, from Stressful Application Test) is a test
18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// designed to stress the system, as well as provide a comprehensive
19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// memory interface test.
20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// stressapptest can be run using memory only, or using many system components.
22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
23b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <errno.h>
24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <pthread.h>
25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <signal.h>
26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdarg.h>
27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdio.h>
28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <stdlib.h>
29b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string.h>
30b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <unistd.h>
31b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/stat.h>
33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/times.h>
34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// #define __USE_GNU
36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// #define __USE_LARGEFILE64
37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <fcntl.h>
38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <list>
40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string>
41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version,
43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct.
44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "disk_blocks.h"
45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "logger.h"
46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "os.h"
47b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sat.h"
48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sattypes.h"
49b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "worker.h"
50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// stressapptest versioning here.
52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#ifndef PACKAGE_VERSION
53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonstatic const char* kVersion = "1.0.0";
54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#else
55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonstatic const char* kVersion = PACKAGE_VERSION;
56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif
57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Global stressapptest reference, for use by signal handler.
59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This makes Sat objects not safe for multiple instances.
60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonnamespace {
61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Sat *g_sat = NULL;
62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Signal handler for catching break or kill.
64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This must be installed after g_sat is assigned and while there is a single
66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // thread.
67b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This must be uninstalled while there is only a single thread, and of course
69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // before g_sat is cleared or deleted.
70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SatHandleBreak(int signal) {
71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    g_sat->Break();
72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
73b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Opens the logfile for writing if necessary
76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::InitializeLogfile() {
77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Open logfile.
78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (use_logfile_) {
79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logfile_ = open(logfilename_,
808f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#if defined(O_DSYNC)
818f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson                    O_DSYNC |
828f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#elif defined(O_SYNC)
838f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson                    O_SYNC |
848f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#elif defined(O_FSYNC)
858f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson                    O_FSYNC |
868f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
878f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson                    O_WRONLY | O_CREAT,
88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (logfile_ < 0) {
90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("Fatal Error: cannot open file %s for logging\n",
91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson             logfilename_);
92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // We seek to the end once instead of opening in append mode because no
96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // other processes should be writing to it while this one exists.
97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (lseek(logfile_, 0, SEEK_END) == -1) {
98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("Fatal Error: cannot seek to end of logfile (%s)\n",
99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson             logfilename_);
100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Logger::GlobalLogger()->SetLogFd(logfile_);
104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Check that the environment is known and safe to run on.
109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return 1 if good, 0 if unsuppported.
110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::CheckEnvironment() {
111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check that this is not a debug build. Debug builds lack
112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // enough performance to stress the system.
113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if !defined NDEBUG
114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (run_on_anything_) {
115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Log: Running DEBUG version of SAT, "
116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with significantly reduced coverage.\n");
117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Running DEBUG version of SAT, "
119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with significantly reduced coverage.\n");
120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#elif !defined CHECKOPTS
125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  #error Build system regression - COPTS disregarded.
126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif
127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
128241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  // Check if the cpu frequency test is enabled and able to run.
129241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (cpu_freq_test_) {
130241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (!CpuFreqThread::CanRun()) {
131241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(0, "Process Error: This platform does not support this "
132241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                "test.\n");
133241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
134241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
135241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    } else if (cpu_freq_threshold_ <= 0) {
136241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(0, "Process Error: The cpu frequency test requires "
137241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                "--cpu_freq_threshold set to a value > 0\n");
138241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
139241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
140241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    } else if (cpu_freq_round_ < 0) {
141241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(0, "Process Error: The --cpu_freq_round option must be greater"
142241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                " than or equal to zero. A value of zero means no rounding.\n");
143241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
144241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
145241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
146241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  }
147241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use all CPUs if nothing is specified.
149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (memory_threads_ == -1) {
150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memory_threads_ = os_->num_cpus();
151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(7, "Log: Defaulting to %d copy threads\n", memory_threads_);
152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use all memory if no size is specified.
155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (size_mb_ == 0)
156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_mb_ = os_->FindFreeMemSize() / kMegabyte;
157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = static_cast<int64>(size_mb_) * kMegabyte;
158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Autodetect file locations.
160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (findfiles_ && (file_threads_ == 0)) {
161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Get a space separated sting of disk locations.
162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    list<string> locations = os_->FindFileDevices();
163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Extract each one.
165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    while (!locations.empty()) {
166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Copy and remove the disk name.
167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      string disk = locations.back();
168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      locations.pop_back();
169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: disk at %s\n", disk.c_str());
171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      file_threads_++;
172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      filename_.push_back(disk + "/sat_disk.a");
173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      file_threads_++;
174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      filename_.push_back(disk + "/sat_disk.b");
175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We'd better have some memory by this point.
179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (size_ < 1) {
180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: No memory found to test.\n");
181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (tag_mode_ && ((file_threads_ > 0) ||
186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    (disk_threads_ > 0) ||
187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    (net_threads_ > 0))) {
188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Memory tag mode incompatible "
189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with disk/network DMA.\n");
190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // If platform is 32 bit Xeon, floor memory size to multiple of 4.
195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (address_mode_ == 32) {
196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_mb_ = (size_mb_ / 4) * 4;
197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_ = size_mb_ * kMegabyte;
198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Log: Flooring memory allocation to multiple of 4: %lldMB\n",
199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              size_mb_);
200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check if this system is on the whitelist for supported systems.
203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_->IsSupported()) {
204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (run_on_anything_) {
205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(1, "Log: Unsupported system. Running with reduced coverage.\n");
206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // This is ok, continue on.
207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Unsupported system, "
209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                   "no error reporting available\n");
210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Allocates memory to run the test on
220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::AllocateMemory() {
221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate our test memory.
222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = os_->AllocateTestMem(size_, paddr_base_);
223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!result) {
224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to allocate memory\n");
225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Sets up access to data patterns
232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::InitializePatterns() {
233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize pattern data.
234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  patternlist_ = new PatternList();
235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!patternlist_) {
236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to allocate patterns\n");
237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!patternlist_->Initialize()) {
241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to initialize patternlist\n");
242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get any valid page, no tag specified.
249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetValid(struct page_entry *pe) {
250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return GetValid(pe, kDontCareTag);
251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Fetch and return empty and full pages into the empty and full pools.
255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetValid(struct page_entry *pe, int32 tag) {
256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = false;
257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get valid page depending on implementation.
258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = finelock_q_->GetValid(pe, tag);
260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = valid_->PopRandom(pe);
262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (result) {
264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->addr = os_->PrepareTestMem(pe->offset, page_length_);  // Map it.
265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Tag this access and current pattern.
267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->ts = os_->GetTimestamp();
268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->lastpattern = pe->pattern;
269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (pe->addr != 0);     // Return success or failure.
271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PutValid(struct page_entry *pe) {
276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe->addr != 0)
277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->ReleaseTestMem(pe->addr, pe->offset, page_length_);  // Unmap the page.
278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe->addr = 0;
279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Put valid page depending on implementation.
281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return finelock_q_->PutValid(pe);
283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return valid_->Push(pe);
285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get an empty page with any tag.
290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetEmpty(struct page_entry *pe) {
291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return GetEmpty(pe, kDontCareTag);
292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetEmpty(struct page_entry *pe, int32 tag) {
295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = false;
296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get empty page depending on implementation.
297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = finelock_q_->GetEmpty(pe, tag);
299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = empty_->PopRandom(pe);
301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (result) {
303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->addr = os_->PrepareTestMem(pe->offset, page_length_);  // Map it.
304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (pe->addr != 0);     // Return success or failure.
305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PutEmpty(struct page_entry *pe) {
310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe->addr != 0)
311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->ReleaseTestMem(pe->addr, pe->offset, page_length_);  // Unmap the page.
312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe->addr = 0;
313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Put empty page depending on implementation.
315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return finelock_q_->PutEmpty(pe);
317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return empty_->Push(pe);
319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set up the bitmap of physical pages in case we want to see which pages were
324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// accessed under this run of SAT.
325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapInit() {
326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Find about how much physical mem is in the system.
329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // TODO(nsanders): Find some way to get the max
330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // and min phys addr in the system.
331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 maxsize = os_->FindFreeMemSize() * 4;
332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(maxsize != 0);
333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Make a bitmask of this many pages. Assume that the memory is relatively
335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // zero based. This is true on x86, typically.
336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This is one bit per page.
337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 arraysize = maxsize / 4096 / 8;
338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  unsigned char *bitmap = new unsigned char[arraysize];
339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(bitmap);
340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Mark every page as 0, not seen.
342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  memset(bitmap, 0, arraysize);
343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_size_ = maxsize;
345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_ = bitmap;
346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Add the 4k pages in this block to the array of pages SAT has seen.
349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapUpdate(struct page_entry *pe) {
350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Go through 4k page blocks.
354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 arraysize = page_bitmap_size_ / 4096 / 8;
355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  char *base = reinterpret_cast<char*>(pe->addr);
357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < page_length_; i += 4096) {
358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    uint64 paddr = os_->VirtualToPhysical(base + i);
359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    uint32 offset = paddr / 4096 / 8;
361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    unsigned char mask = 1 << ((paddr / 4096) % 8);
362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (offset >= arraysize) {
364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Physical address %#llx is "
365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                   "greater than expected %#llx.\n",
366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                paddr, page_bitmap_size_);
367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      sat_assert(0);
368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    page_bitmap_[offset] |= mask;
370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print out the physical memory ranges that SAT has accessed.
374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapPrint() {
375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 pages = page_bitmap_size_ / 4096;
379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 last_page = 0;
381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool valid_range = false;
382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Log: Printing tested physical ranges.\n");
384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (uint64 i = 0; i < pages; i ++) {
386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int offset = i / 8;
387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    unsigned char mask = 1 << (i % 8);
388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bool touched = page_bitmap_[offset] & mask;
390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (touched && !valid_range) {
391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_range = true;
392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      last_page = i * 4096;
393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else if (!touched && valid_range) {
394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_range = false;
395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: %#016llx - %#016llx\n", last_page, (i * 4096) - 1);
396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Log: Done printing physical ranges.\n");
399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initializes page lists and fills pages with data patterns.
402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::InitializePages() {
403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int result = 1;
404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate needed page totals.
405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 neededpages = memory_threads_ +
406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_threads_ +
407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_threads_ +
408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_threads_ +
409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_threads_;
410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Empty-valid page ratio is adjusted depending on queue implementation.
412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // since fine-grain-locked queue keeps both valid and empty entries in the
413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // same queue and randomly traverse to find pages, the empty-valid ratio
414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // should be more even.
415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    freepages_ = pages_ / 5 * 2;  // Mark roughly 2/5 of all pages as Empty.
417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    freepages_ = (pages_ / 100) + (2 * neededpages);
419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (freepages_ < neededpages) {
421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: freepages < neededpages.\n");
422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Stats: Total: %lld, Needed: %lld, Marked free: %lld\n",
423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_),
424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(neededpages),
425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(freepages_));
426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (freepages_ >  pages_/2) {
431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: not enough pages for IO\n");
432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Stats: Total: %lld, Needed: %lld, Available: %lld\n",
433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_),
434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(freepages_),
435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_/2));
436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Allocating pages, Total: %lld Free: %lld\n",
440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            pages_,
441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            freepages_);
442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize page locations.
444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int64 i = 0; i < pages_; i++) {
445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    struct page_entry pe;
446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    init_pe(&pe);
447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe.offset = i * page_length_;
448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result &= PutEmpty(&pe);
449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!result) {
452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: while initializing empty_ list\n");
453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fill valid pages with test patterns.
458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use fill threads to do this.
459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus fill_status;
460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector fill_vector;
461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Starting Fill threads: %d threads, %d pages\n",
463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            fill_threads_, pages_);
464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize the fill threads.
465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < fill_threads_; i++) {
466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    FillThread *thread = new FillThread();
467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(i, this, os_, patternlist_, &fill_status);
468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i != fill_threads_ - 1) {
469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(12, "Starting Fill Threads %d: %d pages\n",
470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  i, pages_ / fill_threads_);
471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->SetFillPages(pages_ / fill_threads_);
472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // The last thread finishes up all the leftover pages.
473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Starting Fill Threads %d: %d pages\n",
475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                i, pages_ - pages_ / fill_threads_ * i);
476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->SetFillPages(pages_ - pages_ / fill_threads_ * i);
477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    fill_vector.push_back(thread);
479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn the fill threads.
482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_status.Initialize();
483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = fill_vector.begin();
484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != fill_vector.end(); ++it)
485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->SpawnThread();
486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Reap the finished fill threads.
488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = fill_vector.begin();
489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != fill_vector.end(); ++it) {
490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->JoinThread();
491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetStatus() != 1) {
492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Thread %d failed with status %d at %.2f seconds\n",
493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetStatus(),
494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->GetRunDurationUSec() * 1.0/1000000);
495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete (*it);
499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_vector.clear();
501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_status.Destroy();
502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Done filling pages.\n");
503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Allocating pages.\n");
504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AddrMapInit();
506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize page locations.
508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int64 i = 0; i < pages_; i++) {
509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    struct page_entry pe;
510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Only get valid pages with uninitialized tags here.
511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (GetValid(&pe, kInvalidTag)) {
512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int64 paddr = os_->VirtualToPhysical(pe.addr);
513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int32 region = os_->FindRegion(paddr);
514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_[region]++;
515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      pe.paddr = paddr;
516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      pe.tag = 1 << region;
517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_mask_ |= pe.tag;
518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Generate a physical region map
520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      AddrMapUpdate(&pe);
521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Note: this does not allocate free pages among all regions
523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // fairly. However, with large enough (thousands) random number
524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // of pages being marked free in each region, the free pages
525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // count in each region end up pretty balanced.
526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < freepages_) {
527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        result &= PutEmpty(&pe);
528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else {
529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        result &= PutValid(&pe);
530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: didn't tag all pages. %d - %d = %d\n",
533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                pages_, i, pages_ - i);
534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Done allocating pages.\n");
538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AddrMapPrint();
540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < 32; i++) {
542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (region_mask_ & (1 << i)) {
543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_count_++;
544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Region %d: %d.\n", i, region_[i]);
545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: Region mask: 0x%x\n", region_mask_);
548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print SAT version info.
553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PrintVersion() {
554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(1, "Stats: SAT revision %s, %d bit binary\n",
555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            kVersion, address_mode_);
556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: %s from %s\n", Timestamp(), BuildChangelist());
557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initializes the resources that SAT needs to run.
563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This needs to be called before Run(), and after ParseArgs().
564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns true on success, false on error, and will exit() on help message.
565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Initialize() {
566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  g_sat = this;
567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initializes sync'd log file to ensure output is saved.
569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializeLogfile())
570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
571241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  Logger::GlobalLogger()->SetTimestampLogging(log_timestamps_);
572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->StartThread();
573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: Commandline - %s\n", cmdline_.c_str());
575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  PrintVersion();
576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  std::map<std::string, std::string> options;
578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  GoogleOsOptions(&options);
580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize OS/Hardware interface.
582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  os_ = OsLayerFactory(options);
583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_) {
584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (min_hugepages_mbytes_ > 0)
589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->SetMinimumHugepagesSize(min_hugepages_mbytes_ * kMegabyte);
590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
591241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (reserve_mb_ > 0)
592241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    os_->SetReserveSize(reserve_mb_);
593241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
594241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (channels_.size() > 0) {
595241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    logprintf(6, "Log: Decoding memory: %dx%d bit channels,"
596241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        "%d modules per channel (x%d), decoding hash 0x%x\n",
597241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        channels_.size(), channel_width_, channels_[0].size(),
598241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        channel_width_/channels_[0].size(), channel_hash_);
599241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    os_->SetDramMappingParams(channel_hash_, channel_width_, &channels_);
600241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  }
601241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_->Initialize()) {
603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Failed to initialize OS layer\n");
604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete os_;
606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Checks that OS/Build/Platform is supported.
610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!CheckEnvironment())
611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (error_injection_)
614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->set_error_injection(true);
615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Run SAT in monitor only mode, do not continue to allocate resources.
617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (monitor_mode_) {
618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(5, "Log: Running in monitor-only mode. "
619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "Will not allocate any memory nor run any stress test. "
620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "Only polling ECC errors.\n");
621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return true;
622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate the memory to test.
625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!AllocateMemory())
626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Stats: Starting SAT, %dM, %d seconds\n",
629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            static_cast<int>(size_/kMegabyte),
630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            runtime_seconds_);
631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializePatterns())
633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize memory allocation.
636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pages_ = size_ / page_length_;
637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate page queue depending on queue implementation switch.
639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK) {
640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      finelock_q_ = new FineLockPEQueue(pages_, page_length_);
641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (finelock_q_ == NULL)
642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        return false;
643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      finelock_q_->set_os(os_);
644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      os_->set_err_log_callback(finelock_q_->get_err_log_callback());
645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else if (pe_q_implementation_ == SAT_ONELOCK) {
646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      empty_ = new PageEntryQueue(pages_);
647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_ = new PageEntryQueue(pages_);
648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((empty_ == NULL) || (valid_ == NULL))
649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        return false;
650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializePages()) {
653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Initialize Pages failed\n");
654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Constructor and destructor.
661b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonSat::Sat() {
662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set defaults, command line might override these.
663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  runtime_seconds_ = 20;
664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_length_ = kSatPageSize;
665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  disk_pages_ = kSatDiskPage;
666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pages_ = 0;
667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_mb_ = 0;
668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = size_mb_ * kMegabyte;
669241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  reserve_mb_ = 0;
670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  min_hugepages_mbytes_ = 0;
671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  freepages_ = 0;
672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  paddr_base_ = 0;
673241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  channel_hash_ = kCacheLineSize;
674241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  channel_width_ = 64;
675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  user_break_ = false;
677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  verbosity_ = 8;
678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetVerbosity(verbosity_);
679241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  print_delay_ = 10;
680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  strict_ = 1;
681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  warm_ = 0;
682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  run_on_anything_ = 0;
683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  use_logfile_ = 0;
684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logfile_ = 0;
685241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  log_timestamps_ = true;
686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Detect 32/64 bit binary.
687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void *pvoid = 0;
688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  address_mode_ = sizeof(pvoid) * 8;
689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  error_injection_ = false;
690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  crazy_error_injection_ = false;
691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  max_errorcount_ = 0;  // Zero means no early exit.
692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  stop_on_error_ = false;
693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  error_poll_ = true;
694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  findfiles_ = false;
695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  do_page_map_ = false;
697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_ = 0;
698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_size_ = 0;
699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Cache coherency data initialization.
701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_test_ = false;         // Flag to trigger cc threads.
702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_cacheline_count_ = 2;  // Two datastructures of cache line size.
703241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  cc_cacheline_size_ = 0;   // Size of a cacheline (0 for auto-detect).
704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_inc_count_ = 1000;     // Number of times to increment the shared variable.
705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_cacheline_data_ = 0;   // Cache Line size datastructure.
706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
707241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  // Cpu frequency data initialization.
708241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  cpu_freq_test_ = false;   // Flag to trigger cpu frequency thread.
709241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  cpu_freq_threshold_ = 0;  // Threshold, in MHz, at which a cpu fails.
710241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  cpu_freq_round_ = 10;     // Round the computed frequency to this value.
711241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_init(&worker_lock_, NULL));
713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  file_threads_ = 0;
714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  net_threads_ = 0;
715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  listen_threads_ = 0;
716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Default to autodetect number of cpus, and run that many threads.
717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  memory_threads_ = -1;
718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  invert_threads_ = 0;
719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_threads_ = 8;
720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  check_threads_ = 0;
721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cpu_stress_threads_ = 0;
722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  disk_threads_ = 0;
723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  total_threads_ = 0;
724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_mask_ = 0;
726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_count_ = 0;
727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < 32; i++) {
728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    region_[i] = 0;
729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_mode_ = 0;
731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  errorcount_ = 0;
733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  statuscount_ = 0;
734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  valid_ = 0;
736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  empty_ = 0;
737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  finelock_q_ = 0;
738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Default to use fine-grain lock for better performance.
739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe_q_implementation_ = SAT_FINELOCK;
740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  os_ = 0;
742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  patternlist_ = 0;
743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logfilename_[0] = 0;
744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  read_block_size_ = 512;
746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  write_block_size_ = -1;
747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  segment_size_ = -1;
748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cache_size_ = -1;
749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  blocks_per_segment_ = -1;
750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  read_threshold_ = -1;
751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  write_threshold_ = -1;
752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  non_destructive_ = 1;
753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  monitor_mode_ = 0;
754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  tag_mode_ = 0;
755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  random_threads_ = 0;
756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pause_delay_ = 600;
758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pause_duration_ = 15;
759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Destructor.
762b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonSat::~Sat() {
763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We need to have called Cleanup() at this point.
764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We should probably enforce this.
765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_KVALUE(argument, variable, value)         \
769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                   \
770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    variable = value;                                 \
771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                         \
772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_IVALUE(argument, variable)                \
775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                   \
776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    i++;                                              \
777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i < argc)                                     \
778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      variable = strtoull(argv[i], NULL, 0);          \
779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                         \
780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_SVALUE(argument, variable)                     \
783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                        \
784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    i++;                                                   \
785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i < argc)                                          \
786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      snprintf(variable, sizeof(variable), "%s", argv[i]); \
787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                              \
788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Configures SAT from command line arguments.
791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This will call exit() given a request for
792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// self-documentation or unexpected args.
793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::ParseArgs(int argc, char **argv) {
794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int i;
795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 filesize = page_length_ * disk_pages_;
796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Parse each argument.
798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (i = 1; i < argc; i++) {
799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Switch to fall back to corase-grain-lock queue. (for benchmarking)
800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--coarse_grain_lock", pe_q_implementation_, SAT_ONELOCK);
801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of megabyte to use.
803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-M", size_mb_);
804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
805241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Specify the amount of megabytes to be reserved for system.
806241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--reserve_memory", reserve_mb_);
807241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set minimum megabytes of hugepages to require.
809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-H", min_hugepages_mbytes_);
810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of seconds to run.
812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-s", runtime_seconds_);
813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of memory copy threads.
815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-m", memory_threads_);
816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of memory invert threads.
818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-i", invert_threads_);
819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of check-only threads.
821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-c", check_threads_);
822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of cache line size datastructures.
824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cc_inc_count", cc_inc_count_);
825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of cache line size datastructures
827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cc_line_count", cc_cacheline_count_);
828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
829241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Override the detected or assumed cache line size.
830241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--cc_line_size", cc_cacheline_size_);
831241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Flag set when cache coherency tests need to be run
833241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_KVALUE("--cc_test", cc_test_, true);
834241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
835241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Set when the cpu_frequency test needs to be run
836241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_KVALUE("--cpu_freq_test", cpu_freq_test_, true);
837241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
838241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Set the threshold in MHz at which the cpu frequency test will fail.
839241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--cpu_freq_threshold", cpu_freq_threshold_);
840241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
841241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Set the rounding value for the cpu frequency test. The default is to
842241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // round to the nearest 10s value.
843241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--cpu_freq_round", cpu_freq_round_);
844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of CPU stress threads.
846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-C", cpu_stress_threads_);
847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set logfile name.
849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_SVALUE("-l", logfilename_);
850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Verbosity level.
852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-v", verbosity_);
853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
854241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Chatty printout level.
855241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--printsec", print_delay_);
856241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
857241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Turn off timestamps logging.
858241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_KVALUE("--no_timestamps", log_timestamps_, false);
859241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set maximum number of errors to collect. Stop running after this many.
861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--max_errors", max_errorcount_);
862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set pattern block size.
864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-p", page_length_);
865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set pattern block size.
867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--filesize", filesize);
868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // NUMA options.
870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--local_numa", region_mode_, kLocalNuma);
871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--remote_numa", region_mode_, kRemoteNuma);
872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Autodetect tempfile locations.
874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--findfiles", findfiles_, 1);
875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Inject errors to force miscompare code paths
877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--force_errors", error_injection_, true);
878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--force_errors_like_crazy", crazy_error_injection_, true);
879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (crazy_error_injection_)
880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      error_injection_ = true;
881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Stop immediately on any arror, for debugging HW problems.
883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--stop_on_errors", stop_on_error_, 1);
884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Don't use internal error polling, allow external detection.
886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--no_errors", error_poll_, 0);
887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Never check data as you go.
889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-F", strict_, 0);
890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Warm the cpu as you go.
892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-W", warm_, 1);
893b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allow runnign on unknown systems with base unimplemented OsLayer
895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-A", run_on_anything_, 1);
896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
897b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of read blocks for disk test.
898b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--read-block-size", read_block_size_);
899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of write blocks for disk test.
901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--write-block-size", write_block_size_);
902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of segment for disk test.
904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--segment-size", segment_size_);
905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of disk cache size for disk test.
907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cache-size", cache_size_);
908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Number of blocks to test per segment.
910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--blocks-per-segment", blocks_per_segment_);
911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Maximum time a block read should take before warning.
913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--read-threshold", read_threshold_);
914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Maximum time a block write should take before warning.
916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--write-threshold", write_threshold_);
917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Do not write anything to disk in the disk test.
919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--destructive", non_destructive_, 0);
920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run SAT in monitor mode. No test load at all.
922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--monitor_mode", monitor_mode_, true);
923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run SAT in address mode. Tag all cachelines by virt addr.
925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--tag_mode", tag_mode_, true);
926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Dump range map of tested pages..
928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--do_page_map", do_page_map_, true);
929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the physical address base to test.
931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--paddr_base", paddr_base_);
932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the frequency for power spikes.
934b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--pause_delay", pause_delay_);
935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the duration of each pause (for power spikes).
937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--pause_duration", pause_duration_);
938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Disk device names
940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-d")) {
941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        disk_threads_++;
944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        diskfilename_.push_back(string(argv[i]));
945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        blocktables_.push_back(new DiskBlockTable());
946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of disk random threads for each disk write thread.
951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--random-threads", random_threads_);
952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set a tempfile to use in a file thread.
954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-f")) {
955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        file_threads_++;
958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        filename_.push_back(string(argv[i]));
959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set a hostname to use in a network thread.
964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-n")) {
965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        net_threads_++;
968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        ipaddrs_.push_back(string(argv[i]));
969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run threads that listen for incoming SAT net connections.
974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--listen", listen_threads_, 1);
975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (CheckGoogleSpecificArgs(argc, argv, &i)) {
977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
980241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--channel_hash", channel_hash_);
981241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    ARG_IVALUE("--channel_width", channel_width_);
982241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
983241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (!strcmp(argv[i], "--memory_channel")) {
984241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      i++;
985241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      if (i < argc) {
986241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        char *channel = argv[i];
987241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        channels_.push_back(vector<string>());
988241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        while (char* next = strchr(channel, ',')) {
989241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          channels_.back().push_back(string(channel, next - channel));
990241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          channel = next + 1;
991241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        }
992241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        channels_.back().push_back(string(channel));
993241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      }
994241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      continue;
995241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
996241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Default:
998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    PrintVersion();
999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    PrintHelp();
1000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (strcmp(argv[i], "-h") && strcmp(argv[i], "--help")) {
1001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("\n Unknown argument %s\n", argv[i]);
1002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
1003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      exit(1);
1004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Forget it, we printed the help, just bail.
1006b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // We don't want to print test status, or any log parser stuff.
1007b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    exit(0);
1008b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetVerbosity(verbosity_);
1011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Update relevant data members with parsed input.
1013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Translate MB into bytes.
1014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = static_cast<int64>(size_mb_) * kMegabyte;
1015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set logfile flag.
1017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (strcmp(logfilename_, ""))
1018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    use_logfile_ = 1;
1019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Checks valid page length.
1020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (page_length_ &&
1021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      !(page_length_ & (page_length_ - 1)) &&
1022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (page_length_ > 1023)) {
1023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Prints if we have changed from default.
1024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (page_length_ != kSatPageSize)
1025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Updating page size to %d\n", page_length_);
1026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Revert to default page length.
1028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(6, "Process Error: "
1029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              "Invalid page size %d\n", page_length_);
1030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    page_length_ = kSatPageSize;
1031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
1032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set disk_pages_ if filesize or page size changed.
1035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (filesize != static_cast<uint64>(page_length_) *
1036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  static_cast<uint64>(disk_pages_)) {
1037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_pages_ = filesize / page_length_;
1038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (disk_pages_ == 0)
1039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      disk_pages_ = 1;
1040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1042241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  // Validate memory channel parameters if supplied
1043241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (channels_.size()) {
1044241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (channels_.size() == 1) {
1045241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      channel_hash_ = 0;
1046241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(7, "Log: "
1047241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          "Only one memory channel...deactivating interleave decoding.\n");
1048241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    } else if (channels_.size() > 2) {
1049241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(6, "Process Error: "
1050241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          "Triple-channel mode not yet supported... sorry.\n");
1051241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
1052241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
1053241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
1054241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    for (uint i = 0; i < channels_.size(); i++)
1055241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      if (channels_[i].size() != channels_[0].size()) {
1056241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        logprintf(6, "Process Error: "
1057241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders            "Channels 0 and %d have a different count of dram modules.\n", i);
1058241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        bad_status();
1059241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        return false;
1060241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      }
1061241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (channels_[0].size() & (channels_[0].size() - 1)) {
1062241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(6, "Process Error: "
1063241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          "Amount of modules per memory channel is not a power of 2.\n");
1064241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
1065241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
1066241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
1067241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (channel_width_ < 16
1068241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        || channel_width_ & (channel_width_ - 1)) {
1069241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(6, "Process Error: "
1070241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          "Channel width %d is invalid.\n", channel_width_);
1071241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
1072241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
1073241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
1074241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (channel_width_ / channels_[0].size() < 8) {
1075241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(6, "Process Error: Chip width x%d must be x8 or greater.\n",
1076241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders          channel_width_ / channels_[0].size());
1077241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      bad_status();
1078241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      return false;
1079241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
1080241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  }
1081241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1082241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1083b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Print each argument.
1084b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < argc; i++) {
1085b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i)
1086b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cmdline_ += " ";
1087b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cmdline_ += argv[i];
1088b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1089b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1090b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
1091b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1092b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1093b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::PrintHelp() {
1094b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  printf("Usage: ./sat(32|64) [options]\n"
1095b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -M mbytes        megabytes of ram to test\n"
1096241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --reserve-memory If not using hugepages, the amount of memory to "
1097241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " reserve for the system\n"
1098b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -H mbytes        minimum megabytes of hugepages to require\n"
1099b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -s seconds       number of seconds to run\n"
1100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -m threads       number of memory copy threads to run\n"
1101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -i threads       number of memory invert threads to run\n"
1102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -C threads       number of memory CPU stress threads to run\n"
1103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --findfiles      find locations to do disk IO automatically\n"
1104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -d device        add a direct write disk thread with block "
1105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "device (or file) 'device'\n"
1106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -f filename      add a disk thread with "
1107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "tempfile 'filename'\n"
1108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -l logfile       log output to file 'logfile'\n"
1109241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --no_timestamps  do not prefix timestamps to log messages\n"
1110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --max_errors n   exit early after finding 'n' errors\n"
1111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -v level         verbosity (0-20), default is 8\n"
1112241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --printsec secs  How often to print 'seconds remaining'\n"
1113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -W               Use more CPU-stressful memory copy\n"
1114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -A               run in degraded mode on incompatible systems\n"
1115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -p pagesize      size in bytes of memory chunks\n"
1116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --filesize size  size of disk IO tempfiles\n"
1117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -n ipaddr        add a network thread connecting to "
1118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "system at 'ipaddr'\n"
1119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --listen         run a thread to listen for and respond "
1120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to network threads.\n"
1121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --no_errors      run without checking for ECC or other errors\n"
1122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --force_errors   inject false errors to test error handling\n"
1123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --force_errors_like_crazy   inject a lot of false errors "
1124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to test error handling\n"
1125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -F               don't result check each transaction\n"
1126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --stop_on_errors  Stop after finding the first error.\n"
1127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --read-block-size     size of block for reading (-d)\n"
1128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --write-block-size    size of block for writing (-d). If not "
1129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "defined, the size of block for writing will be defined as the "
1130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "size of block for reading\n"
1131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --segment-size   size of segments to split disk into (-d)\n"
1132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cache-size     size of disk cache (-d)\n"
1133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --blocks-per-segment  number of blocks to read/write per "
1134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "segment per iteration (-d)\n"
1135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --read-threshold      maximum time (in us) a block read should "
1136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "take (-d)\n"
1137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --write-threshold     maximum time (in us) a block write "
1138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "should take (-d)\n"
1139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --random-threads      number of random threads for each disk "
1140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "write thread (-d)\n"
1141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --destructive    write/wipe disk partition (-d)\n"
1142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --monitor_mode   only do ECC error polling, no stress load.\n"
1143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_test        do the cache coherency testing\n"
1144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_inc_count   number of times to increment the "
1145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "cacheline's member\n"
1146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_line_count  number of cache line sized datastructures "
1147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to allocate for the cache coherency threads to operate\n"
1148241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --cc_line_size   override the auto-detected cache line size\n"
1149241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --cpu_freq_test  enable the cpu frequency test (requires the "
1150241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "--cpu_freq_threshold argument to be set)\n"
1151241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --cpu_freq_threshold  fail the cpu frequency test if the frequency "
1152241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "goes below this value (specified in MHz)\n"
1153241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --cpu_freq_round round the computed frequency to this value, if set"
1154241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " to zero, only round to the nearest MHz\n"
1155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --paddr_base     allocate memory starting from this address\n"
1156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --pause_delay    delay (in seconds) between power spikes\n"
1157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --pause_duration duration (in seconds) of each pause\n"
1158241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --local_numa     choose memory regions associated with "
1159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "each CPU to be tested by that CPU\n"
1160241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --remote_numa    choose memory regions not associated with "
1161241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "each CPU to be tested by that CPU\n"
1162241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --channel_hash   mask of address bits XORed to determine channel. "
1163241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "Mask 0x40 interleaves cachelines between channels\n"
1164241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --channel_width bits     width in bits of each memory channel\n"
1165241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         " --memory_channel u1,u2   defines a comma-separated list of names "
1166241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "for dram packages in a memory channel. Use multiple times to "
1167241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders         "define multiple channels.\n");
1168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::CheckGoogleSpecificArgs(int argc, char **argv, int *i) {
1171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, no google-specific argument on public stressapptest
1172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
1173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::GoogleOsOptions(std::map<std::string, std::string> *options) {
1176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, no OS-specific argument on public stressapptest
1177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Launch the SAT task threads. Returns 0 on error.
1180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::InitializeThreads() {
1181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Memory copy threads.
1182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting worker threads\n");
1185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *memory_vector = new WorkerVector();
1186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Error polling thread.
1188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This may detect ECC corrected errors, disk problems, or
1189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // any other errors normally hidden from userspace.
1190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *error_vector = new WorkerVector();
1191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (error_poll_) {
1192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ErrorPollThread *thread = new ErrorPollThread();
1193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    error_vector->insert(error_vector->end(), thread);
1197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(5, "Log: Skipping error poll thread due to --no_errors flag\n");
1199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kErrorType, error_vector));
1201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Only start error poll threads for monitor-mode SAT,
1203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // skip all other types of worker threads.
1204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (monitor_mode_) {
1205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ReleaseWorkerLock();
1206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
1207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < memory_threads_; i++) {
1210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CopyThread *thread = new CopyThread();
1211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((region_count_ > 1) && (region_mode_)) {
1215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int32 region = region_find(i % region_count_);
1216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpu_set_t *cpuset = os_->FindCoreMask(region);
1217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      sat_assert(cpuset);
1218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (region_mode_ == kLocalNuma) {
1219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Choose regions associated with this CPU.
1220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask(cpuset);
1221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_tag(1 << region);
1222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else if (region_mode_ == kRemoteNuma) {
1223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Choose regions not associated with this CPU..
1224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask(cpuset);
1225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_tag(region_mask_ & ~(1 << region));
1226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
1228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpu_set_t available_cpus;
1229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->AvailableCpus(&available_cpus);
1230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int cores = cpuset_count(&available_cpus);
1231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Don't restrict thread location if we have more than one
1232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // thread per core. Not so good for performance.
1233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (cpu_stress_threads_ + memory_threads_ <= cores) {
1234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Place a thread on alternating cores first.
1235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // This assures interleaved core use with no overlap.
1236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        int nthcore = i;
1237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        int nthbit = (((2 * nthcore) % cores) +
1238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                      (((2 * nthcore) / cores) % 2)) % cores;
1239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        cpu_set_t all_cores;
1240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        cpuset_set_ab(&all_cores, 0, cores);
1241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        if (!cpuset_isequal(&available_cpus, &all_cores)) {
1242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          // We are assuming the bits are contiguous.
1243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          // Complain if this is not so.
1244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          logprintf(0, "Log: cores = %s, expected %s\n",
1245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    cpuset_format(&available_cpus).c_str(),
1246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    cpuset_format(&all_cores).c_str());
1247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        }
1248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Set thread affinity.
1250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask_to_cpu(nthbit);
1251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memory_vector->insert(memory_vector->end(), thread);
1254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kMemoryType, memory_vector));
1256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // File IO threads.
1258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *fileio_vector = new WorkerVector();
1259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < file_threads_; i++) {
1260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    FileThread *thread = new FileThread();
1261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetFile(filename_[i].c_str());
1264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set disk threads high priority. They don't take much processor time,
1265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // but blocking them will delay disk IO.
1266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetPriority(WorkerThread::High);
1267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    fileio_vector->insert(fileio_vector->end(), thread);
1269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kFileIOType, fileio_vector));
1271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Net IO threads.
1273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *netio_vector = new WorkerVector();
1274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *netslave_vector = new WorkerVector();
1275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (listen_threads_ > 0) {
1276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Create a network slave thread. This listens for connections.
1277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    NetworkListenThread *thread = new NetworkListenThread();
1278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    netslave_vector->insert(netslave_vector->end(), thread);
1282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < net_threads_; i++) {
1284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    NetworkThread *thread = new NetworkThread();
1285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetIP(ipaddrs_[i].c_str());
1288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    netio_vector->insert(netio_vector->end(), thread);
1290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kNetIOType, netio_vector));
1292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kNetSlaveType, netslave_vector));
1293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Result check threads.
1295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *check_vector = new WorkerVector();
1296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < check_threads_; i++) {
1297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CheckThread *thread = new CheckThread();
1298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_vector->insert(check_vector->end(), thread);
1302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kCheckType, check_vector));
1304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Memory invert threads.
1306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting invert threads\n");
1307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *invert_vector = new WorkerVector();
1308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < invert_threads_; i++) {
1309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    InvertThread *thread = new InvertThread();
1310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_vector->insert(invert_vector->end(), thread);
1314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kInvertType, invert_vector));
1316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Disk stress threads.
1318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *disk_vector = new WorkerVector();
1319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *random_vector = new WorkerVector();
1320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting disk stress threads\n");
1321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < disk_threads_; i++) {
1322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Creating write threads
1323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    DiskThread *thread = new DiskThread(blocktables_[i]);
1324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetDevice(diskfilename_[i].c_str());
1327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (thread->SetParameters(read_block_size_, write_block_size_,
1328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              segment_size_, cache_size_,
1329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              blocks_per_segment_,
1330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              read_threshold_, write_threshold_,
1331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              non_destructive_)) {
1332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      disk_vector->insert(disk_vector->end(), thread);
1333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
1334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: DiskThread::SetParameters() failed\n");
1335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      delete thread;
1336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (int j = 0; j < random_threads_; j++) {
1339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Creating random threads
1340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      RandomDiskThread *rthread = new RandomDiskThread(blocktables_[i]);
1341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      rthread->InitThread(total_threads_++, this, os_, patternlist_,
1342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          &power_spike_status_);
1343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      rthread->SetDevice(diskfilename_[i].c_str());
1344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (rthread->SetParameters(read_block_size_, write_block_size_,
1345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 segment_size_, cache_size_,
1346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 blocks_per_segment_,
1347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 read_threshold_, write_threshold_,
1348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 non_destructive_)) {
1349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        random_vector->insert(random_vector->end(), rthread);
1350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else {
1351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: RandomDiskThread::SetParameters() failed\n");
1352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        delete rthread;
1353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kDiskType, disk_vector));
1358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kRandomDiskType, random_vector));
1359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // CPU stress threads.
1361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *cpu_vector = new WorkerVector();
1362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting cpu stress threads\n");
1363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < cpu_stress_threads_; i++) {
1364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CpuStressThread *thread = new CpuStressThread();
1365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Don't restrict thread location if we have more than one
1369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // thread per core. Not so good for performance.
1370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpu_set_t available_cpus;
1371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->AvailableCpus(&available_cpus);
1372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int cores = cpuset_count(&available_cpus);
1373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (cpu_stress_threads_ + memory_threads_ <= cores) {
1374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Place a thread on alternating cores first.
1375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Go in reverse order for CPU stress threads. This assures interleaved
1376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // core use with no overlap.
1377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int nthcore = (cores - 1) - i;
1378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int nthbit = (((2 * nthcore) % cores) +
1379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    (((2 * nthcore) / cores) % 2)) % cores;
1380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpu_set_t all_cores;
1381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpuset_set_ab(&all_cores, 0, cores);
1382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (!cpuset_isequal(&available_cpus, &all_cores)) {
1383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(0, "Log: cores = %s, expected %s\n",
1384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  cpuset_format(&available_cpus).c_str(),
1385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  cpuset_format(&all_cores).c_str());
1386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Set thread affinity.
1389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->set_cpu_mask_to_cpu(nthbit);
1390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpu_vector->insert(cpu_vector->end(), thread);
1394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kCPUType, cpu_vector));
1396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // CPU Cache Coherency Threads - one for each core available.
1398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (cc_test_) {
1399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    WorkerVector *cc_vector = new WorkerVector();
1400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Starting cpu cache coherency threads\n");
1401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allocate the shared datastructure to be worked on by the threads.
1403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cc_cacheline_data_ = reinterpret_cast<cc_cacheline_data*>(
1404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        malloc(sizeof(cc_cacheline_data) * cc_cacheline_count_));
1405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(cc_cacheline_data_ != NULL);
1406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Initialize the strucutre.
1408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memset(cc_cacheline_data_, 0,
1409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson           sizeof(cc_cacheline_data) * cc_cacheline_count_);
1410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int num_cpus = CpuCount();
1412241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    char *num;
1413241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Calculate the number of cache lines needed just to give each core
1414241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // its own counter.
1415241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    int line_size = cc_cacheline_size_;
1416241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    if (line_size <= 0) {
1417241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      line_size = CacheLineSize();
1418241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      if (line_size < kCacheLineSize)
1419241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        line_size = kCacheLineSize;
1420241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      logprintf(12, "Log: Using %d as cache line size\n", line_size);
1421241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    }
1422241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // The number of cache lines needed to hold an array of num_cpus.
1423241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // "num" must be the same type as cc_cacheline_data[X].num or the memory
1424241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // size calculations will fail.
1425241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    int needed_lines = (sizeof(*num) * num_cpus + line_size - 1) / line_size;
1426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allocate all the nums once so that we get a single chunk
1427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // of contiguous memory.
14288f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_POSIX_MEMALIGN
1429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int err_result = posix_memalign(
1430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        reinterpret_cast<void**>(&num),
1431241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        line_size, line_size * needed_lines * cc_cacheline_count_);
14328f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#else
1433241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    num = reinterpret_cast<char*>(memalign(
1434241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders        line_size, line_size * needed_lines * cc_cacheline_count_));
14358f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson    int err_result = (num == 0);
14368f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
1437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(err_result == 0);
1438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int cline;
1440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (cline = 0; cline < cc_cacheline_count_; cline++) {
1441241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      memset(num, 0, sizeof(*num) * num_cpus);
1442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cc_cacheline_data_[cline].num = num;
1443241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      num += (line_size * needed_lines) / sizeof(*num);
1444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int tnum;
1447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (tnum = 0; tnum < num_cpus; tnum++) {
1448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      CpuCacheCoherencyThread *thread =
1449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          new CpuCacheCoherencyThread(cc_cacheline_data_, cc_cacheline_count_,
1450241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                                      tnum, num_cpus, cc_inc_count_);
1451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->InitThread(total_threads_++, this, os_, patternlist_,
1452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                         &continuous_status_);
1453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Pin the thread to a particular core.
1454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->set_cpu_mask_to_cpu(tnum);
1455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Insert the thread into the vector.
1457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cc_vector->insert(cc_vector->end(), thread);
1458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    workers_map_.insert(make_pair(kCCType, cc_vector));
1460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1461241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1462241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (cpu_freq_test_) {
1463241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // Create the frequency test thread.
1464241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    logprintf(5, "Log: Running cpu frequency test: threshold set to %dMHz.\n",
1465241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders              cpu_freq_threshold_);
1466241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    CpuFreqThread *thread = new CpuFreqThread(CpuCount(), cpu_freq_threshold_,
1467241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                                              cpu_freq_round_);
1468241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    // This thread should be paused when other threads are paused.
1469241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    thread->InitThread(total_threads_++, this, os_, NULL,
1470241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders                       &power_spike_status_);
1471241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1472241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    WorkerVector *cpu_freq_vector = new WorkerVector();
1473241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    cpu_freq_vector->insert(cpu_freq_vector->end(), thread);
1474241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders    workers_map_.insert(make_pair(kCPUFreqType, cpu_freq_vector));
1475241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  }
1476241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return the number of cpus actually present in the machine.
1481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint Sat::CpuCount() {
1482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return sysconf(_SC_NPROCESSORS_CONF);
1483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1485241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders// Return the worst case (largest) cache line size of the various levels of
1486241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders// cache actually prsent in the machine.
1487241f33a3e958842e3db803c03300764bd2ee9c19Nick Sandersint Sat::CacheLineSize() {
1488241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  int max_linesize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
1489241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  int linesize = sysconf(_SC_LEVEL2_CACHE_LINESIZE);
1490241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (linesize > max_linesize) max_linesize = linesize;
1491241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  linesize = sysconf(_SC_LEVEL3_CACHE_LINESIZE);
1492241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (linesize > max_linesize) max_linesize = linesize;
1493241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  linesize = sysconf(_SC_LEVEL4_CACHE_LINESIZE);
1494241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  if (linesize > max_linesize) max_linesize = linesize;
1495241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  return max_linesize;
1496241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders}
1497241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
1498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Notify and reap worker threads.
1499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::JoinThreads() {
1500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Joining worker threads\n");
1501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.StopWorkers();
1502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.StopWorkers();
1503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
1510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (*it)->JoinThread();
1511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  QueueStats();
1516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Finish up result checking.
1518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn 4 check threads to minimize check time.
1519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Finished countdown, begin to result check\n");
1520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus reap_check_status;
1521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector reap_check_vector;
1522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // No need for check threads for monitor mode.
1524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!monitor_mode_) {
1525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Initialize the check threads.
1526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (int i = 0; i < fill_threads_; i++) {
1527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      CheckThread *thread = new CheckThread();
1528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->InitThread(total_threads_++, this, os_, patternlist_,
1529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                         &reap_check_status);
1530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Finished countdown, begin to result check\n");
1531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      reap_check_vector.push_back(thread);
1532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.Initialize();
1536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check threads should be marked to stop ASAP.
1537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.StopWorkers();
1538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn the check threads.
1540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
1543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->SpawnThread();
1544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Join the check threads.
1547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
1550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->JoinThread();
1551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Reap all children. Stopped threads should have already ended.
1554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Result checking threads will end when they have finished
1555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // result checking.
1556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Join all outstanding threads\n");
1557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Find all errors.
1559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  errorcount_ = GetTotalErrorCount();
1560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
1567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((*it)->GetStatus() != 1) {
1568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(0, "Process Error: Thread %d failed with status %d at "
1569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  "%.2f seconds\n",
1570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  (*it)->ThreadID(), (*it)->GetStatus(),
1571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  (*it)->GetRunDurationUSec()*1.0/1000000);
1572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        bad_status();
1573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int priority = 12;
1575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((*it)->GetErrorCount())
1576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        priority = 5;
1577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
1578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetErrorCount());
1579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Add in any errors from check threads.
1585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
1588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetStatus() != 1) {
1589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Thread %d failed with status %d at "
1590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "%.2f seconds\n",
1591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetStatus(),
1592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->GetRunDurationUSec()*1.0/1000000);
1593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
1594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    errorcount_ += (*it)->GetErrorCount();
1596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int priority = 12;
1597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetErrorCount())
1598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      priority = 5;
1599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
1600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              (*it)->ThreadID(), (*it)->GetErrorCount());
1601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete (*it);
1602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_vector.clear();
1604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.Destroy();
1605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print queuing information.
1608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::QueueStats() {
1609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  finelock_q_->QueueAnalysis();
1610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AnalysisAllStats() {
1613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float max_runtime_sec = 0.;
1614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float total_data = 0.;
1615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float total_bandwidth = 0.;
1616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float thread_runtime_sec = 0.;
1617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1622241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      thread_runtime_sec = (*it)->GetRunDurationUSec()*1.0/1000000.;
1623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      total_data += (*it)->GetMemoryCopiedData();
1624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      total_data += (*it)->GetDeviceCopiedData();
1625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (thread_runtime_sec > max_runtime_sec) {
1626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        max_runtime_sec = thread_runtime_sec;
1627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  total_bandwidth = total_data / max_runtime_sec;
1632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(0, "Stats: Completed: %.2fM in %.2fs %.2fMB/s, "
1634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            "with %d hardware incidents, %d errors\n",
1635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            total_data,
1636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            max_runtime_sec,
1637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            total_bandwidth,
1638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            errorcount_,
1639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            statuscount_);
1640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::MemoryStats() {
1643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float memcopy_data = 0.;
1644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float memcopy_bandwidth = 0.;
1645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator mem_it = workers_map_.find(
1646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kMemoryType));
1647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator file_it = workers_map_.find(
1648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kFileIOType));
1649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(mem_it != workers_map_.end());
1650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(file_it != workers_map_.end());
1651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = mem_it->second->begin();
1652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != mem_it->second->end(); ++it) {
1653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_data += (*it)->GetMemoryCopiedData();
1654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_bandwidth += (*it)->GetMemoryBandwidth();
1655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = file_it->second->begin();
1657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != file_it->second->end(); ++it) {
1658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_data += (*it)->GetMemoryCopiedData();
1659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_bandwidth += (*it)->GetMemoryBandwidth();
1660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  GoogleMemoryStats(&memcopy_data, &memcopy_bandwidth);
1662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Memory Copy: %.2fM at %.2fMB/s\n",
1663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            memcopy_data,
1664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            memcopy_bandwidth);
1665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::GoogleMemoryStats(float *memcopy_data,
1668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            float *memcopy_bandwidth) {
1669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, should be implemented by subclasses.
1670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::FileStats() {
1673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float file_data = 0.;
1674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float file_bandwidth = 0.;
1675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator file_it = workers_map_.find(
1676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kFileIOType));
1677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(file_it != workers_map_.end());
1678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = file_it->second->begin();
1679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != file_it->second->end(); ++it) {
1680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_data += (*it)->GetDeviceCopiedData();
1681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_bandwidth += (*it)->GetDeviceBandwidth();
1682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: File Copy: %.2fM at %.2fMB/s\n",
1684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            file_data,
1685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            file_bandwidth);
1686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::CheckStats() {
1689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float check_data = 0.;
1690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float check_bandwidth = 0.;
1691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator check_it = workers_map_.find(
1692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kCheckType));
1693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(check_it != workers_map_.end());
1694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = check_it->second->begin();
1695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != check_it->second->end(); ++it) {
1696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_data += (*it)->GetMemoryCopiedData();
1697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_bandwidth += (*it)->GetMemoryBandwidth();
1698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Data Check: %.2fM at %.2fMB/s\n",
1700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            check_data,
1701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            check_bandwidth);
1702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::NetStats() {
1705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float net_data = 0.;
1706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float net_bandwidth = 0.;
1707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator netio_it = workers_map_.find(
1708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kNetIOType));
1709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator netslave_it = workers_map_.find(
1710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kNetSlaveType));
1711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(netio_it != workers_map_.end());
1712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(netslave_it != workers_map_.end());
1713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = netio_it->second->begin();
1714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != netio_it->second->end(); ++it) {
1715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_data += (*it)->GetDeviceCopiedData();
1716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_bandwidth += (*it)->GetDeviceBandwidth();
1717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = netslave_it->second->begin();
1719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != netslave_it->second->end(); ++it) {
1720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_data += (*it)->GetDeviceCopiedData();
1721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_bandwidth += (*it)->GetDeviceBandwidth();
1722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Net Copy: %.2fM at %.2fMB/s\n",
1724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            net_data,
1725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            net_bandwidth);
1726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::InvertStats() {
1729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float invert_data = 0.;
1730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float invert_bandwidth = 0.;
1731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator invert_it = workers_map_.find(
1732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kInvertType));
1733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(invert_it != workers_map_.end());
1734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = invert_it->second->begin();
1735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != invert_it->second->end(); ++it) {
1736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_data += (*it)->GetMemoryCopiedData();
1737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_bandwidth += (*it)->GetMemoryBandwidth();
1738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Invert Data: %.2fM at %.2fMB/s\n",
1740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            invert_data,
1741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            invert_bandwidth);
1742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::DiskStats() {
1745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float disk_data = 0.;
1746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float disk_bandwidth = 0.;
1747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator disk_it = workers_map_.find(
1748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kDiskType));
1749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator random_it = workers_map_.find(
1750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kRandomDiskType));
1751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(disk_it != workers_map_.end());
1752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(random_it != workers_map_.end());
1753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = disk_it->second->begin();
1754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != disk_it->second->end(); ++it) {
1755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_data += (*it)->GetDeviceCopiedData();
1756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_bandwidth += (*it)->GetDeviceBandwidth();
1757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = random_it->second->begin();
1759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != random_it->second->end(); ++it) {
1760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_data += (*it)->GetDeviceCopiedData();
1761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_bandwidth += (*it)->GetDeviceBandwidth();
1762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Disk: %.2fM at %.2fMB/s\n",
1765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            disk_data,
1766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            disk_bandwidth);
1767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Process worker thread data for bandwidth information, and error results.
1770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// You can add more methods here just subclassing SAT.
1771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::RunAnalysis() {
1772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AnalysisAllStats();
1773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  MemoryStats();
1774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  FileStats();
1775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  NetStats();
1776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CheckStats();
1777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  InvertStats();
1778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DiskStats();
1779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get total error count, summing across all threads..
1782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 Sat::GetTotalErrorCount() {
1783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 errors = 0;
1784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      errors += (*it)->GetErrorCount();
1791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return errors;
1795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::SpawnThreads() {
1799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Initializing WorkerStatus objects\n");
1800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.Initialize();
1801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.Initialize();
1802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Spawning worker threads\n");
1803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
1808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (*it)->SpawnThread();
1809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Delete used worker thread objects.
1814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::DeleteThreads() {
1815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Deleting worker threads\n");
1816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Deleting thread %d\n", (*it)->ThreadID());
1821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      delete (*it);
1822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete map_it->second;
1824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.clear();
1826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Destroying WorkerStatus objects\n");
1827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.Destroy();
1828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.Destroy();
1829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonnamespace {
1832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Calculates the next time an action in Sat::Run() should occur, based on a
1833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// schedule derived from a start point and a regular frequency.
1834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Using frequencies instead of intervals with their accompanying drift allows
1836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// users to better predict when the actions will occur throughout a run.
1837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Arguments:
1839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   frequency: seconds
1840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   start: unixtime
1841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   now: unixtime
1842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns: unixtime
1844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersoninline time_t NextOccurance(time_t frequency, time_t start, time_t now) {
1845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return start + frequency + (((now - start) / frequency) * frequency);
1846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Run the actual test.
1850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Run() {
1851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Install signal handlers to gracefully exit in the middle of a run.
1852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Why go through this whole rigmarole?  It's the only standards-compliant
1854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // (C++ and POSIX) way to handle signals in a multithreaded program.
1855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Specifically:
1856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // 1) (C++) The value of a variable not of type "volatile sig_atomic_t" is
1858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    unspecified upon entering a signal handler and, if modified by the
1859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    handler, is unspecified after leaving the handler.
1860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // 2) (POSIX) After the value of a variable is changed in one thread, another
1862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    thread is only guaranteed to see the new value after both threads have
1863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    acquired or released the same mutex or rwlock, synchronized to the
1864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    same barrier, or similar.
1865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // #1 prevents the use of #2 in a signal handler, so the signal handler must
1867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // be called in the same thread that reads the "volatile sig_atomic_t"
1868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // variable it sets.  We enforce that by blocking the signals in question in
1869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // the worker threads, forcing them to be handled by this thread.
1870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Installing signal handlers\n");
1871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigset_t new_blocked_signals;
1872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigemptyset(&new_blocked_signals);
1873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigaddset(&new_blocked_signals, SIGINT);
1874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigaddset(&new_blocked_signals, SIGTERM);
1875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigset_t prev_blocked_signals;
1876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_sigmask(SIG_BLOCK, &new_blocked_signals, &prev_blocked_signals);
1877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sighandler_t prev_sigint_handler = signal(SIGINT, SatHandleBreak);
1878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sighandler_t prev_sigterm_handler = signal(SIGTERM, SatHandleBreak);
1879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Kick off all the worker threads.
1881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Launching worker threads\n");
1882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  InitializeThreads();
1883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  SpawnThreads();
1884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_sigmask(SIG_SETMASK, &prev_blocked_signals, NULL);
1885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting countdown with %d seconds\n", runtime_seconds_);
1887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // In seconds.
1889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const time_t kSleepFrequency = 5;
1890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // All of these are in seconds.  You probably want them to be >=
1891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // kSleepFrequency and multiples of kSleepFrequency, but neither is necessary.
1892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const time_t kInjectionFrequency = 10;
1893241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  // print_delay_ determines "seconds remaining" chatty update.
1894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  const time_t start = time(NULL);
1896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  const time_t end = start + runtime_seconds_;
1897b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t now = start;
1898241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  time_t next_print = start + print_delay_;
1899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_pause = start + pause_delay_;
1900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_resume = 0;
1901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_injection;
1902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (crazy_error_injection_) {
1903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    next_injection = start + kInjectionFrequency;
1904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    next_injection = 0;
1906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  while (now < end) {
1909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // This is an int because it's for logprintf().
1910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    const int seconds_remaining = end - now;
1911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (user_break_) {
1913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Handle early exit.
1914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: User exiting early (%d seconds remaining)\n",
1915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                seconds_remaining);
1916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      break;
1917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // If we have an error limit, check it here and see if we should exit.
1920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (max_errorcount_ != 0) {
1921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      uint64 errors = GetTotalErrorCount();
1922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (errors > max_errorcount_) {
1923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(0, "Log: Exiting early (%d seconds remaining) "
1924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                     "due to excessive failures (%lld)\n",
1925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  seconds_remaining,
1926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  errors);
1927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        break;
1928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (now >= next_print) {
1932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Print a count down message.
1933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(5, "Log: Seconds remaining: %d\n", seconds_remaining);
1934241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders      next_print = NextOccurance(print_delay_, start, now);
1935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_injection && now >= next_injection) {
1938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Inject an error.
1939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Injecting error (%d seconds remaining)\n",
1940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                seconds_remaining);
1941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      struct page_entry src;
1942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      GetValid(&src);
1943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      src.pattern = patternlist_->GetPattern(0);
1944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      PutValid(&src);
1945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_injection = NextOccurance(kInjectionFrequency, start, now);
1946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_pause && now >= next_pause) {
1949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Tell worker threads to pause in preparation for a power spike.
1950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Pausing worker threads in preparation for power spike "
1951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "(%d seconds remaining)\n", seconds_remaining);
1952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      power_spike_status_.PauseWorkers();
1953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Worker threads paused\n");
1954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_pause = 0;
1955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_resume = now + pause_duration_;
1956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_resume && now >= next_resume) {
1959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Tell worker threads to resume in order to cause a power spike.
1960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Resuming worker threads to cause a power spike (%d "
1961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "seconds remaining)\n", seconds_remaining);
1962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      power_spike_status_.ResumeWorkers();
1963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Worker threads resumed\n");
1964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_pause = NextOccurance(pause_delay_, start, now);
1965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_resume = 0;
1966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_sleep(NextOccurance(kSleepFrequency, start, now) - now);
1969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    now = time(NULL);
1970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  JoinThreads();
1973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(0, "Stats: Found %lld hardware incidents\n", errorcount_);
1975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!monitor_mode_)
1977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    RunAnalysis();
1978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DeleteThreads();
1980b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1981b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Uninstalling signal handlers\n");
1982b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  signal(SIGINT, prev_sigint_handler);
1983b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  signal(SIGTERM, prev_sigterm_handler);
1984b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1985b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
1986b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1987b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1988b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Clean up all resources.
1989b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Cleanup() {
1990b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  g_sat = NULL;
1991b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->StopThread();
1992b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetStdoutOnly();
1993b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (logfile_) {
1994b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    close(logfile_);
1995b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logfile_ = 0;
1996b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (patternlist_) {
1998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    patternlist_->Destroy();
1999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete patternlist_;
2000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    patternlist_ = 0;
2001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (os_) {
2003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->FreeTestMem();
2004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete os_;
2005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_ = 0;
2006b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2007b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (empty_) {
2008b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete empty_;
2009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    empty_ = 0;
2010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (valid_) {
2012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete valid_;
2013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    valid_ = 0;
2014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (finelock_q_) {
2016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete finelock_q_;
2017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    finelock_q_ = 0;
2018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (page_bitmap_) {
2020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete[] page_bitmap_;
2021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (size_t i = 0; i < blocktables_.size(); i++) {
2024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete blocktables_[i];
2025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (cc_cacheline_data_) {
2028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // The num integer arrays for all the cacheline structures are
2029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // allocated as a single chunk. The pointers in the cacheline struct
2030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // are populated accordingly. Hence calling free on the first
2031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // cacheline's num's address is going to free the entire array.
2032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // TODO(aganti): Refactor this to have a class for the cacheline
2033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // structure (currently defined in worker.h) and clean this up
2034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // in the destructor of that class.
2035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (cc_cacheline_data_[0].num) {
2036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      free(cc_cacheline_data_[0].num);
2037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
2038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    free(cc_cacheline_data_);
2039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_destroy(&worker_lock_));
2042b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2043b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
2044b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
2045b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2046b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2047b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Pretty print really obvious results.
2048b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PrintResults() {
2049b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = true;
2050b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2051b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "\n");
2052b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (statuscount_) {
2053b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: FAIL - test encountered procedural errors\n");
2054b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = false;
2055b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else if (errorcount_) {
2056b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: FAIL - test discovered HW problems\n");
2057b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = false;
2058b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
2059b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: PASS - please verify no corrected errors\n");
2060b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
2061b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "\n");
2062b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2063b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return result;
2064b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
2065b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2066b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Helper functions.
2067b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AcquireWorkerLock() {
2068b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_lock(&worker_lock_));
2069b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
2070b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::ReleaseWorkerLock() {
2071b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_unlock(&worker_lock_));
2072b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
2073b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
2074b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid logprintf(int priority, const char *format, ...) {
2075b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_list args;
2076b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_start(args, format);
2077b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->VLogF(priority, format, args);
2078b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_end(args);
2079b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
2080241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
2081241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders// Stop the logging thread and verify any pending data is written to the log.
2082241f33a3e958842e3db803c03300764bd2ee9c19Nick Sandersvoid logstop() {
2083241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders  Logger::GlobalLogger()->StopThread();
2084241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders}
2085241f33a3e958842e3db803c03300764bd2ee9c19Nick Sanders
2086