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// worker.h : worker thread interface
16b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
17b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file contains the Worker Thread class interface
18b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// for the SAT test. Worker Threads implement a repetative
19b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// task used to test or stress the system.
20b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
21b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#ifndef STRESSAPPTEST_WORKER_H_
22b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#define STRESSAPPTEST_WORKER_H_
23b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
24b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <pthread.h>
25b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
26b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/time.h>
27b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <sys/types.h>
28b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
298f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H
30b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <libaio.h>
318f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
32b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
33b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <queue>
34b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <set>
35b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <string>
36b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include <vector>
37b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
38b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This file must work with autoconf on its public version,
39b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// so these includes are correct.
40b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "disk_blocks.h"
41b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "queue.h"
42b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#include "sattypes.h"
43b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
44b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
45b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Global Datastruture shared by the Cache Coherency Worker Threads.
46b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonstruct cc_cacheline_data {
47b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int *num;
48b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
49b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
50b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Typical usage:
51b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// (Other workflows may be possible, see function comments for details.)
52b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread creates object.
53b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread calls AddWorkers(1) for each worker thread.
54b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread calls Initialize().
55b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread launches worker threads.
56b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Every worker thread frequently calls ContinueRunning().
57b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread periodically calls PauseWorkers(), effectively sleeps, and
58b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//     then calls ResumeWorkers().
59b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Some worker threads may exit early, before StopWorkers() is called.  They
60b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//     call RemoveSelf() after their last call to ContinueRunning().
61b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread eventually calls StopWorkers().
62b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Worker threads exit.
63b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread joins worker threads.
64b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread calls Destroy().
65b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - Control thread destroys object.
66b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
67b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Threadsafety:
68b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - ContinueRunning() may be called concurrently by different workers, but not
69b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//     by a single worker.
70b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - No other methods may ever be called concurrently, with themselves or
71b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//     eachother.
72b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// - This object may be used by multiple threads only between Initialize() and
73b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//     Destroy().
74b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson//
75b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// TODO(matthewb): Move this class and its unittest to their own files.
76b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass WorkerStatus {
77b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
78b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //--------------------------------
79b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Methods for the control thread.
80b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //--------------------------------
81b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
82b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus() : num_workers_(0), status_(RUN) {}
83b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
84b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread to increase the worker count.  Must be called
85b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // before Initialize().  The worker count is 0 upon object initialization.
86b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void AddWorkers(int num_new_workers) {
87b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    // No need to lock num_workers_mutex_ because this is before Initialize().
88b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    num_workers_ += num_new_workers;
89b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
90b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
91b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread.  May not be called multiple times.  If
92b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // called, Destroy() must be called before destruction.
93b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void Initialize();
94b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
95b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread after joining all worker threads.  Must be
96b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // called iff Initialize() was called.  No methods may be called after calling
97b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // this.
98b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void Destroy();
99b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
100b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread to tell the workers to pause.  Does not return
101b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // until all workers have called ContinueRunning() or RemoveSelf().  May only
102b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // be called between Initialize() and Stop().  Must not be called multiple
103b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // times without ResumeWorkers() having been called inbetween.
104b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void PauseWorkers();
105b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
106b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread to tell the workers to resume from a pause.
107b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // May only be called between Initialize() and Stop().  May only be called
108b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // directly after PauseWorkers().
109b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void ResumeWorkers();
110b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
111b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by the control thread to tell the workers to stop.  May only be
112b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // called between Initialize() and Destroy().  May only be called once.
113b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void StopWorkers();
114b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
115b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //--------------------------------
116b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Methods for the worker threads.
117b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //--------------------------------
118b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
119b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by worker threads to decrease the worker count by one.  May only be
120b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // called between Initialize() and Destroy().  May wait for ResumeWorkers()
121b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // when called after PauseWorkers().
122b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void RemoveSelf();
123b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
124b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Called by worker threads between Initialize() and Destroy().  May be called
125b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // any number of times.  Return value is whether or not the worker should
126b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // continue running.  When called after PauseWorkers(), does not return until
127b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // ResumeWorkers() or StopWorkers() has been called.  Number of distinct
128b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // calling threads must match the worker count (see AddWorkers() and
129b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // RemoveSelf()).
130b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool ContinueRunning();
131b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
132b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // TODO(matthewb): Is this functionality really necessary?  Remove it if not.
133b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
134b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This is a hack!  It's like ContinueRunning(), except it won't pause.  If
135b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // any worker threads use this exclusively in place of ContinueRunning() then
136b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // PauseWorkers() should never be used!
137b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool ContinueRunningNoPause();
138b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
139b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
140b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  enum Status { RUN, PAUSE, STOP };
141b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
142b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void WaitOnPauseBarrier() {
1438f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef _POSIX_BARRIERS
144b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    int error = pthread_barrier_wait(&pause_barrier_);
145b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    if (error != PTHREAD_BARRIER_SERIAL_THREAD)
146b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      sat_assert(error == 0);
1478f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
148b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
149b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
150b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void AcquireNumWorkersLock() {
151b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(0 == pthread_mutex_lock(&num_workers_mutex_));
152b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
153b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
154b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void ReleaseNumWorkersLock() {
155b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(0 == pthread_mutex_unlock(&num_workers_mutex_));
156b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
157b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
158b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void AcquireStatusReadLock() {
159b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(0 == pthread_rwlock_rdlock(&status_rwlock_));
160b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
161b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
162b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void AcquireStatusWriteLock() {
163b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(0 == pthread_rwlock_wrlock(&status_rwlock_));
164b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
165b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
166b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void ReleaseStatusLock() {
167b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    sat_assert(0 == pthread_rwlock_unlock(&status_rwlock_));
168b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
169b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
170b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Status GetStatus() {
171b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    AcquireStatusReadLock();
172b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Status status = status_;
173b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ReleaseStatusLock();
174b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return status;
175b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
176b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
177b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Returns the previous status.
178b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Status SetStatus(Status status) {
179b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    AcquireStatusWriteLock();
180b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Status prev_status = status_;
181b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    status_ = status;
182b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ReleaseStatusLock();
183b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return prev_status;
184b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
185b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
186b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_mutex_t num_workers_mutex_;
187b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int num_workers_;
188b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
189b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_rwlock_t status_rwlock_;
190b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Status status_;
191b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
1928f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef _POSIX_BARRIERS
193b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Guaranteed to not be in use when (status_ != PAUSE).
194b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_barrier_t pause_barrier_;
1958f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
196b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
197b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(WorkerStatus);
198b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
199b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
200b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
201b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// This is a base class for worker threads.
202b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Each thread repeats a specific
203b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// task on various blocks of memory.
204b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass WorkerThread {
205b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
206b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Enum to mark a thread as low/med/high priority.
207b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  enum Priority {
208b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Low,
209b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    Normal,
210b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    High,
211b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
212b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerThread();
213b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual ~WorkerThread();
214b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
215b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Initialize values and thread ID number.
216b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void InitThread(int thread_num_init,
217b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          class Sat *sat_init,
218b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          class OsLayer *os_init,
219b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          class PatternList *patternlist_init,
220b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          WorkerStatus *worker_status);
221b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
222b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This function is DEPRECATED, it does nothing.
223b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetPriority(Priority priority) { priority_ = priority; }
224b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Spawn the worker thread, by running Work().
225b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int SpawnThread();
226b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Only for ThreadSpawnerGeneric().
227b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void StartRoutine();
228b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool InitPriority();
229b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
230b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Wait for the thread to complete its cleanup.
231b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool JoinThread();
232b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Kill worker thread with SIGINT.
233b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool KillThread();
234b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
235b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This is the task function that the thread executes.
236b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This is implemented per subclass.
237b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
238b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
239b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Starts per-WorkerThread timer.
240b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void StartThreadTimer() {gettimeofday(&start_time_, NULL);}
241b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Reads current timer value and returns run duration without recording it.
242b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 ReadThreadTimer() {
243b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    struct timeval end_time_;
244b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    gettimeofday(&end_time_, NULL);
245b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (end_time_.tv_sec - start_time_.tv_sec)*1000000 +
246b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson      (end_time_.tv_usec - start_time_.tv_usec);
247b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
248b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Stops per-WorkerThread timer and records thread run duration.
249b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Start/Stop ThreadTimer repetitively has cumulative effect, ie the timer
250b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // is effectively paused and restarted, so runduration_usec accumulates on.
251b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void StopThreadTimer() {
252b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    runduration_usec_ += ReadThreadTimer();
253b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
254b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
255b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Acccess member variables.
256b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool GetStatus() {return status_;}
257b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 GetErrorCount() {return errorcount_;}
258b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 GetPageCount() {return pages_copied_;}
259b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 GetRunDurationUSec() {return runduration_usec_;}
260b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
261b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Returns bandwidth defined as pages_copied / thread_run_durations.
262b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetCopiedData();
263b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific copied data.
264b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData() {return 0;}
265b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceCopiedData() {return 0;}
266b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
267b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryBandwidth()
268b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetMemoryCopiedData() / (
269b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        runduration_usec_ * 1.0 / 1000000);}
270b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceBandwidth()
271b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetDeviceCopiedData() / (
272b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson        runduration_usec_ * 1.0 / 1000000);}
273b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
274b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void set_cpu_mask(cpu_set_t *mask) {
275b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    memcpy(&cpu_mask_, mask, sizeof(*mask));
276b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
277b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
278b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void set_cpu_mask_to_cpu(int cpu_num) {
279b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpuset_set_ab(&cpu_mask_, cpu_num, cpu_num + 1);
280b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
281b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
282b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void set_tag(int32 tag) {tag_ = tag;}
283b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
284b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Returns CPU mask, where each bit represents a logical cpu.
285b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool AvailableCpus(cpu_set_t *cpuset);
286b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Returns CPU mask of CPUs this thread is bound to,
287b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool CurrentCpus(cpu_set_t *cpuset);
288b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Returns Current Cpus mask as string.
289b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string CurrentCpusFormat() {
290b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    cpu_set_t current_cpus;
291b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    CurrentCpus(&current_cpus);
292b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return cpuset_format(&current_cpus);
293b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
294b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
295b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int ThreadID() {return thread_num_;}
296b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
297b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Bind worker thread to specified CPU(s)
298b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool BindToCpus(const cpu_set_t *cpuset);
299b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
300b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
301b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // This function dictates whether the main work loop
302b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // continues, waits, or terminates.
303b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // All work loops should be of the form:
304b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //   do {
305b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //     // work.
306b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //   } while (IsReadyToRun());
307b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool IsReadyToRun() { return worker_status_->ContinueRunning(); }
308b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // TODO(matthewb): Is this function really necessary? Remove it if not.
309b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  //
310b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Like IsReadyToRun(), except it won't pause.
311b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool IsReadyToRunNoPause() {
312b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return worker_status_->ContinueRunningNoPause();
313b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
314b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
315b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // These are functions used by the various work loops.
316b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Pretty print and log a data miscompare.
317b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void ProcessError(struct ErrorRecord *er,
318b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            int priority,
319b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            const char *message);
320b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
321b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Compare a region of memory with a known data patter, and report errors.
322b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int CheckRegion(void *addr,
323b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          class Pattern *pat,
324b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int64 length,
325b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int offset,
326b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int64 patternoffset);
327b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
328b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fast compare a block of memory.
329b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int CrcCheckPage(struct page_entry *srcpe);
330b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
331b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fast copy a block of memory, while verifying correctness.
332b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int CrcCopyPage(struct page_entry *dstpe,
333b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          struct page_entry *srcpe);
334b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
335b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fast copy a block of memory, while verifying correctness, and heating CPU.
336b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int CrcWarmCopyPage(struct page_entry *dstpe,
337b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              struct page_entry *srcpe);
338b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
339b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fill a page with its specified pattern.
340b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool FillPage(struct page_entry *pe);
341b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
342b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Copy with address tagging.
343b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool AdlerAddrMemcpyC(uint64 *dstmem64,
344b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                uint64 *srcmem64,
345b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                unsigned int size_in_bytes,
346b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                AdlerChecksum *checksum,
347b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                struct page_entry *pe);
348b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // SSE copy with address tagging.
349b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool AdlerAddrMemcpyWarm(uint64 *dstmem64,
350b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                   uint64 *srcmem64,
351b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                   unsigned int size_in_bytes,
352b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                   AdlerChecksum *checksum,
353b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                   struct page_entry *pe);
354b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Crc data with address tagging.
355b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool AdlerAddrCrcC(uint64 *srcmem64,
356b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             unsigned int size_in_bytes,
357b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             AdlerChecksum *checksum,
358b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             struct page_entry *pe);
359b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Setup tagging on an existing page.
360b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool TagAddrC(uint64 *memwords,
361b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                        unsigned int size_in_bytes);
362b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Report a mistagged cacheline.
363b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ReportTagError(uint64 *mem64,
364b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                      uint64 actual,
365b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                      uint64 tag);
366b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Print out the error record of the tag mismatch.
367b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void ProcessTagError(struct ErrorRecord *error,
368b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       int priority,
369b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                       const char *message);
370b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
371b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // A worker thread can yield itself to give up CPU until it's scheduled again
372b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool YieldSelf();
373b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
374b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
375b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // General state variables that all subclasses need.
376b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int thread_num_;                  // Thread ID.
377b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  volatile bool status_;            // Error status.
378b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  volatile int64 pages_copied_;     // Recorded for memory bandwidth calc.
379b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  volatile int64 errorcount_;       // Miscompares seen by this thread.
380b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
381b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cpu_set_t cpu_mask_;              // Cores this thread is allowed to run on.
382b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  volatile uint32 tag_;             // Tag hint for memory this thread can use.
383b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
384b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool tag_mode_;                   // Tag cachelines with vaddr.
385b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
386b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Thread timing variables.
387b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct timeval start_time_;        // Worker thread start time.
388b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  volatile int64 runduration_usec_;  // Worker run duration in u-seconds.
389b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
390b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Function passed to pthread_create.
391b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void *(*thread_spawner_)(void *args);
392b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  pthread_t thread_;                // Pthread thread ID.
393b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  Priority priority_;               // Worker thread priority.
394b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  class Sat *sat_;                  // Reference to parent stest object.
395b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  class OsLayer *os_;               // Os abstraction: put hacks here.
396b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  class PatternList *patternlist_;  // Reference to data patterns.
397b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
398b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Work around style guide ban on sizeof(int).
399b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const uint64 iamint_ = 0;
400b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int wordsize_ = sizeof(iamint_);
401b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
402b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
403b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  WorkerStatus *worker_status_;
404b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
405b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(WorkerThread);
406b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
407b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
408b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform File IO.
409b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass FileThread : public WorkerThread {
410b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
411b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  FileThread();
412b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set filename to use for file IO.
413b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void SetFile(const char *filename_init);
414b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
415b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
416b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
417b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceCopiedData()
418b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData()*2;}
419b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData();
420b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
421b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
422b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Record of where these pages were sourced from, and what
423b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // potentially broken components they passed through.
424b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct PageRec {
425b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson     struct Pattern *pattern;  // This is the data it should contain.
426b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson     void *src;  // This is the memory location the data was sourced from.
427b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson     void *dst;  // This is where it ended up.
428b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
429b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
430b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // These are functions used by the various work loops.
431b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Pretty print and log a data miscompare. Disks require
432b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // slightly different error handling.
433b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void ProcessError(struct ErrorRecord *er,
434b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            int priority,
435b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            const char *message);
436b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
437b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool OpenFile(int *pfile);
438b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool CloseFile(int fd);
439b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
440b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Read and write whole file to disk.
441b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool WritePages(int fd);
442b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ReadPages(int fd);
443b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
444b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Read and write pages to disk.
445b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool WritePageToFile(int fd, struct page_entry *src);
446b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ReadPageFromFile(int fd, struct page_entry *dst);
447b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
448b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Sector tagging support.
449b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool SectorTagPage(struct page_entry *src, int block);
450b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool SectorValidatePage(const struct PageRec &page,
451b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                  struct page_entry *dst,
452b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                  int block);
453b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
454b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get memory for an incoming data transfer..
455b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool PagePrepare();
456b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Remove memory allocated for data transfer.
457b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool PageTeardown();
458b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
459b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get memory for an incoming data transfer..
460b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool GetEmptyPage(struct page_entry *dst);
461b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Get memory for an outgoing data transfer..
462b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool GetValidPage(struct page_entry *dst);
463b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Throw out a used empty page.
464b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool PutEmptyPage(struct page_entry *src);
465b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Throw out a used, filled page.
466b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool PutValidPage(struct page_entry *src);
467b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
468b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
469b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct PageRec *page_recs_;          // Array of page records.
470b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int crc_page_;                        // Page currently being CRC checked.
471b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string filename_;                     // Name of file to access.
472b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string devicename_;                   // Name of device file is on.
473b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
474b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool page_io_;                        // Use page pool for IO.
475b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void *local_page_;                   // malloc'd page fon non-pool IO.
476b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int pass_;                            // Number of writes to the file so far.
477b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
478b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Tag to detect file corruption.
479b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct SectorTag {
480b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    volatile uint8 magic;
481b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    volatile uint8 block;
482b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    volatile uint8 sector;
483b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    volatile uint8 pass;
484b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    char pad[512-4];
485b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
486b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
487b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(FileThread);
488b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
489b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
490b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
491b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform Network IO.
492b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass NetworkThread : public WorkerThread {
493b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
494b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  NetworkThread();
495b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set hostname to use for net IO.
496b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void SetIP(const char *ipaddr_init);
497b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
498b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
499b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
500b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceCopiedData()
501b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData()*2;}
502b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
503b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
504b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // IsReadyToRunNoPause() wrapper, for NetworkSlaveThread to override.
505b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool IsNetworkStopSet();
506b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool CreateSocket(int *psocket);
507b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool CloseSocket(int sock);
508b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Connect(int sock);
509b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool SendPage(int sock, struct page_entry *src);
510b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ReceivePage(int sock, struct page_entry *dst);
511b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  char ipaddr_[256];
512b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int sock_;
513b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
514b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
515b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(NetworkThread);
516b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
517b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
518b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to reflect Network IO.
519b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass NetworkSlaveThread : public NetworkThread {
520b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
521b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  NetworkSlaveThread();
522b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set socket for IO.
523b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void SetSock(int sock);
524b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
525b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
526b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
527b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool IsNetworkStopSet();
528b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
529b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
530b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(NetworkSlaveThread);
531b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
532b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
533b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to detect incoming Network IO.
534b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass NetworkListenThread : public NetworkThread {
535b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
536b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  NetworkListenThread();
537b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
538b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
539b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
540b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Listen();
541b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Wait();
542b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool GetConnection(int *pnewsock);
543b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool SpawnSlave(int newsock, int threadid);
544b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ReapSlaves();
545b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
546b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // For serviced incoming connections.
547b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  struct ChildWorker {
548b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    WorkerStatus status;
549b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    NetworkSlaveThread thread;
550b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
551b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  typedef vector<ChildWorker*> ChildVector;
552b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ChildVector child_workers_;
553b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
554b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(NetworkListenThread);
555b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
556b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
557b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform Memory Copy.
558b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass CopyThread : public WorkerThread {
559b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
560b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CopyThread() {}
561b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
562b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
563b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData()
564b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData()*2;}
565b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
566b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
567b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(CopyThread);
568b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
569b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
570b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform Memory Invert.
571b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass InvertThread : public WorkerThread {
572b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
573b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  InvertThread() {}
574b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
575b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
576b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData()
577b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData()*4;}
578b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
579b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
580b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int InvertPageUp(struct page_entry *srcpe);
581b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int InvertPageDown(struct page_entry *srcpe);
582b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(InvertThread);
583b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
584b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
585b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to fill blank pages on startup.
586b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass FillThread : public WorkerThread {
587b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
588b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  FillThread();
589b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set how many pages this thread should fill before exiting.
590b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void SetFillPages(int64 num_pages_to_fill_init);
591b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
592b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
593b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
594b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Fill a page with the data pattern in pe->pattern.
595b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool FillPageRandom(struct page_entry *pe);
596b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 num_pages_to_fill_;
597b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(FillThread);
598b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
599b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
600b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to verify page data matches pattern data.
601b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Thread will check and replace pages until "done" flag is set,
602b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// then it will check and discard pages until no more remain.
603b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass CheckThread : public WorkerThread {
604b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
605b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CheckThread() {}
606b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
607b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
608b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData()
609b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData();}
610b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
611b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
612b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(CheckThread);
613b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
614b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
615b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
616b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to poll for system error messages.
617b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Thread will check for messages until "done" flag is set.
618b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass ErrorPollThread : public WorkerThread {
619b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
620b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ErrorPollThread() {}
621b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
622b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
623b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
624b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(ErrorPollThread);
625b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
626b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
627b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Computation intensive worker thread to stress CPU.
628b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass CpuStressThread : public WorkerThread {
629b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
630b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CpuStressThread() {}
631b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
632b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
633b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
634b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(CpuStressThread);
635b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
636b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
637b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread that tests the correctness of the
638b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// CPU Cache Coherency Protocol.
639b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass CpuCacheCoherencyThread : public WorkerThread {
640b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
641b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  CpuCacheCoherencyThread(cc_cacheline_data *cc_data,
642b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int cc_cacheline_count_,
643b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int cc_thread_num_,
644b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                          int cc_inc_count_);
645b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
646b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
647b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
648b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  cc_cacheline_data *cc_cacheline_data_;  // Datstructure for each cacheline.
649b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int cc_local_num_;        // Local counter for each thread.
650b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int cc_cacheline_count_;  // Number of cache lines to operate on.
651b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int cc_thread_num_;       // The integer id of the thread which is
652b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            // used as an index into the integer array
653b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                            // of the cacheline datastructure.
654b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int cc_inc_count_;        // Number of times to increment the counter.
655b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
656b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
657b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(CpuCacheCoherencyThread);
658b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
659b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
660b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform disk test.
661b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass DiskThread : public WorkerThread {
662b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
663b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  explicit DiskThread(DiskBlockTable *block_table);
664b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual ~DiskThread();
665b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate disk thread specific bandwidth.
666b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceCopiedData() {
667b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    return (blocks_written_ * write_block_size_ +
668b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson            blocks_read_ * read_block_size_) / kMegabyte;}
669b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
670b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set filename for device file (in /dev).
671b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual void SetDevice(const char *device_name);
672b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Set various parameters that control the behaviour of the test.
673b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool SetParameters(int read_block_size,
674b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int write_block_size,
675b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int64 segment_size,
676b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int64 cache_size,
677b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int blocks_per_segment,
678b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int64 read_threshold,
679b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int64 write_threshold,
680b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                             int non_destructive);
681b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
682b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
683b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
684b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData() {return 0;}
685b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
686b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
687b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kSectorSize = 512;       // Size of sector on disk.
688b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kBufferAlignment = 512;  // Buffer alignment required by the
689b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                            // kernel.
690b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kBlockRetry = 100;       // Number of retries to allocate
691b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                            // sectors.
692b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
693b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  enum IoOp {
694b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ASYNC_IO_READ   = 0,
695b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    ASYNC_IO_WRITE  = 1
696b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  };
697b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
698b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool OpenDevice(int *pfile);
699b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool CloseDevice(int fd);
700b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
701b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Retrieves the size (in bytes) of the disk/file.
702b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool GetDiskSize(int fd);
703b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
704b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Retrieves the current time in microseconds.
705b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual int64 GetTime();
706b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
707b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Do an asynchronous disk I/O operation.
708b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
709b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                           int64 offset, int64 timeout);
710b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
711b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Write a block to disk.
712b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool WriteBlockToDisk(int fd, BlockData *block);
713b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
714b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Verify a block on disk.
715b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool ValidateBlockOnDisk(int fd, BlockData *block);
716b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
717b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Main work loop.
718b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool DoWork(int fd);
719b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
720b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int read_block_size_;       // Size of blocks read from disk, in bytes.
721b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int write_block_size_;      // Size of blocks written to disk, in bytes.
722b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 blocks_read_;         // Number of blocks read in work loop.
723b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 blocks_written_;      // Number of blocks written in work loop.
724b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 segment_size_;        // Size of disk segments (in bytes) that the disk
725b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // will be split into where testing can be
726b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // confined to a particular segment.
727b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // Allows for control of how evenly the disk will
728b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // be tested.  Smaller segments imply more even
729b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // testing (less random).
730b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int blocks_per_segment_;    // Number of blocks that will be tested per
731b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // segment.
732b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int cache_size_;            // Size of disk cache, in bytes.
733b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int queue_size_;            // Length of in-flight-blocks queue, in blocks.
734b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int non_destructive_;       // Use non-destructive mode or not.
735b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int update_block_table_;    // If true, assume this is the thread
736b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // responsible for writing the data in the disk
737b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // for this block device and, therefore,
738b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // update the block table. If false, just use
739b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // the block table to get data.
740b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
741b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // read/write times threshold for reporting a problem
742b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 read_threshold_;      // Maximum time a read should take (in us) before
743b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // a warning is given.
744b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 write_threshold_;     // Maximum time a write should take (in us) before
745b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // a warning is given.
746b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 read_timeout_;        // Maximum time a read can take before a timeout
747b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // and the aborting of the read operation.
748b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 write_timeout_;       // Maximum time a write can take before a timeout
749b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                              // and the aborting of the write operation.
750b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
751b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string device_name_;        // Name of device file to access.
752b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int64 device_sectors_;      // Number of sectors on the device.
753b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
754b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  std::queue<BlockData*> in_flight_sectors_;   // Queue of sectors written but
755b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                                // not verified.
756b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void *block_buffer_;        // Pointer to aligned block buffer.
757b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
7588f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#ifdef HAVE_LIBAIO_H
759b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  io_context_t aio_ctx_;     // Asynchronous I/O context for Linux native AIO.
7608f1c60d605d31447b4f9ccf86029790bed3fb3f3Scott Anderson#endif
761b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
762b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DiskBlockTable *block_table_;  // Disk Block Table, shared by all disk
763b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 // threads that read / write at the same
764b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                                 // device
765b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
766b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(DiskThread);
767b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
768b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
769b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass RandomDiskThread : public DiskThread {
770b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
771b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  explicit RandomDiskThread(DiskBlockTable *block_table);
772b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual ~RandomDiskThread();
773b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Main work loop.
774b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool DoWork(int fd);
775b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
776b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(RandomDiskThread);
777b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
778b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
779b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson// Worker thread to perform checks in a specific memory region.
780b0114cb9f332db144f65291211ae65f7f0e814e6Scott Andersonclass MemoryRegionThread : public WorkerThread {
781b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson public:
782b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  MemoryRegionThread();
783b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  ~MemoryRegionThread();
784b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual bool Work();
785b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void ProcessError(struct ErrorRecord *error, int priority,
786b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson                    const char *message);
787b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool SetRegion(void *region, int64 size);
788b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Calculate worker thread specific bandwidth.
789b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetMemoryCopiedData()
790b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData();}
791b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  virtual float GetDeviceCopiedData()
792b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    {return GetCopiedData() * 2;}
793b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  void SetIdentifier(string identifier) {
794b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson    identifier_ = identifier;
795b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  }
796b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
797b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson protected:
798b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  // Page queue for this particular memory region.
799b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  char *region_;
800b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  PageEntryQueue *pages_;
801b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  bool error_injection_;
802b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  int phase_;
803b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  string identifier_;
804b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kPhaseNoPhase = 0;
805b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kPhaseCopy = 1;
806b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  static const int kPhaseCheck = 2;
807b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
808b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson private:
809b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson  DISALLOW_COPY_AND_ASSIGN(MemoryRegionThread);
810b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson};
811b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson
812b0114cb9f332db144f65291211ae65f7f0e814e6Scott Anderson#endif  // STRESSAPPTEST_WORKER_H_
813