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