1 // Copyright 2006 Google Inc. All Rights Reserved.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // worker.h : worker thread interface
17 // This file contains the Worker Thread class interface
18 // for the SAT test. Worker Threads implement a repetative
19 // task used to test or stress the system.
21 #ifndef STRESSAPPTEST_WORKER_H_
22 #define STRESSAPPTEST_WORKER_H_
27 #include <sys/types.h>
38 // This file must work with autoconf on its public version,
39 // so these includes are correct.
40 #include "disk_blocks.h"
45 // Global Datastruture shared by the Cache Coherency Worker Threads.
46 struct cc_cacheline_data {
51 // (Other workflows may be possible, see function comments for details.)
52 // - Control thread creates object.
53 // - Control thread calls AddWorkers(1) for each worker thread.
54 // - Control thread calls Initialize().
55 // - Control thread launches worker threads.
56 // - Every worker thread frequently calls ContinueRunning().
57 // - Control thread periodically calls PauseWorkers(), effectively sleeps, and
58 // then calls ResumeWorkers().
59 // - Some worker threads may exit early, before StopWorkers() is called. They
60 // call RemoveSelf() after their last call to ContinueRunning().
61 // - Control thread eventually calls StopWorkers().
62 // - Worker threads exit.
63 // - Control thread joins worker threads.
64 // - Control thread calls Destroy().
65 // - Control thread destroys object.
68 // - ContinueRunning() may be called concurrently by different workers, but not
69 // by a single worker.
70 // - No other methods may ever be called concurrently, with themselves or
72 // - This object may be used by multiple threads only between Initialize() and
75 // TODO(matthewb): Move this class and its unittest to their own files.
78 //--------------------------------
79 // Methods for the control thread.
80 //--------------------------------
82 WorkerStatus() : num_workers_(0), status_(RUN) {}
84 // Called by the control thread to increase the worker count. Must be called
85 // before Initialize(). The worker count is 0 upon object initialization.
86 void AddWorkers(int num_new_workers) {
87 // No need to lock num_workers_mutex_ because this is before Initialize().
88 num_workers_ += num_new_workers;
91 // Called by the control thread. May not be called multiple times. If
92 // called, Destroy() must be called before destruction.
95 // Called by the control thread after joining all worker threads. Must be
96 // called iff Initialize() was called. No methods may be called after calling
100 // Called by the control thread to tell the workers to pause. Does not return
101 // until all workers have called ContinueRunning() or RemoveSelf(). May only
102 // be called between Initialize() and Stop(). Must not be called multiple
103 // times without ResumeWorkers() having been called inbetween.
106 // Called by the control thread to tell the workers to resume from a pause.
107 // May only be called between Initialize() and Stop(). May only be called
108 // directly after PauseWorkers().
109 void ResumeWorkers();
111 // Called by the control thread to tell the workers to stop. May only be
112 // called between Initialize() and Destroy(). May only be called once.
115 //--------------------------------
116 // Methods for the worker threads.
117 //--------------------------------
119 // Called by worker threads to decrease the worker count by one. May only be
120 // called between Initialize() and Destroy(). May wait for ResumeWorkers()
121 // when called after PauseWorkers().
124 // Called by worker threads between Initialize() and Destroy(). May be called
125 // any number of times. Return value is whether or not the worker should
126 // continue running. When called after PauseWorkers(), does not return until
127 // ResumeWorkers() or StopWorkers() has been called. Number of distinct
128 // calling threads must match the worker count (see AddWorkers() and
130 bool ContinueRunning(bool *paused);
132 // This is a hack! It's like ContinueRunning(), except it won't pause. If
133 // any worker threads use this exclusively in place of ContinueRunning() then
134 // PauseWorkers() should never be used!
135 bool ContinueRunningNoPause();
138 enum Status { RUN, PAUSE, STOP };
140 void WaitOnPauseBarrier() {
141 #ifdef HAVE_PTHREAD_BARRIERS
142 int error = pthread_barrier_wait(&pause_barrier_);
143 if (error != PTHREAD_BARRIER_SERIAL_THREAD)
144 sat_assert(error == 0);
148 void AcquireNumWorkersLock() {
149 sat_assert(0 == pthread_mutex_lock(&num_workers_mutex_));
152 void ReleaseNumWorkersLock() {
153 sat_assert(0 == pthread_mutex_unlock(&num_workers_mutex_));
156 void AcquireStatusReadLock() {
157 sat_assert(0 == pthread_rwlock_rdlock(&status_rwlock_));
160 void AcquireStatusWriteLock() {
161 sat_assert(0 == pthread_rwlock_wrlock(&status_rwlock_));
164 void ReleaseStatusLock() {
165 sat_assert(0 == pthread_rwlock_unlock(&status_rwlock_));
169 AcquireStatusReadLock();
170 Status status = status_;
175 // Returns the previous status.
176 Status SetStatus(Status status) {
177 AcquireStatusWriteLock();
178 Status prev_status = status_;
184 pthread_mutex_t num_workers_mutex_;
187 pthread_rwlock_t status_rwlock_;
190 #ifdef HAVE_PTHREAD_BARRIERS
191 // Guaranteed to not be in use when (status_ != PAUSE).
192 pthread_barrier_t pause_barrier_;
195 DISALLOW_COPY_AND_ASSIGN(WorkerStatus);
199 // This is a base class for worker threads.
200 // Each thread repeats a specific
201 // task on various blocks of memory.
204 // Enum to mark a thread as low/med/high priority.
211 virtual ~WorkerThread();
213 // Initialize values and thread ID number.
214 virtual void InitThread(int thread_num_init,
216 class OsLayer *os_init,
217 class PatternList *patternlist_init,
218 WorkerStatus *worker_status);
220 // This function is DEPRECATED, it does nothing.
221 void SetPriority(Priority priority) { priority_ = priority; }
222 // Spawn the worker thread, by running Work().
224 // Only for ThreadSpawnerGeneric().
228 // Wait for the thread to complete its cleanup.
229 virtual bool JoinThread();
230 // Kill worker thread with SIGINT.
231 virtual bool KillThread();
233 // This is the task function that the thread executes.
234 // This is implemented per subclass.
237 // Starts per-WorkerThread timer.
238 void StartThreadTimer() {gettimeofday(&start_time_, NULL);}
239 // Reads current timer value and returns run duration without recording it.
240 int64 ReadThreadTimer() {
241 struct timeval end_time_;
242 gettimeofday(&end_time_, NULL);
243 return (end_time_.tv_sec - start_time_.tv_sec)*1000000ULL +
244 (end_time_.tv_usec - start_time_.tv_usec);
246 // Stops per-WorkerThread timer and records thread run duration.
247 // Start/Stop ThreadTimer repetitively has cumulative effect, ie the timer
248 // is effectively paused and restarted, so runduration_usec accumulates on.
249 void StopThreadTimer() {
250 runduration_usec_ += ReadThreadTimer();
253 // Acccess member variables.
254 bool GetStatus() {return status_;}
255 int64 GetErrorCount() {return errorcount_;}
256 int64 GetPageCount() {return pages_copied_;}
257 int64 GetRunDurationUSec() {return runduration_usec_;}
259 // Returns bandwidth defined as pages_copied / thread_run_durations.
260 virtual float GetCopiedData();
261 // Calculate worker thread specific copied data.
262 virtual float GetMemoryCopiedData() {return 0;}
263 virtual float GetDeviceCopiedData() {return 0;}
264 // Calculate worker thread specific bandwidth.
265 virtual float GetMemoryBandwidth()
266 {return GetMemoryCopiedData() / (
267 runduration_usec_ * 1.0 / 1000000.);}
268 virtual float GetDeviceBandwidth()
269 {return GetDeviceCopiedData() / (
270 runduration_usec_ * 1.0 / 1000000.);}
272 void set_cpu_mask(cpu_set_t *mask) {
273 memcpy(&cpu_mask_, mask, sizeof(*mask));
276 void set_cpu_mask_to_cpu(int cpu_num) {
277 cpuset_set_ab(&cpu_mask_, cpu_num, cpu_num + 1);
280 void set_tag(int32 tag) {tag_ = tag;}
282 // Returns CPU mask, where each bit represents a logical cpu.
283 bool AvailableCpus(cpu_set_t *cpuset);
284 // Returns CPU mask of CPUs this thread is bound to,
285 bool CurrentCpus(cpu_set_t *cpuset);
286 // Returns Current Cpus mask as string.
287 string CurrentCpusFormat() {
288 cpu_set_t current_cpus;
289 CurrentCpus(¤t_cpus);
290 return cpuset_format(¤t_cpus);
293 int ThreadID() {return thread_num_;}
295 // Bind worker thread to specified CPU(s)
296 bool BindToCpus(const cpu_set_t *cpuset);
299 // This function dictates whether the main work loop
300 // continues, waits, or terminates.
301 // All work loops should be of the form:
304 // } while (IsReadyToRun());
305 virtual bool IsReadyToRun(bool *paused = NULL) {
306 return worker_status_->ContinueRunning(paused);
309 // Like IsReadyToRun(), except it won't pause.
310 virtual bool IsReadyToRunNoPause() {
311 return worker_status_->ContinueRunningNoPause();
314 // These are functions used by the various work loops.
315 // Pretty print and log a data miscompare.
316 virtual void ProcessError(struct ErrorRecord *er,
318 const char *message);
320 // Compare a region of memory with a known data patter, and report errors.
321 virtual int CheckRegion(void *addr,
325 int64 patternoffset);
327 // Fast compare a block of memory.
328 virtual int CrcCheckPage(struct page_entry *srcpe);
330 // Fast copy a block of memory, while verifying correctness.
331 virtual int CrcCopyPage(struct page_entry *dstpe,
332 struct page_entry *srcpe);
334 // Fast copy a block of memory, while verifying correctness, and heating CPU.
335 virtual int CrcWarmCopyPage(struct page_entry *dstpe,
336 struct page_entry *srcpe);
338 // Fill a page with its specified pattern.
339 virtual bool FillPage(struct page_entry *pe);
341 // Copy with address tagging.
342 virtual bool AdlerAddrMemcpyC(uint64 *dstmem64,
344 unsigned int size_in_bytes,
345 AdlerChecksum *checksum,
346 struct page_entry *pe);
347 // SSE copy with address tagging.
348 virtual bool AdlerAddrMemcpyWarm(uint64 *dstmem64,
350 unsigned int size_in_bytes,
351 AdlerChecksum *checksum,
352 struct page_entry *pe);
353 // Crc data with address tagging.
354 virtual bool AdlerAddrCrcC(uint64 *srcmem64,
355 unsigned int size_in_bytes,
356 AdlerChecksum *checksum,
357 struct page_entry *pe);
358 // Setup tagging on an existing page.
359 virtual bool TagAddrC(uint64 *memwords,
360 unsigned int size_in_bytes);
361 // Report a mistagged cacheline.
362 virtual bool ReportTagError(uint64 *mem64,
365 // Print out the error record of the tag mismatch.
366 virtual void ProcessTagError(struct ErrorRecord *error,
368 const char *message);
370 // A worker thread can yield itself to give up CPU until it's scheduled again
374 // General state variables that all subclasses need.
375 int thread_num_; // Thread ID.
376 volatile bool status_; // Error status.
377 volatile int64 pages_copied_; // Recorded for memory bandwidth calc.
378 volatile int64 errorcount_; // Miscompares seen by this thread.
380 cpu_set_t cpu_mask_; // Cores this thread is allowed to run on.
381 volatile uint32 tag_; // Tag hint for memory this thread can use.
383 bool tag_mode_; // Tag cachelines with vaddr.
385 // Thread timing variables.
386 struct timeval start_time_; // Worker thread start time.
387 volatile int64 runduration_usec_; // Worker run duration in u-seconds.
389 // Function passed to pthread_create.
390 void *(*thread_spawner_)(void *args);
391 pthread_t thread_; // Pthread thread ID.
392 Priority priority_; // Worker thread priority.
393 class Sat *sat_; // Reference to parent stest object.
394 class OsLayer *os_; // Os abstraction: put hacks here.
395 class PatternList *patternlist_; // Reference to data patterns.
397 // Work around style guide ban on sizeof(int).
398 static const uint64 iamint_ = 0;
399 static const int wordsize_ = sizeof(iamint_);
402 WorkerStatus *worker_status_;
404 DISALLOW_COPY_AND_ASSIGN(WorkerThread);
407 // Worker thread to perform File IO.
408 class FileThread : public WorkerThread {
411 // Set filename to use for file IO.
412 virtual void SetFile(const char *filename_init);
415 // Calculate worker thread specific bandwidth.
416 virtual float GetDeviceCopiedData()
417 {return GetCopiedData()*2;}
418 virtual float GetMemoryCopiedData();
421 // Record of where these pages were sourced from, and what
422 // potentially broken components they passed through.
424 class Pattern *pattern; // This is the data it should contain.
425 void *src; // This is the memory location the data was sourced from.
426 void *dst; // This is where it ended up.
429 // These are functions used by the various work loops.
430 // Pretty print and log a data miscompare. Disks require
431 // slightly different error handling.
432 virtual void ProcessError(struct ErrorRecord *er,
434 const char *message);
436 virtual bool OpenFile(int *pfile);
437 virtual bool CloseFile(int fd);
439 // Read and write whole file to disk.
440 virtual bool WritePages(int fd);
441 virtual bool ReadPages(int fd);
443 // Read and write pages to disk.
444 virtual bool WritePageToFile(int fd, struct page_entry *src);
445 virtual bool ReadPageFromFile(int fd, struct page_entry *dst);
447 // Sector tagging support.
448 virtual bool SectorTagPage(struct page_entry *src, int block);
449 virtual bool SectorValidatePage(const struct PageRec &page,
450 struct page_entry *dst,
453 // Get memory for an incoming data transfer..
454 virtual bool PagePrepare();
455 // Remove memory allocated for data transfer.
456 virtual bool PageTeardown();
458 // Get memory for an incoming data transfer..
459 virtual bool GetEmptyPage(struct page_entry *dst);
460 // Get memory for an outgoing data transfer..
461 virtual bool GetValidPage(struct page_entry *dst);
462 // Throw out a used empty page.
463 virtual bool PutEmptyPage(struct page_entry *src);
464 // Throw out a used, filled page.
465 virtual bool PutValidPage(struct page_entry *src);
468 struct PageRec *page_recs_; // Array of page records.
469 int crc_page_; // Page currently being CRC checked.
470 string filename_; // Name of file to access.
471 string devicename_; // Name of device file is on.
473 bool page_io_; // Use page pool for IO.
474 void *local_page_; // malloc'd page fon non-pool IO.
475 int pass_; // Number of writes to the file so far.
477 // Tag to detect file corruption.
479 volatile uint8 magic;
480 volatile uint8 block;
481 volatile uint8 sector;
486 DISALLOW_COPY_AND_ASSIGN(FileThread);
490 // Worker thread to perform Network IO.
491 class NetworkThread : public WorkerThread {
494 // Set hostname to use for net IO.
495 virtual void SetIP(const char *ipaddr_init);
498 // Calculate worker thread specific bandwidth.
499 virtual float GetDeviceCopiedData()
500 {return GetCopiedData()*2;}
503 // IsReadyToRunNoPause() wrapper, for NetworkSlaveThread to override.
504 virtual bool IsNetworkStopSet();
505 virtual bool CreateSocket(int *psocket);
506 virtual bool CloseSocket(int sock);
507 virtual bool Connect(int sock);
508 virtual bool SendPage(int sock, struct page_entry *src);
509 virtual bool ReceivePage(int sock, struct page_entry *dst);
514 DISALLOW_COPY_AND_ASSIGN(NetworkThread);
517 // Worker thread to reflect Network IO.
518 class NetworkSlaveThread : public NetworkThread {
520 NetworkSlaveThread();
521 // Set socket for IO.
522 virtual void SetSock(int sock);
526 virtual bool IsNetworkStopSet();
529 DISALLOW_COPY_AND_ASSIGN(NetworkSlaveThread);
532 // Worker thread to detect incoming Network IO.
533 class NetworkListenThread : public NetworkThread {
535 NetworkListenThread();
539 virtual bool Listen();
541 virtual bool GetConnection(int *pnewsock);
542 virtual bool SpawnSlave(int newsock, int threadid);
543 virtual bool ReapSlaves();
545 // For serviced incoming connections.
548 NetworkSlaveThread thread;
550 typedef vector<ChildWorker*> ChildVector;
551 ChildVector child_workers_;
553 DISALLOW_COPY_AND_ASSIGN(NetworkListenThread);
556 // Worker thread to perform Memory Copy.
557 class CopyThread : public WorkerThread {
561 // Calculate worker thread specific bandwidth.
562 virtual float GetMemoryCopiedData()
563 {return GetCopiedData()*2;}
566 DISALLOW_COPY_AND_ASSIGN(CopyThread);
569 // Worker thread to perform Memory Invert.
570 class InvertThread : public WorkerThread {
574 // Calculate worker thread specific bandwidth.
575 virtual float GetMemoryCopiedData()
576 {return GetCopiedData()*4;}
579 virtual int InvertPageUp(struct page_entry *srcpe);
580 virtual int InvertPageDown(struct page_entry *srcpe);
581 DISALLOW_COPY_AND_ASSIGN(InvertThread);
584 // Worker thread to fill blank pages on startup.
585 class FillThread : public WorkerThread {
588 // Set how many pages this thread should fill before exiting.
589 virtual void SetFillPages(int64 num_pages_to_fill_init);
593 // Fill a page with the data pattern in pe->pattern.
594 virtual bool FillPageRandom(struct page_entry *pe);
595 int64 num_pages_to_fill_;
596 DISALLOW_COPY_AND_ASSIGN(FillThread);
599 // Worker thread to verify page data matches pattern data.
600 // Thread will check and replace pages until "done" flag is set,
601 // then it will check and discard pages until no more remain.
602 class CheckThread : public WorkerThread {
606 // Calculate worker thread specific bandwidth.
607 virtual float GetMemoryCopiedData()
608 {return GetCopiedData();}
611 DISALLOW_COPY_AND_ASSIGN(CheckThread);
615 // Worker thread to poll for system error messages.
616 // Thread will check for messages until "done" flag is set.
617 class ErrorPollThread : public WorkerThread {
623 DISALLOW_COPY_AND_ASSIGN(ErrorPollThread);
626 // Computation intensive worker thread to stress CPU.
627 class CpuStressThread : public WorkerThread {
633 DISALLOW_COPY_AND_ASSIGN(CpuStressThread);
636 // Worker thread that tests the correctness of the
637 // CPU Cache Coherency Protocol.
638 class CpuCacheCoherencyThread : public WorkerThread {
640 CpuCacheCoherencyThread(cc_cacheline_data *cc_data,
641 int cc_cacheline_count_,
643 int cc_thread_count_,
648 // Used by the simple random number generator as a shift feedback;
649 // this polynomial (x^64 + x^63 + x^61 + x^60 + 1) will produce a
650 // psuedorandom cycle of period 2^64-1.
651 static const uint64 kRandomPolynomial = 0xD800000000000000ULL;
652 // A very simple psuedorandom generator that can be inlined and use
653 // registers, to keep the CC test loop tight and focused.
654 static uint64 SimpleRandom(uint64 seed);
656 cc_cacheline_data *cc_cacheline_data_; // Datstructure for each cacheline.
657 int cc_local_num_; // Local counter for each thread.
658 int cc_cacheline_count_; // Number of cache lines to operate on.
659 int cc_thread_num_; // The integer id of the thread which is
660 // used as an index into the integer array
661 // of the cacheline datastructure.
662 int cc_thread_count_; // Total number of threads being run, for
663 // calculations mixing up cache line access.
664 int cc_inc_count_; // Number of times to increment the counter.
667 DISALLOW_COPY_AND_ASSIGN(CpuCacheCoherencyThread);
670 // Worker thread to perform disk test.
671 class DiskThread : public WorkerThread {
673 explicit DiskThread(DiskBlockTable *block_table);
674 virtual ~DiskThread();
675 // Calculate disk thread specific bandwidth.
676 virtual float GetDeviceCopiedData() {
677 return (blocks_written_ * write_block_size_ +
678 blocks_read_ * read_block_size_) / kMegabyte;}
680 // Set filename for device file (in /dev).
681 virtual void SetDevice(const char *device_name);
682 // Set various parameters that control the behaviour of the test.
683 virtual bool SetParameters(int read_block_size,
684 int write_block_size,
687 int blocks_per_segment,
688 int64 read_threshold,
689 int64 write_threshold,
690 int non_destructive);
694 virtual float GetMemoryCopiedData() {return 0;}
697 static const int kSectorSize = 512; // Size of sector on disk.
698 static const int kBufferAlignment = 512; // Buffer alignment required by the
700 static const int kBlockRetry = 100; // Number of retries to allocate
708 virtual bool OpenDevice(int *pfile);
709 virtual bool CloseDevice(int fd);
711 // Retrieves the size (in bytes) of the disk/file.
712 virtual bool GetDiskSize(int fd);
714 // Retrieves the current time in microseconds.
715 virtual int64 GetTime();
717 // Do an asynchronous disk I/O operation.
718 virtual bool AsyncDiskIO(IoOp op, int fd, void *buf, int64 size,
719 int64 offset, int64 timeout);
721 // Write a block to disk.
722 virtual bool WriteBlockToDisk(int fd, BlockData *block);
724 // Verify a block on disk.
725 virtual bool ValidateBlockOnDisk(int fd, BlockData *block);
728 virtual bool DoWork(int fd);
730 int read_block_size_; // Size of blocks read from disk, in bytes.
731 int write_block_size_; // Size of blocks written to disk, in bytes.
732 int64 blocks_read_; // Number of blocks read in work loop.
733 int64 blocks_written_; // Number of blocks written in work loop.
734 int64 segment_size_; // Size of disk segments (in bytes) that the disk
735 // will be split into where testing can be
736 // confined to a particular segment.
737 // Allows for control of how evenly the disk will
738 // be tested. Smaller segments imply more even
739 // testing (less random).
740 int blocks_per_segment_; // Number of blocks that will be tested per
742 int cache_size_; // Size of disk cache, in bytes.
743 int queue_size_; // Length of in-flight-blocks queue, in blocks.
744 int non_destructive_; // Use non-destructive mode or not.
745 int update_block_table_; // If true, assume this is the thread
746 // responsible for writing the data in the disk
747 // for this block device and, therefore,
748 // update the block table. If false, just use
749 // the block table to get data.
751 // read/write times threshold for reporting a problem
752 int64 read_threshold_; // Maximum time a read should take (in us) before
753 // a warning is given.
754 int64 write_threshold_; // Maximum time a write should take (in us) before
755 // a warning is given.
756 int64 read_timeout_; // Maximum time a read can take before a timeout
757 // and the aborting of the read operation.
758 int64 write_timeout_; // Maximum time a write can take before a timeout
759 // and the aborting of the write operation.
761 string device_name_; // Name of device file to access.
762 int64 device_sectors_; // Number of sectors on the device.
764 std::queue<BlockData*> in_flight_sectors_; // Queue of sectors written but
766 void *block_buffer_; // Pointer to aligned block buffer.
769 io_context_t aio_ctx_; // Asynchronous I/O context for Linux native AIO.
772 DiskBlockTable *block_table_; // Disk Block Table, shared by all disk
773 // threads that read / write at the same
776 DISALLOW_COPY_AND_ASSIGN(DiskThread);
779 class RandomDiskThread : public DiskThread {
781 explicit RandomDiskThread(DiskBlockTable *block_table);
782 virtual ~RandomDiskThread();
784 virtual bool DoWork(int fd);
786 DISALLOW_COPY_AND_ASSIGN(RandomDiskThread);
789 // Worker thread to perform checks in a specific memory region.
790 class MemoryRegionThread : public WorkerThread {
792 MemoryRegionThread();
793 ~MemoryRegionThread();
795 void ProcessError(struct ErrorRecord *error, int priority,
796 const char *message);
797 bool SetRegion(void *region, int64 size);
798 // Calculate worker thread specific bandwidth.
799 virtual float GetMemoryCopiedData()
800 {return GetCopiedData();}
801 virtual float GetDeviceCopiedData()
802 {return GetCopiedData() * 2;}
803 void SetIdentifier(string identifier) {
804 identifier_ = identifier;
808 // Page queue for this particular memory region.
810 PageEntryQueue *pages_;
811 bool error_injection_;
814 static const int kPhaseNoPhase = 0;
815 static const int kPhaseCopy = 1;
816 static const int kPhaseCheck = 2;
819 DISALLOW_COPY_AND_ASSIGN(MemoryRegionThread);
822 // Worker thread to check that the frequency of every cpu does not go below a
823 // certain threshold.
824 class CpuFreqThread : public WorkerThread {
826 CpuFreqThread(int num_cpus, int freq_threshold, int round);
829 // This is the task function that the thread executes.
832 // Returns true if this test can run on the current machine. Otherwise,
834 static bool CanRun();
837 static const int kIntervalPause = 10; // The number of seconds to pause
838 // between acquiring the MSR data.
839 static const int kStartupDelay = 5; // The number of seconds to wait
840 // before acquiring MSR data.
841 static const int kMsrTscAddr = 0x10; // The address of the TSC MSR.
842 static const int kMsrAperfAddr = 0xE8; // The address of the APERF MSR.
843 static const int kMsrMperfAddr = 0xE7; // The address of the MPERF MSR.
845 // The index values into the CpuDataType.msr[] array.
847 kMsrTsc = 0, // MSR index 0 = TSC.
848 kMsrAperf = 1, // MSR index 1 = APERF.
849 kMsrMperf = 2, // MSR index 2 = MPERF.
850 kMsrLast, // Last MSR index.
854 uint32 msr; // The address of the MSR.
855 const char *name; // A human readable string for the MSR.
859 uint64 msrs[kMsrLast]; // The values of the MSRs.
860 struct timeval tv; // The time at which the MSRs were read.
863 // The set of MSR addresses and register names.
864 static const CpuRegisterType kCpuRegisters[kMsrLast];
866 // Compute the change in values of the MSRs between current and previous,
867 // set the frequency in MHz of the cpu. If there is an error computing
868 // the delta, return false. Othewise, return true.
869 bool ComputeFrequency(CpuDataType *current, CpuDataType *previous,
872 // Get the MSR values for this particular cpu and save them in data. If
873 // any error is encountered, returns false. Otherwise, returns true.
874 bool GetMsrs(int cpu, CpuDataType *data);
876 // Compute the difference between the currently read MSR values and the
877 // previously read values and store the results in delta. If any of the
878 // values did not increase, or the TSC value is too small, returns false.
879 // Otherwise, returns true.
880 bool ComputeDelta(CpuDataType *current, CpuDataType *previous,
883 // The total number of cpus on the system.
886 // The minimum frequency that each cpu must operate at (in MHz).
889 // The value to round the computed frequency to.
892 // Precomputed value to add to the frequency to do the rounding.
895 DISALLOW_COPY_AND_ASSIGN(CpuFreqThread);
898 #endif // STRESSAPPTEST_WORKER_H_