sat.cc revision b0114cb9f332db144f65291211ae65f7f0e814e6
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_,
80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    O_WRONLY | O_CREAT | O_DSYNC,
81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (logfile_ < 0) {
83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("Fatal Error: cannot open file %s for logging\n",
84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson             logfilename_);
85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // We seek to the end once instead of opening in append mode because no
89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // other processes should be writing to it while this one exists.
90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (lseek(logfile_, 0, SEEK_END) == -1) {
91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("Fatal Error: cannot seek to end of logfile (%s)\n",
92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson             logfilename_);
93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Logger::GlobalLogger()->SetLogFd(logfile_);
97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Check that the environment is known and safe to run on.
102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return 1 if good, 0 if unsuppported.
103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::CheckEnvironment() {
104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check that this is not a debug build. Debug builds lack
105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // enough performance to stress the system.
106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#if !defined NDEBUG
107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (run_on_anything_) {
108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Log: Running DEBUG version of SAT, "
109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with significantly reduced coverage.\n");
110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Running DEBUG version of SAT, "
112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with significantly reduced coverage.\n");
113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#elif !defined CHECKOPTS
118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  #error Build system regression - COPTS disregarded.
119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif
120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use all CPUs if nothing is specified.
122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (memory_threads_ == -1) {
123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memory_threads_ = os_->num_cpus();
124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(7, "Log: Defaulting to %d copy threads\n", memory_threads_);
125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use all memory if no size is specified.
128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (size_mb_ == 0)
129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_mb_ = os_->FindFreeMemSize() / kMegabyte;
130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = static_cast<int64>(size_mb_) * kMegabyte;
131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Autodetect file locations.
133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (findfiles_ && (file_threads_ == 0)) {
134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Get a space separated sting of disk locations.
135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    list<string> locations = os_->FindFileDevices();
136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Extract each one.
138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    while (!locations.empty()) {
139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Copy and remove the disk name.
140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      string disk = locations.back();
141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      locations.pop_back();
142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: disk at %s\n", disk.c_str());
144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      file_threads_++;
145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      filename_.push_back(disk + "/sat_disk.a");
146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      file_threads_++;
147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      filename_.push_back(disk + "/sat_disk.b");
148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We'd better have some memory by this point.
152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (size_ < 1) {
153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: No memory found to test.\n");
154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (tag_mode_ && ((file_threads_ > 0) ||
159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    (disk_threads_ > 0) ||
160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    (net_threads_ > 0))) {
161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Memory tag mode incompatible "
162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "with disk/network DMA.\n");
163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // If platform is 32 bit Xeon, floor memory size to multiple of 4.
168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (address_mode_ == 32) {
169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_mb_ = (size_mb_ / 4) * 4;
170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    size_ = size_mb_ * kMegabyte;
171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Log: Flooring memory allocation to multiple of 4: %lldMB\n",
172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              size_mb_);
173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check if this system is on the whitelist for supported systems.
176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_->IsSupported()) {
177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (run_on_anything_) {
178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(1, "Log: Unsupported system. Running with reduced coverage.\n");
179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // This is ok, continue on.
180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Unsupported system, "
182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                   "no error reporting available\n");
183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: Command line option '-A' bypasses this error.\n");
184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Allocates memory to run the test on
193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::AllocateMemory() {
194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate our test memory.
195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = os_->AllocateTestMem(size_, paddr_base_);
196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!result) {
197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to allocate memory\n");
198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Sets up access to data patterns
205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::InitializePatterns() {
206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize pattern data.
207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  patternlist_ = new PatternList();
208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!patternlist_) {
209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to allocate patterns\n");
210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!patternlist_->Initialize()) {
214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: failed to initialize patternlist\n");
215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get any valid page, no tag specified.
222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetValid(struct page_entry *pe) {
223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return GetValid(pe, kDontCareTag);
224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Fetch and return empty and full pages into the empty and full pools.
228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetValid(struct page_entry *pe, int32 tag) {
229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = false;
230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get valid page depending on implementation.
231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = finelock_q_->GetValid(pe, tag);
233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = valid_->PopRandom(pe);
235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (result) {
237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->addr = os_->PrepareTestMem(pe->offset, page_length_);  // Map it.
238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Tag this access and current pattern.
240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->ts = os_->GetTimestamp();
241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->lastpattern = pe->pattern;
242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (pe->addr != 0);     // Return success or failure.
244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PutValid(struct page_entry *pe) {
249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe->addr != 0)
250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->ReleaseTestMem(pe->addr, pe->offset, page_length_);  // Unmap the page.
251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe->addr = 0;
252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Put valid page depending on implementation.
254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return finelock_q_->PutValid(pe);
256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return valid_->Push(pe);
258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get an empty page with any tag.
263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetEmpty(struct page_entry *pe) {
264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return GetEmpty(pe, kDontCareTag);
265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::GetEmpty(struct page_entry *pe, int32 tag) {
268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = false;
269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get empty page depending on implementation.
270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = finelock_q_->GetEmpty(pe, tag);
272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = empty_->PopRandom(pe);
274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (result) {
276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe->addr = os_->PrepareTestMem(pe->offset, page_length_);  // Map it.
277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (pe->addr != 0);     // Return success or failure.
278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PutEmpty(struct page_entry *pe) {
283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe->addr != 0)
284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->ReleaseTestMem(pe->addr, pe->offset, page_length_);  // Unmap the page.
285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe->addr = 0;
286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Put empty page depending on implementation.
288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return finelock_q_->PutEmpty(pe);
290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else if (pe_q_implementation_ == SAT_ONELOCK)
291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return empty_->Push(pe);
292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Set up the bitmap of physical pages in case we want to see which pages were
297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// accessed under this run of SAT.
298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapInit() {
299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Find about how much physical mem is in the system.
302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // TODO(nsanders): Find some way to get the max
303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // and min phys addr in the system.
304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 maxsize = os_->FindFreeMemSize() * 4;
305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(maxsize != 0);
306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Make a bitmask of this many pages. Assume that the memory is relatively
308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // zero based. This is true on x86, typically.
309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This is one bit per page.
310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 arraysize = maxsize / 4096 / 8;
311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  unsigned char *bitmap = new unsigned char[arraysize];
312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(bitmap);
313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Mark every page as 0, not seen.
315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  memset(bitmap, 0, arraysize);
316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_size_ = maxsize;
318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_ = bitmap;
319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Add the 4k pages in this block to the array of pages SAT has seen.
322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapUpdate(struct page_entry *pe) {
323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Go through 4k page blocks.
327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 arraysize = page_bitmap_size_ / 4096 / 8;
328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  char *base = reinterpret_cast<char*>(pe->addr);
330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < page_length_; i += 4096) {
331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    uint64 paddr = os_->VirtualToPhysical(base + i);
332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    uint32 offset = paddr / 4096 / 8;
334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    unsigned char mask = 1 << ((paddr / 4096) % 8);
335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (offset >= arraysize) {
337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Physical address %#llx is "
338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                   "greater than expected %#llx.\n",
339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                paddr, page_bitmap_size_);
340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      sat_assert(0);
341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    page_bitmap_[offset] |= mask;
343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print out the physical memory ranges that SAT has accessed.
347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AddrMapPrint() {
348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!do_page_map_)
349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 pages = page_bitmap_size_ / 4096;
352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 last_page = 0;
354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool valid_range = false;
355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Log: Printing tested physical ranges.\n");
357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (uint64 i = 0; i < pages; i ++) {
359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int offset = i / 8;
360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    unsigned char mask = 1 << (i % 8);
361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bool touched = page_bitmap_[offset] & mask;
363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (touched && !valid_range) {
364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_range = true;
365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      last_page = i * 4096;
366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else if (!touched && valid_range) {
367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_range = false;
368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: %#016llx - %#016llx\n", last_page, (i * 4096) - 1);
369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Log: Done printing physical ranges.\n");
372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initializes page lists and fills pages with data patterns.
375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::InitializePages() {
376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int result = 1;
377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate needed page totals.
378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 neededpages = memory_threads_ +
379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_threads_ +
380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_threads_ +
381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_threads_ +
382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_threads_;
383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Empty-valid page ratio is adjusted depending on queue implementation.
385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // since fine-grain-locked queue keeps both valid and empty entries in the
386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // same queue and randomly traverse to find pages, the empty-valid ratio
387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // should be more even.
388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK)
389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    freepages_ = pages_ / 5 * 2;  // Mark roughly 2/5 of all pages as Empty.
390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  else
391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    freepages_ = (pages_ / 100) + (2 * neededpages);
392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (freepages_ < neededpages) {
394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: freepages < neededpages.\n");
395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Stats: Total: %lld, Needed: %lld, Marked free: %lld\n",
396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_),
397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(neededpages),
398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(freepages_));
399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (freepages_ >  pages_/2) {
404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: not enough pages for IO\n");
405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(1, "Stats: Total: %lld, Needed: %lld, Available: %lld\n",
406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_),
407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(freepages_),
408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              static_cast<int64>(pages_/2));
409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Allocating pages, Total: %lld Free: %lld\n",
413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            pages_,
414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            freepages_);
415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize page locations.
417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int64 i = 0; i < pages_; i++) {
418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    struct page_entry pe;
419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    init_pe(&pe);
420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    pe.offset = i * page_length_;
421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result &= PutEmpty(&pe);
422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!result) {
425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: while initializing empty_ list\n");
426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fill valid pages with test patterns.
431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Use fill threads to do this.
432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus fill_status;
433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector fill_vector;
434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Starting Fill threads: %d threads, %d pages\n",
436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            fill_threads_, pages_);
437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize the fill threads.
438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < fill_threads_; i++) {
439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    FillThread *thread = new FillThread();
440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(i, this, os_, patternlist_, &fill_status);
441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i != fill_threads_ - 1) {
442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(12, "Starting Fill Threads %d: %d pages\n",
443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  i, pages_ / fill_threads_);
444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->SetFillPages(pages_ / fill_threads_);
445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // The last thread finishes up all the leftover pages.
446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Starting Fill Threads %d: %d pages\n",
448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                i, pages_ - pages_ / fill_threads_ * i);
449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->SetFillPages(pages_ - pages_ / fill_threads_ * i);
450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    fill_vector.push_back(thread);
452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn the fill threads.
455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_status.Initialize();
456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = fill_vector.begin();
457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != fill_vector.end(); ++it)
458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->SpawnThread();
459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Reap the finished fill threads.
461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = fill_vector.begin();
462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != fill_vector.end(); ++it) {
463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->JoinThread();
464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetStatus() != 1) {
465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Thread %d failed with status %d at %.2f seconds\n",
466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetStatus(),
467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->GetRunDurationUSec() * 1.0/1000000);
468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete (*it);
472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_vector.clear();
474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_status.Destroy();
475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Done filling pages.\n");
476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Allocating pages.\n");
477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AddrMapInit();
479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize page locations.
481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int64 i = 0; i < pages_; i++) {
482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    struct page_entry pe;
483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Only get valid pages with uninitialized tags here.
484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    char buf[256];
485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (GetValid(&pe, kInvalidTag)) {
486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int64 paddr = os_->VirtualToPhysical(pe.addr);
487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int32 region = os_->FindRegion(paddr);
488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      os_->FindDimm(paddr, buf, sizeof(buf));
490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < 256) {
491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(12, "Log: address: %#llx, %s\n", paddr, buf);
492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_[region]++;
494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      pe.paddr = paddr;
495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      pe.tag = 1 << region;
496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_mask_ |= pe.tag;
497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Generate a physical region map
499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      AddrMapUpdate(&pe);
500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Note: this does not allocate free pages among all regions
502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // fairly. However, with large enough (thousands) random number
503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // of pages being marked free in each region, the free pages
504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // count in each region end up pretty balanced.
505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < freepages_) {
506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        result &= PutEmpty(&pe);
507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else {
508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        result &= PutValid(&pe);
509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: didn't tag all pages. %d - %d = %d\n",
512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                pages_, i, pages_ - i);
513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      return false;
514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Done allocating pages.\n");
517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AddrMapPrint();
519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < 32; i++) {
521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (region_mask_ & (1 << i)) {
522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      region_count_++;
523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Region %d: %d.\n", i, region_[i]);
524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: Region mask: 0x%x\n", region_mask_);
527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print SAT version info.
532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PrintVersion() {
533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(1, "Stats: SAT revision %s, %d bit binary\n",
534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            kVersion, address_mode_);
535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: %s from %s\n", Timestamp(), BuildChangelist());
536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Initializes the resources that SAT needs to run.
542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This needs to be called before Run(), and after ParseArgs().
543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns true on success, false on error, and will exit() on help message.
544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Initialize() {
545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  g_sat = this;
546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initializes sync'd log file to ensure output is saved.
548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializeLogfile())
549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->StartThread();
551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Log: Commandline - %s\n", cmdline_.c_str());
553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  PrintVersion();
554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  std::map<std::string, std::string> options;
556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  GoogleOsOptions(&options);
558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize OS/Hardware interface.
560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  os_ = OsLayerFactory(options);
561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_) {
562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (min_hugepages_mbytes_ > 0)
567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->SetMinimumHugepagesSize(min_hugepages_mbytes_ * kMegabyte);
568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!os_->Initialize()) {
570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Failed to initialize OS layer\n");
571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    bad_status();
572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete os_;
573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Checks that OS/Build/Platform is supported.
577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!CheckEnvironment())
578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (error_injection_)
581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->set_error_injection(true);
582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Run SAT in monitor only mode, do not continue to allocate resources.
584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (monitor_mode_) {
585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(5, "Log: Running in monitor-only mode. "
586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "Will not allocate any memory nor run any stress test. "
587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                 "Only polling ECC errors.\n");
588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return true;
589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate the memory to test.
592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!AllocateMemory())
593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(5, "Stats: Starting SAT, %dM, %d seconds\n",
596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            static_cast<int>(size_/kMegabyte),
597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            runtime_seconds_);
598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializePatterns())
600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize memory allocation.
603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pages_ = size_ / page_length_;
604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Allocate page queue depending on queue implementation switch.
606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (pe_q_implementation_ == SAT_FINELOCK) {
607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      finelock_q_ = new FineLockPEQueue(pages_, page_length_);
608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (finelock_q_ == NULL)
609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        return false;
610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      finelock_q_->set_os(os_);
611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      os_->set_err_log_callback(finelock_q_->get_err_log_callback());
612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else if (pe_q_implementation_ == SAT_ONELOCK) {
613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      empty_ = new PageEntryQueue(pages_);
614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      valid_ = new PageEntryQueue(pages_);
615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((empty_ == NULL) || (valid_ == NULL))
616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        return false;
617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!InitializePages()) {
620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(0, "Process Error: Initialize Pages failed\n");
621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Constructor and destructor.
628b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonSat::Sat() {
629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set defaults, command line might override these.
630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  runtime_seconds_ = 20;
631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_length_ = kSatPageSize;
632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  disk_pages_ = kSatDiskPage;
633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pages_ = 0;
634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_mb_ = 0;
635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = size_mb_ * kMegabyte;
636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  min_hugepages_mbytes_ = 0;
637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  freepages_ = 0;
638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  paddr_base_ = 0;
639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  user_break_ = false;
641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  verbosity_ = 8;
642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetVerbosity(verbosity_);
643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  strict_ = 1;
644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  warm_ = 0;
645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  run_on_anything_ = 0;
646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  use_logfile_ = 0;
647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logfile_ = 0;
648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Detect 32/64 bit binary.
649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void *pvoid = 0;
650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  address_mode_ = sizeof(pvoid) * 8;
651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  error_injection_ = false;
652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  crazy_error_injection_ = false;
653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  max_errorcount_ = 0;  // Zero means no early exit.
654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  stop_on_error_ = false;
655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  error_poll_ = true;
656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  findfiles_ = false;
657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  do_page_map_ = false;
659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_ = 0;
660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  page_bitmap_size_ = 0;
661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Cache coherency data initialization.
663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_test_ = false;         // Flag to trigger cc threads.
664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_cacheline_count_ = 2;  // Two datastructures of cache line size.
665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_inc_count_ = 1000;     // Number of times to increment the shared variable.
666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_cacheline_data_ = 0;   // Cache Line size datastructure.
667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_init(&worker_lock_, NULL));
669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  file_threads_ = 0;
670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  net_threads_ = 0;
671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  listen_threads_ = 0;
672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Default to autodetect number of cpus, and run that many threads.
673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  memory_threads_ = -1;
674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  invert_threads_ = 0;
675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  fill_threads_ = 8;
676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  check_threads_ = 0;
677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cpu_stress_threads_ = 0;
678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  disk_threads_ = 0;
679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  total_threads_ = 0;
680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_mask_ = 0;
682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_count_ = 0;
683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < 32; i++) {
684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    region_[i] = 0;
685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  region_mode_ = 0;
687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  errorcount_ = 0;
689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  statuscount_ = 0;
690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  valid_ = 0;
692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  empty_ = 0;
693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  finelock_q_ = 0;
694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Default to use fine-grain lock for better performance.
695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pe_q_implementation_ = SAT_FINELOCK;
696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  os_ = 0;
698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  patternlist_ = 0;
699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logfilename_[0] = 0;
700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  read_block_size_ = 512;
702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  write_block_size_ = -1;
703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  segment_size_ = -1;
704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cache_size_ = -1;
705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  blocks_per_segment_ = -1;
706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  read_threshold_ = -1;
707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  write_threshold_ = -1;
708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  non_destructive_ = 1;
709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  monitor_mode_ = 0;
710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  tag_mode_ = 0;
711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  random_threads_ = 0;
712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pause_delay_ = 600;
714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pause_duration_ = 15;
715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Destructor.
718b0114cb9f332db144f65291211ae65f7f0e814e6Scott AndersonSat::~Sat() {
719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We need to have called Cleanup() at this point.
720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // We should probably enforce this.
721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_KVALUE(argument, variable, value)         \
725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                   \
726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    variable = value;                                 \
727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                         \
728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_IVALUE(argument, variable)                \
731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                   \
732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    i++;                                              \
733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i < argc)                                     \
734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      variable = strtoull(argv[i], NULL, 0);          \
735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                         \
736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define ARG_SVALUE(argument, variable)                     \
739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!strcmp(argv[i], argument)) {                        \
740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    i++;                                                   \
741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i < argc)                                          \
742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      snprintf(variable, sizeof(variable), "%s", argv[i]); \
743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    continue;                                              \
744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Configures SAT from command line arguments.
747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This will call exit() given a request for
748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// self-documentation or unexpected args.
749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::ParseArgs(int argc, char **argv) {
750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int i;
751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  uint64 filesize = page_length_ * disk_pages_;
752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Parse each argument.
754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (i = 1; i < argc; i++) {
755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Switch to fall back to corase-grain-lock queue. (for benchmarking)
756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--coarse_grain_lock", pe_q_implementation_, SAT_ONELOCK);
757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of megabyte to use.
759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-M", size_mb_);
760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set minimum megabytes of hugepages to require.
762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-H", min_hugepages_mbytes_);
763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of seconds to run.
765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-s", runtime_seconds_);
766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of memory copy threads.
768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-m", memory_threads_);
769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of memory invert threads.
771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-i", invert_threads_);
772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of check-only threads.
774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-c", check_threads_);
775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of cache line size datastructures.
777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cc_inc_count", cc_inc_count_);
778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of cache line size datastructures
780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cc_line_count", cc_cacheline_count_);
781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Flag set when cache coherency tests need to be run
783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--cc_test", cc_test_, 1);
784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of CPU stress threads.
786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-C", cpu_stress_threads_);
787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set logfile name.
789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_SVALUE("-l", logfilename_);
790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Verbosity level.
792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-v", verbosity_);
793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set maximum number of errors to collect. Stop running after this many.
795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--max_errors", max_errorcount_);
796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set pattern block size.
798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("-p", page_length_);
799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set pattern block size.
801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--filesize", filesize);
802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // NUMA options.
804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--local_numa", region_mode_, kLocalNuma);
805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--remote_numa", region_mode_, kRemoteNuma);
806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Autodetect tempfile locations.
808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--findfiles", findfiles_, 1);
809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Inject errors to force miscompare code paths
811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--force_errors", error_injection_, true);
812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--force_errors_like_crazy", crazy_error_injection_, true);
813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (crazy_error_injection_)
814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      error_injection_ = true;
815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Stop immediately on any arror, for debugging HW problems.
817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--stop_on_errors", stop_on_error_, 1);
818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Don't use internal error polling, allow external detection.
820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--no_errors", error_poll_, 0);
821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Never check data as you go.
823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-F", strict_, 0);
824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Warm the cpu as you go.
826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-W", warm_, 1);
827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allow runnign on unknown systems with base unimplemented OsLayer
829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("-A", run_on_anything_, 1);
830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of read blocks for disk test.
832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--read-block-size", read_block_size_);
833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of write blocks for disk test.
835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--write-block-size", write_block_size_);
836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of segment for disk test.
838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--segment-size", segment_size_);
839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Size of disk cache size for disk test.
841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--cache-size", cache_size_);
842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Number of blocks to test per segment.
844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--blocks-per-segment", blocks_per_segment_);
845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Maximum time a block read should take before warning.
847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--read-threshold", read_threshold_);
848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Maximum time a block write should take before warning.
850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--write-threshold", write_threshold_);
851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Do not write anything to disk in the disk test.
853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--destructive", non_destructive_, 0);
854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run SAT in monitor mode. No test load at all.
856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--monitor_mode", monitor_mode_, true);
857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run SAT in address mode. Tag all cachelines by virt addr.
859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--tag_mode", tag_mode_, true);
860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Dump range map of tested pages..
862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--do_page_map", do_page_map_, true);
863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the physical address base to test.
865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--paddr_base", paddr_base_);
866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the frequency for power spikes.
868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--pause_delay", pause_delay_);
869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Specify the duration of each pause (for power spikes).
871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--pause_duration", pause_duration_);
872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Disk device names
874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-d")) {
875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        disk_threads_++;
878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        diskfilename_.push_back(string(argv[i]));
879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        blocktables_.push_back(new DiskBlockTable());
880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set number of disk random threads for each disk write thread.
885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_IVALUE("--random-threads", random_threads_);
886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set a tempfile to use in a file thread.
888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-f")) {
889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
891b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        file_threads_++;
892b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        filename_.push_back(string(argv[i]));
893b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
894b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
895b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
896b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
897b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set a hostname to use in a network thread.
898b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (!strcmp(argv[i], "-n")) {
899b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      i++;
900b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (i < argc) {
901b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        net_threads_++;
902b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        ipaddrs_.push_back(string(argv[i]));
903b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
904b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
905b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
906b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
907b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Run threads that listen for incoming SAT net connections.
908b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ARG_KVALUE("--listen", listen_threads_, 1);
909b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
910b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (CheckGoogleSpecificArgs(argc, argv, &i)) {
911b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      continue;
912b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
913b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
914b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Default:
915b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    PrintVersion();
916b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    PrintHelp();
917b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (strcmp(argv[i], "-h") && strcmp(argv[i], "--help")) {
918b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      printf("\n Unknown argument %s\n", argv[i]);
919b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
920b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      exit(1);
921b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
922b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Forget it, we printed the help, just bail.
923b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // We don't want to print test status, or any log parser stuff.
924b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    exit(0);
925b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
926b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
927b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetVerbosity(verbosity_);
928b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
929b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Update relevant data members with parsed input.
930b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Translate MB into bytes.
931b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  size_ = static_cast<int64>(size_mb_) * kMegabyte;
932b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
933b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set logfile flag.
934b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (strcmp(logfilename_, ""))
935b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    use_logfile_ = 1;
936b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Checks valid page length.
937b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (page_length_ &&
938b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      !(page_length_ & (page_length_ - 1)) &&
939b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (page_length_ > 1023)) {
940b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Prints if we have changed from default.
941b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (page_length_ != kSatPageSize)
942b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Updating page size to %d\n", page_length_);
943b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
944b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Revert to default page length.
945b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(6, "Process Error: "
946b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              "Invalid page size %d\n", page_length_);
947b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    page_length_ = kSatPageSize;
948b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return false;
949b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
950b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
951b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set disk_pages_ if filesize or page size changed.
952b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (filesize != static_cast<uint64>(page_length_) *
953b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  static_cast<uint64>(disk_pages_)) {
954b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_pages_ = filesize / page_length_;
955b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (disk_pages_ == 0)
956b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      disk_pages_ = 1;
957b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
958b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
959b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Print each argument.
960b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < argc; i++) {
961b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (i)
962b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cmdline_ += " ";
963b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cmdline_ += argv[i];
964b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
965b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
966b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
967b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
968b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
969b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::PrintHelp() {
970b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  printf("Usage: ./sat(32|64) [options]\n"
971b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -M mbytes        megabytes of ram to test\n"
972b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -H mbytes        minimum megabytes of hugepages to require\n"
973b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -s seconds       number of seconds to run\n"
974b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -m threads       number of memory copy threads to run\n"
975b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -i threads       number of memory invert threads to run\n"
976b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -C threads       number of memory CPU stress threads to run\n"
977b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --findfiles      find locations to do disk IO automatically\n"
978b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -d device        add a direct write disk thread with block "
979b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "device (or file) 'device'\n"
980b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -f filename      add a disk thread with "
981b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "tempfile 'filename'\n"
982b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -l logfile       log output to file 'logfile'\n"
983b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --max_errors n   exit early after finding 'n' errors\n"
984b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -v level         verbosity (0-20), default is 8\n"
985b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -W               Use more CPU-stressful memory copy\n"
986b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -A               run in degraded mode on incompatible systems\n"
987b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -p pagesize      size in bytes of memory chunks\n"
988b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --filesize size  size of disk IO tempfiles\n"
989b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -n ipaddr        add a network thread connecting to "
990b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "system at 'ipaddr'\n"
991b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --listen         run a thread to listen for and respond "
992b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to network threads.\n"
993b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --no_errors      run without checking for ECC or other errors\n"
994b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --force_errors   inject false errors to test error handling\n"
995b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --force_errors_like_crazy   inject a lot of false errors "
996b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to test error handling\n"
997b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " -F               don't result check each transaction\n"
998b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --stop_on_errors  Stop after finding the first error.\n"
999b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --read-block-size     size of block for reading (-d)\n"
1000b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --write-block-size    size of block for writing (-d). If not "
1001b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "defined, the size of block for writing will be defined as the "
1002b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "size of block for reading\n"
1003b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --segment-size   size of segments to split disk into (-d)\n"
1004b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cache-size     size of disk cache (-d)\n"
1005b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --blocks-per-segment  number of blocks to read/write per "
1006b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "segment per iteration (-d)\n"
1007b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --read-threshold      maximum time (in us) a block read should "
1008b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "take (-d)\n"
1009b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --write-threshold     maximum time (in us) a block write "
1010b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "should take (-d)\n"
1011b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --random-threads      number of random threads for each disk "
1012b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "write thread (-d)\n"
1013b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --destructive    write/wipe disk partition (-d)\n"
1014b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --monitor_mode   only do ECC error polling, no stress load.\n"
1015b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_test        do the cache coherency testing\n"
1016b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_inc_count   number of times to increment the "
1017b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "cacheline's member\n"
1018b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --cc_line_count  number of cache line sized datastructures "
1019b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "to allocate for the cache coherency threads to operate\n"
1020b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --paddr_base     allocate memory starting from this address\n"
1021b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --pause_delay    delay (in seconds) between power spikes\n"
1022b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --pause_duration duration (in seconds) of each pause\n"
1023b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --local_numa : choose memory regions associated with "
1024b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "each CPU to be tested by that CPU\n"
1025b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         " --remote_numa : choose memory regions not associated with "
1026b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         "each CPU to be tested by that CPU\n");
1027b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1028b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1029b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::CheckGoogleSpecificArgs(int argc, char **argv, int *i) {
1030b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, no google-specific argument on public stressapptest
1031b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return false;
1032b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1033b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1034b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::GoogleOsOptions(std::map<std::string, std::string> *options) {
1035b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, no OS-specific argument on public stressapptest
1036b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1037b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1038b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Launch the SAT task threads. Returns 0 on error.
1039b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::InitializeThreads() {
1040b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Memory copy threads.
1041b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1042b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1043b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting worker threads\n");
1044b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *memory_vector = new WorkerVector();
1045b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1046b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Error polling thread.
1047b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This may detect ECC corrected errors, disk problems, or
1048b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // any other errors normally hidden from userspace.
1049b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *error_vector = new WorkerVector();
1050b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (error_poll_) {
1051b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ErrorPollThread *thread = new ErrorPollThread();
1052b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1053b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1054b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1055b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    error_vector->insert(error_vector->end(), thread);
1056b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1057b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(5, "Log: Skipping error poll thread due to --no_errors flag\n");
1058b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1059b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kErrorType, error_vector));
1060b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1061b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Only start error poll threads for monitor-mode SAT,
1062b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // skip all other types of worker threads.
1063b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (monitor_mode_) {
1064b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ReleaseWorkerLock();
1065b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return;
1066b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1067b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1068b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < memory_threads_; i++) {
1069b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CopyThread *thread = new CopyThread();
1070b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1071b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1072b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1073b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((region_count_ > 1) && (region_mode_)) {
1074b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int32 region = region_find(i % region_count_);
1075b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpu_set_t *cpuset = os_->FindCoreMask(region);
1076b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      sat_assert(cpuset);
1077b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (region_mode_ == kLocalNuma) {
1078b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Choose regions associated with this CPU.
1079b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask(cpuset);
1080b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_tag(1 << region);
1081b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else if (region_mode_ == kRemoteNuma) {
1082b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Choose regions not associated with this CPU..
1083b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask(cpuset);
1084b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_tag(region_mask_ & ~(1 << region));
1085b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1086b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
1087b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cpu_set_t available_cpus;
1088b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->AvailableCpus(&available_cpus);
1089b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int cores = cpuset_count(&available_cpus);
1090b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Don't restrict thread location if we have more than one
1091b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // thread per core. Not so good for performance.
1092b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (cpu_stress_threads_ + memory_threads_ <= cores) {
1093b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Place a thread on alternating cores first.
1094b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // This assures interleaved core use with no overlap.
1095b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        int nthcore = i;
1096b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        int nthbit = (((2 * nthcore) % cores) +
1097b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                      (((2 * nthcore) / cores) % 2)) % cores;
1098b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        cpu_set_t all_cores;
1099b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        cpuset_set_ab(&all_cores, 0, cores);
1100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        if (!cpuset_isequal(&available_cpus, &all_cores)) {
1101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          // We are assuming the bits are contiguous.
1102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          // Complain if this is not so.
1103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          logprintf(0, "Log: cores = %s, expected %s\n",
1104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    cpuset_format(&available_cpus).c_str(),
1105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    cpuset_format(&all_cores).c_str());
1106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        }
1107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        // Set thread affinity.
1109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        thread->set_cpu_mask_to_cpu(nthbit);
1110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memory_vector->insert(memory_vector->end(), thread);
1113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kMemoryType, memory_vector));
1115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // File IO threads.
1117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *fileio_vector = new WorkerVector();
1118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < file_threads_; i++) {
1119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    FileThread *thread = new FileThread();
1120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetFile(filename_[i].c_str());
1123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Set disk threads high priority. They don't take much processor time,
1124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // but blocking them will delay disk IO.
1125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetPriority(WorkerThread::High);
1126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    fileio_vector->insert(fileio_vector->end(), thread);
1128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kFileIOType, fileio_vector));
1130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Net IO threads.
1132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *netio_vector = new WorkerVector();
1133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *netslave_vector = new WorkerVector();
1134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (listen_threads_ > 0) {
1135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Create a network slave thread. This listens for connections.
1136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    NetworkListenThread *thread = new NetworkListenThread();
1137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    netslave_vector->insert(netslave_vector->end(), thread);
1141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < net_threads_; i++) {
1143b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    NetworkThread *thread = new NetworkThread();
1144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetIP(ipaddrs_[i].c_str());
1147b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    netio_vector->insert(netio_vector->end(), thread);
1149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kNetIOType, netio_vector));
1151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kNetSlaveType, netslave_vector));
1152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Result check threads.
1154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *check_vector = new WorkerVector();
1155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < check_threads_; i++) {
1156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CheckThread *thread = new CheckThread();
1157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_vector->insert(check_vector->end(), thread);
1161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kCheckType, check_vector));
1163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Memory invert threads.
1165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting invert threads\n");
1166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *invert_vector = new WorkerVector();
1167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < invert_threads_; i++) {
1168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    InvertThread *thread = new InvertThread();
1169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_vector->insert(invert_vector->end(), thread);
1173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kInvertType, invert_vector));
1175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Disk stress threads.
1177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *disk_vector = new WorkerVector();
1178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *random_vector = new WorkerVector();
1179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting disk stress threads\n");
1180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < disk_threads_; i++) {
1181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Creating write threads
1182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    DiskThread *thread = new DiskThread(blocktables_[i]);
1183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &power_spike_status_);
1185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->SetDevice(diskfilename_[i].c_str());
1186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (thread->SetParameters(read_block_size_, write_block_size_,
1187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              segment_size_, cache_size_,
1188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              blocks_per_segment_,
1189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              read_threshold_, write_threshold_,
1190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              non_destructive_)) {
1191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      disk_vector->insert(disk_vector->end(), thread);
1192b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    } else {
1193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: DiskThread::SetParameters() failed\n");
1194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      delete thread;
1195b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (int j = 0; j < random_threads_; j++) {
1198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Creating random threads
1199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      RandomDiskThread *rthread = new RandomDiskThread(blocktables_[i]);
1200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      rthread->InitThread(total_threads_++, this, os_, patternlist_,
1201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          &power_spike_status_);
1202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      rthread->SetDevice(diskfilename_[i].c_str());
1203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (rthread->SetParameters(read_block_size_, write_block_size_,
1204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 segment_size_, cache_size_,
1205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 blocks_per_segment_,
1206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 read_threshold_, write_threshold_,
1207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 non_destructive_)) {
1208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        random_vector->insert(random_vector->end(), rthread);
1209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      } else {
1210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: RandomDiskThread::SetParameters() failed\n");
1211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        delete rthread;
1212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kDiskType, disk_vector));
1217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kRandomDiskType, random_vector));
1218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // CPU stress threads.
1220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector *cpu_vector = new WorkerVector();
1221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting cpu stress threads\n");
1222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (int i = 0; i < cpu_stress_threads_; i++) {
1223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CpuStressThread *thread = new CpuStressThread();
1224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->InitThread(total_threads_++, this, os_, patternlist_,
1225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       &continuous_status_);
1226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Don't restrict thread location if we have more than one
1228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // thread per core. Not so good for performance.
1229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpu_set_t available_cpus;
1230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    thread->AvailableCpus(&available_cpus);
1231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int cores = cpuset_count(&available_cpus);
1232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (cpu_stress_threads_ + memory_threads_ <= cores) {
1233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Place a thread on alternating cores first.
1234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Go in reverse order for CPU stress threads. This assures interleaved
1235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // core use with no overlap.
1236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int nthcore = (cores - 1) - 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        logprintf(0, "Log: cores = %s, expected %s\n",
1243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  cpuset_format(&available_cpus).c_str(),
1244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  cpuset_format(&all_cores).c_str());
1245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Set thread affinity.
1248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->set_cpu_mask_to_cpu(nthbit);
1249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpu_vector->insert(cpu_vector->end(), thread);
1253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.insert(make_pair(kCPUType, cpu_vector));
1255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // CPU Cache Coherency Threads - one for each core available.
1257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (cc_test_) {
1258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    WorkerVector *cc_vector = new WorkerVector();
1259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Starting cpu cache coherency threads\n");
1260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allocate the shared datastructure to be worked on by the threads.
1262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cc_cacheline_data_ = reinterpret_cast<cc_cacheline_data*>(
1263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        malloc(sizeof(cc_cacheline_data) * cc_cacheline_count_));
1264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(cc_cacheline_data_ != NULL);
1265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Initialize the strucutre.
1267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memset(cc_cacheline_data_, 0,
1268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson           sizeof(cc_cacheline_data) * cc_cacheline_count_);
1269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int num_cpus = CpuCount();
1271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Allocate all the nums once so that we get a single chunk
1272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // of contiguous memory.
1273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int *num;
1274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int err_result = posix_memalign(
1275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        reinterpret_cast<void**>(&num),
1276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        kCacheLineSize, sizeof(*num) * num_cpus * cc_cacheline_count_);
1277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(err_result == 0);
1278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int cline;
1280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (cline = 0; cline < cc_cacheline_count_; cline++) {
1281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      memset(num, 0, sizeof(num_cpus) * num_cpus);
1282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cc_cacheline_data_[cline].num = num;
1283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      num += num_cpus;
1284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int tnum;
1287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (tnum = 0; tnum < num_cpus; tnum++) {
1288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      CpuCacheCoherencyThread *thread =
1289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson          new CpuCacheCoherencyThread(cc_cacheline_data_, cc_cacheline_count_,
1290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                      tnum, cc_inc_count_);
1291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->InitThread(total_threads_++, this, os_, patternlist_,
1292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                         &continuous_status_);
1293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Pin the thread to a particular core.
1294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->set_cpu_mask_to_cpu(tnum);
1295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Insert the thread into the vector.
1297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      cc_vector->insert(cc_vector->end(), thread);
1298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    workers_map_.insert(make_pair(kCCType, cc_vector));
1300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Return the number of cpus actually present in the machine.
1305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint Sat::CpuCount() {
1306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return sysconf(_SC_NPROCESSORS_CONF);
1307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Notify and reap worker threads.
1310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::JoinThreads() {
1311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Joining worker threads\n");
1312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.StopWorkers();
1313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.StopWorkers();
1314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
1321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (*it)->JoinThread();
1322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  QueueStats();
1327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Finish up result checking.
1329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn 4 check threads to minimize check time.
1330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Finished countdown, begin to result check\n");
1331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus reap_check_status;
1332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerVector reap_check_vector;
1333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // No need for check threads for monitor mode.
1335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!monitor_mode_) {
1336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // Initialize the check threads.
1337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (int i = 0; i < fill_threads_; i++) {
1338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      CheckThread *thread = new CheckThread();
1339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread->InitThread(total_threads_++, this, os_, patternlist_,
1340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                         &reap_check_status);
1341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Finished countdown, begin to result check\n");
1342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      reap_check_vector.push_back(thread);
1343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.Initialize();
1347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Check threads should be marked to stop ASAP.
1348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.StopWorkers();
1349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn the check threads.
1351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
1354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->SpawnThread();
1355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Join the check threads.
1358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Joining thread %d\n", (*it)->ThreadID());
1361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    (*it)->JoinThread();
1362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Reap all children. Stopped threads should have already ended.
1365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Result checking threads will end when they have finished
1366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // result checking.
1367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Join all outstanding threads\n");
1368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Find all errors.
1370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  errorcount_ = GetTotalErrorCount();
1371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
1378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((*it)->GetStatus() != 1) {
1379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(0, "Process Error: Thread %d failed with status %d at "
1380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  "%.2f seconds\n",
1381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  (*it)->ThreadID(), (*it)->GetStatus(),
1382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  (*it)->GetRunDurationUSec()*1.0/1000000);
1383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        bad_status();
1384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      int priority = 12;
1386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if ((*it)->GetErrorCount())
1387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        priority = 5;
1388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
1389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetErrorCount());
1390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Add in any errors from check threads.
1396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = reap_check_vector.begin();
1397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != reap_check_vector.end(); ++it) {
1398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(12, "Log: Reaping thread status %d\n", (*it)->ThreadID());
1399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetStatus() != 1) {
1400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Process Error: Thread %d failed with status %d at "
1401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "%.2f seconds\n",
1402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->ThreadID(), (*it)->GetStatus(),
1403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                (*it)->GetRunDurationUSec()*1.0/1000000);
1404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      bad_status();
1405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    errorcount_ += (*it)->GetErrorCount();
1407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int priority = 12;
1408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if ((*it)->GetErrorCount())
1409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      priority = 5;
1410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(priority, "Log: Thread %d found %lld hardware incidents\n",
1411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson              (*it)->ThreadID(), (*it)->GetErrorCount());
1412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete (*it);
1413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_vector.clear();
1415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  reap_check_status.Destroy();
1416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Print queuing information.
1419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::QueueStats() {
1420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  finelock_q_->QueueAnalysis();
1421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AnalysisAllStats() {
1424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float max_runtime_sec = 0.;
1425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float total_data = 0.;
1426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float total_bandwidth = 0.;
1427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float thread_runtime_sec = 0.;
1428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      thread_runtime_sec = (*it)->GetRunDurationUSec()*1.0/1000000;
1434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      total_data += (*it)->GetMemoryCopiedData();
1435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      total_data += (*it)->GetDeviceCopiedData();
1436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (thread_runtime_sec > max_runtime_sec) {
1437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        max_runtime_sec = thread_runtime_sec;
1438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  total_bandwidth = total_data / max_runtime_sec;
1443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(0, "Stats: Completed: %.2fM in %.2fs %.2fMB/s, "
1445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            "with %d hardware incidents, %d errors\n",
1446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            total_data,
1447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            max_runtime_sec,
1448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            total_bandwidth,
1449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            errorcount_,
1450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            statuscount_);
1451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::MemoryStats() {
1454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float memcopy_data = 0.;
1455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float memcopy_bandwidth = 0.;
1456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator mem_it = workers_map_.find(
1457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kMemoryType));
1458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator file_it = workers_map_.find(
1459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kFileIOType));
1460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(mem_it != workers_map_.end());
1461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(file_it != workers_map_.end());
1462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = mem_it->second->begin();
1463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != mem_it->second->end(); ++it) {
1464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_data += (*it)->GetMemoryCopiedData();
1465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_bandwidth += (*it)->GetMemoryBandwidth();
1466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = file_it->second->begin();
1468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != file_it->second->end(); ++it) {
1469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_data += (*it)->GetMemoryCopiedData();
1470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcopy_bandwidth += (*it)->GetMemoryBandwidth();
1471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  GoogleMemoryStats(&memcopy_data, &memcopy_bandwidth);
1473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Memory Copy: %.2fM at %.2fMB/s\n",
1474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            memcopy_data,
1475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            memcopy_bandwidth);
1476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::GoogleMemoryStats(float *memcopy_data,
1479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            float *memcopy_bandwidth) {
1480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do nothing, should be implemented by subclasses.
1481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::FileStats() {
1484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float file_data = 0.;
1485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float file_bandwidth = 0.;
1486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator file_it = workers_map_.find(
1487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kFileIOType));
1488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(file_it != workers_map_.end());
1489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = file_it->second->begin();
1490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != file_it->second->end(); ++it) {
1491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_data += (*it)->GetDeviceCopiedData();
1492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    file_bandwidth += (*it)->GetDeviceBandwidth();
1493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: File Copy: %.2fM at %.2fMB/s\n",
1495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            file_data,
1496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            file_bandwidth);
1497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::CheckStats() {
1500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float check_data = 0.;
1501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float check_bandwidth = 0.;
1502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator check_it = workers_map_.find(
1503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kCheckType));
1504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(check_it != workers_map_.end());
1505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = check_it->second->begin();
1506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != check_it->second->end(); ++it) {
1507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_data += (*it)->GetMemoryCopiedData();
1508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    check_bandwidth += (*it)->GetMemoryBandwidth();
1509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Data Check: %.2fM at %.2fMB/s\n",
1511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            check_data,
1512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            check_bandwidth);
1513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::NetStats() {
1516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float net_data = 0.;
1517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float net_bandwidth = 0.;
1518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator netio_it = workers_map_.find(
1519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kNetIOType));
1520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator netslave_it = workers_map_.find(
1521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kNetSlaveType));
1522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(netio_it != workers_map_.end());
1523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(netslave_it != workers_map_.end());
1524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = netio_it->second->begin();
1525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != netio_it->second->end(); ++it) {
1526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_data += (*it)->GetDeviceCopiedData();
1527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_bandwidth += (*it)->GetDeviceBandwidth();
1528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = netslave_it->second->begin();
1530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != netslave_it->second->end(); ++it) {
1531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_data += (*it)->GetDeviceCopiedData();
1532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    net_bandwidth += (*it)->GetDeviceBandwidth();
1533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Net Copy: %.2fM at %.2fMB/s\n",
1535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            net_data,
1536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            net_bandwidth);
1537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::InvertStats() {
1540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float invert_data = 0.;
1541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float invert_bandwidth = 0.;
1542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator invert_it = workers_map_.find(
1543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kInvertType));
1544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(invert_it != workers_map_.end());
1545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = invert_it->second->begin();
1546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != invert_it->second->end(); ++it) {
1547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_data += (*it)->GetMemoryCopiedData();
1548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    invert_bandwidth += (*it)->GetMemoryBandwidth();
1549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Invert Data: %.2fM at %.2fMB/s\n",
1551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            invert_data,
1552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            invert_bandwidth);
1553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::DiskStats() {
1556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float disk_data = 0.;
1557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  float disk_bandwidth = 0.;
1558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator disk_it = workers_map_.find(
1559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kDiskType));
1560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerMap::const_iterator random_it = workers_map_.find(
1561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      static_cast<int>(kRandomDiskType));
1562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(disk_it != workers_map_.end());
1563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(random_it != workers_map_.end());
1564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = disk_it->second->begin();
1565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != disk_it->second->end(); ++it) {
1566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_data += (*it)->GetDeviceCopiedData();
1567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_bandwidth += (*it)->GetDeviceBandwidth();
1568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerVector::const_iterator it = random_it->second->begin();
1570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       it != random_it->second->end(); ++it) {
1571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_data += (*it)->GetDeviceCopiedData();
1572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    disk_bandwidth += (*it)->GetDeviceBandwidth();
1573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "Stats: Disk: %.2fM at %.2fMB/s\n",
1576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            disk_data,
1577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            disk_bandwidth);
1578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Process worker thread data for bandwidth information, and error results.
1581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// You can add more methods here just subclassing SAT.
1582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::RunAnalysis() {
1583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AnalysisAllStats();
1584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  MemoryStats();
1585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  FileStats();
1586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  NetStats();
1587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CheckStats();
1588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  InvertStats();
1589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DiskStats();
1590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Get total error count, summing across all threads..
1593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonint64 Sat::GetTotalErrorCount() {
1594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 errors = 0;
1595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  AcquireWorkerLock();
1597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      errors += (*it)->GetErrorCount();
1602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ReleaseWorkerLock();
1605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return errors;
1606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::SpawnThreads() {
1610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Initializing WorkerStatus objects\n");
1611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.Initialize();
1612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.Initialize();
1613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Spawning worker threads\n");
1614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Spawning thread %d\n", (*it)->ThreadID());
1619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (*it)->SpawnThread();
1620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Delete used worker thread objects.
1625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::DeleteThreads() {
1626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Deleting worker threads\n");
1627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (WorkerMap::const_iterator map_it = workers_map_.begin();
1628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson       map_it != workers_map_.end(); ++map_it) {
1629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    for (WorkerVector::const_iterator it = map_it->second->begin();
1630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson         it != map_it->second->end(); ++it) {
1631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Deleting thread %d\n", (*it)->ThreadID());
1632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      delete (*it);
1633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete map_it->second;
1635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  workers_map_.clear();
1637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Destroying WorkerStatus objects\n");
1638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  power_spike_status_.Destroy();
1639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  continuous_status_.Destroy();
1640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonnamespace {
1643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Calculates the next time an action in Sat::Run() should occur, based on a
1644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// schedule derived from a start point and a regular frequency.
1645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Using frequencies instead of intervals with their accompanying drift allows
1647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// users to better predict when the actions will occur throughout a run.
1648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Arguments:
1650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   frequency: seconds
1651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   start: unixtime
1652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//   now: unixtime
1653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
1654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Returns: unixtime
1655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersoninline time_t NextOccurance(time_t frequency, time_t start, time_t now) {
1656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return start + frequency + (((now - start) / frequency) * frequency);
1657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Run the actual test.
1661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Run() {
1662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Install signal handlers to gracefully exit in the middle of a run.
1663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Why go through this whole rigmarole?  It's the only standards-compliant
1665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // (C++ and POSIX) way to handle signals in a multithreaded program.
1666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Specifically:
1667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // 1) (C++) The value of a variable not of type "volatile sig_atomic_t" is
1669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    unspecified upon entering a signal handler and, if modified by the
1670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    handler, is unspecified after leaving the handler.
1671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // 2) (POSIX) After the value of a variable is changed in one thread, another
1673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    thread is only guaranteed to see the new value after both threads have
1674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    acquired or released the same mutex or rwlock, synchronized to the
1675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //    same barrier, or similar.
1676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
1677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // #1 prevents the use of #2 in a signal handler, so the signal handler must
1678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // be called in the same thread that reads the "volatile sig_atomic_t"
1679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // variable it sets.  We enforce that by blocking the signals in question in
1680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // the worker threads, forcing them to be handled by this thread.
1681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Installing signal handlers\n");
1682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigset_t new_blocked_signals;
1683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigemptyset(&new_blocked_signals);
1684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigaddset(&new_blocked_signals, SIGINT);
1685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigaddset(&new_blocked_signals, SIGTERM);
1686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sigset_t prev_blocked_signals;
1687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_sigmask(SIG_BLOCK, &new_blocked_signals, &prev_blocked_signals);
1688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sighandler_t prev_sigint_handler = signal(SIGINT, SatHandleBreak);
1689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sighandler_t prev_sigterm_handler = signal(SIGTERM, SatHandleBreak);
1690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Kick off all the worker threads.
1692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Launching worker threads\n");
1693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  InitializeThreads();
1694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  SpawnThreads();
1695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_sigmask(SIG_SETMASK, &prev_blocked_signals, NULL);
1696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Starting countdown with %d seconds\n", runtime_seconds_);
1698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // In seconds.
1700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const time_t kSleepFrequency = 5;
1701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // All of these are in seconds.  You probably want them to be >=
1702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // kSleepFrequency and multiples of kSleepFrequency, but neither is necessary.
1703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const time_t kInjectionFrequency = 10;
1704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const time_t kPrintFrequency = 10;
1705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  const time_t start = time(NULL);
1707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  const time_t end = start + runtime_seconds_;
1708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t now = start;
1709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_print = start + kPrintFrequency;
1710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_pause = start + pause_delay_;
1711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_resume = 0;
1712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  time_t next_injection;
1713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (crazy_error_injection_) {
1714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    next_injection = start + kInjectionFrequency;
1715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    next_injection = 0;
1717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  while (now < end) {
1720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // This is an int because it's for logprintf().
1721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    const int seconds_remaining = end - now;
1722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (user_break_) {
1724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Handle early exit.
1725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(0, "Log: User exiting early (%d seconds remaining)\n",
1726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                seconds_remaining);
1727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      break;
1728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // If we have an error limit, check it here and see if we should exit.
1731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (max_errorcount_ != 0) {
1732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      uint64 errors = GetTotalErrorCount();
1733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      if (errors > max_errorcount_) {
1734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        logprintf(0, "Log: Exiting early (%d seconds remaining) "
1735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                     "due to excessive failures (%lld)\n",
1736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  seconds_remaining,
1737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                  errors);
1738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        break;
1739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      }
1740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (now >= next_print) {
1743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Print a count down message.
1744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(5, "Log: Seconds remaining: %d\n", seconds_remaining);
1745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_print = NextOccurance(kPrintFrequency, start, now);
1746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_injection && now >= next_injection) {
1749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Inject an error.
1750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Injecting error (%d seconds remaining)\n",
1751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                seconds_remaining);
1752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      struct page_entry src;
1753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      GetValid(&src);
1754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      src.pattern = patternlist_->GetPattern(0);
1755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      PutValid(&src);
1756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_injection = NextOccurance(kInjectionFrequency, start, now);
1757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1758b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_pause && now >= next_pause) {
1760b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Tell worker threads to pause in preparation for a power spike.
1761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Pausing worker threads in preparation for power spike "
1762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "(%d seconds remaining)\n", seconds_remaining);
1763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      power_spike_status_.PauseWorkers();
1764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Worker threads paused\n");
1765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_pause = 0;
1766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_resume = now + pause_duration_;
1767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (next_resume && now >= next_resume) {
1770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      // Tell worker threads to resume in order to cause a power spike.
1771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(4, "Log: Resuming worker threads to cause a power spike (%d "
1772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                "seconds remaining)\n", seconds_remaining);
1773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      power_spike_status_.ResumeWorkers();
1774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      logprintf(12, "Log: Worker threads resumed\n");
1775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_pause = NextOccurance(pause_delay_, start, now);
1776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      next_resume = 0;
1777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_sleep(NextOccurance(kSleepFrequency, start, now) - now);
1780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    now = time(NULL);
1781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  JoinThreads();
1784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(0, "Stats: Found %lld hardware incidents\n", errorcount_);
1786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (!monitor_mode_)
1788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    RunAnalysis();
1789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DeleteThreads();
1791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(12, "Log: Uninstalling signal handlers\n");
1793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  signal(SIGINT, prev_sigint_handler);
1794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  signal(SIGTERM, prev_sigterm_handler);
1795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
1797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Clean up all resources.
1800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::Cleanup() {
1801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  g_sat = NULL;
1802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->StopThread();
1803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->SetStdoutOnly();
1804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (logfile_) {
1805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    close(logfile_);
1806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logfile_ = 0;
1807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (patternlist_) {
1809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    patternlist_->Destroy();
1810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete patternlist_;
1811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    patternlist_ = 0;
1812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1813b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (os_) {
1814b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_->FreeTestMem();
1815b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete os_;
1816b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    os_ = 0;
1817b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1818b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (empty_) {
1819b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete empty_;
1820b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    empty_ = 0;
1821b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1822b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (valid_) {
1823b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete valid_;
1824b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    valid_ = 0;
1825b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1826b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (finelock_q_) {
1827b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete finelock_q_;
1828b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    finelock_q_ = 0;
1829b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1830b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (page_bitmap_) {
1831b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete[] page_bitmap_;
1832b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1833b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1834b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  for (size_t i = 0; i < blocktables_.size(); i++) {
1835b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    delete blocktables_[i];
1836b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1837b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1838b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (cc_cacheline_data_) {
1839b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // The num integer arrays for all the cacheline structures are
1840b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // allocated as a single chunk. The pointers in the cacheline struct
1841b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // are populated accordingly. Hence calling free on the first
1842b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // cacheline's num's address is going to free the entire array.
1843b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // TODO(aganti): Refactor this to have a class for the cacheline
1844b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // structure (currently defined in worker.h) and clean this up
1845b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // in the destructor of that class.
1846b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (cc_cacheline_data_[0].num) {
1847b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      free(cc_cacheline_data_[0].num);
1848b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    }
1849b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    free(cc_cacheline_data_);
1850b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1851b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1852b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_destroy(&worker_lock_));
1853b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1854b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return true;
1855b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1856b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1857b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1858b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Pretty print really obvious results.
1859b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonbool Sat::PrintResults() {
1860b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool result = true;
1861b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1862b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "\n");
1863b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  if (statuscount_) {
1864b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: FAIL - test encountered procedural errors\n");
1865b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = false;
1866b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else if (errorcount_) {
1867b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: FAIL - test discovered HW problems\n");
1868b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    result = false;
1869b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  } else {
1870b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    logprintf(4, "Status: PASS - please verify no corrected errors\n");
1871b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
1872b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  logprintf(4, "\n");
1873b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1874b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  return result;
1875b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1876b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1877b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Helper functions.
1878b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::AcquireWorkerLock() {
1879b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_lock(&worker_lock_));
1880b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1881b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid Sat::ReleaseWorkerLock() {
1882b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  sat_assert(0 == pthread_mutex_unlock(&worker_lock_));
1883b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1884b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1885b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonvoid logprintf(int priority, const char *format, ...) {
1886b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_list args;
1887b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_start(args, format);
1888b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Logger::GlobalLogger()->VLogF(priority, format, args);
1889b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  va_end(args);
1890b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson}
1891