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