Coverage for /Syzygy/agent/memprof/memprof_harness.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%0070.C++source

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  //
  15    :  // A minimal test harness that invokes all of the functions that are observed
  16    :  // by the memory profiler. The harness also uses threading so that the traces
  17    :  // produced by profiling this harness put the grinder through its paces.
  18    :  //
  19    :  // The output of the grinder should look like the following (with a minimal set
  20    :  // of dependencies drawn as arrows):
  21    :  //
  22    :  //     WorkerThread1                       WorkerThread2
  23    :  //     -------------                       -------------
  24    :  //  1: create heap 0                       create heap 3
  25    :  //  2: create alloc 0 on heap 0            create alloc 3 on heap 3
  26    :  //  3: create heap 1 --------------------> create alloc 4 on heap 1
  27    :  //  4: create alloc 1 on heap 1 ---------> get size of alloc 1 on heap 1
  28    :  //  5: create alloc 2 on heap 1            realloc alloc 1 on heap 1
  29    :  //  6: free alloc 2 on heap 1              free alloc 1 on heap 1
  30    :  //  7: set info on heap 2                  free alloc 4 on heap 1
  31    :  //  8: free alloc 0 on heap 0              destroy heap 1
  32    :  //  9: destroy heap 0                      free alloc 3 on heap 3
  33    :  // 10:                                     destroy heap 3
  34    :  
  35    :  #include "windows.h"
  36    :  
  37  m :  namespace {
  38    :  
  39    :  // Mutex synchronizing access to shared_heap and shared_alloc.
  40  m :  HANDLE shared_mutex = nullptr;
  41    :  
  42    :  // Heap that has shared use across two threads.
  43  m :  HANDLE shared_heap = nullptr;
  44    :  
  45    :  // Allocation that has shared use across two threads. Allocated from
  46    :  // shared_heap.
  47  m :  void* shared_alloc = nullptr;
  48    :  
  49    :  // Helper function for acquiring |shared_mutex| on the current thread.
  50  m :  void AcquireMutex() {
  51  m :    while (::WaitForSingleObject(shared_mutex, INFINITE) != WAIT_OBJECT_0) {}
  52  m :  }
  53    :  
  54    :  // Body of the first worker thread. This thread is responsible for creating the
  55    :  // shared heap and allocation.
  56  m :  DWORD WINAPI WorkerThread1Main(LPVOID param) {
  57    :    // Allocate a heap and a buffer on this thread.
  58  m :    HANDLE heap = ::HeapCreate(0, 0, 0);                     // 1
  59  m :    void* alloc1 = ::HeapAlloc(heap, HEAP_ZERO_MEMORY, 42);  // 2
  60    :  
  61  m :    AcquireMutex();
  62    :  
  63  m :    shared_heap = ::HeapCreate(0, 0, 0);                  // 3
  64  m :    shared_alloc = ::HeapAlloc(shared_heap, 0, 1 << 20);  // 4
  65    :  
  66  m :    void* alloc2 = ::HeapAlloc(shared_heap, 0, 16);  // 5
  67  m :    ::HeapFree(shared_heap, 0, alloc2);              // 6
  68    :  
  69  m :    ::ReleaseMutex(shared_mutex);
  70    :  
  71    :    // Tinker with the process heap a bit.
  72  m :    HANDLE process_heap = ::GetProcessHeap();
  73  m :    ::HeapSetInformation(process_heap, HeapEnableTerminationOnCorruption,  // 7
  74  m :                         0, 0);
  75    :  
  76    :    // Free the allocation and heap made on this thread.
  77  m :    ::HeapFree(heap, 0, alloc1);  // 8
  78  m :    alloc1 = nullptr;
  79  m :    ::HeapDestroy(heap);  // 9
  80  m :    heap = nullptr;
  81    :  
  82    :    // Wait for the shared_heap to be cleaned up. This ensures that the two
  83    :    // threads do run simultaneously and get distinct thread IDs.
  84  m :    while (true) {
  85  m :      AcquireMutex();
  86  m :      if (shared_heap == nullptr)
  87  m :        break;
  88  m :      ::ReleaseMutex(shared_mutex);
  89  m :    }
  90  m :    ::ReleaseMutex(shared_mutex);
  91    :  
  92  m :    return 0;
  93  m :  }
  94    :  
  95    :  // Body of the second worker thread. This thread is responsible for releasing
  96    :  // the shared heap and allocation.
  97  m :  DWORD WINAPI WorkerThread2Main(LPVOID param) {
  98    :    // Allocate a heap and a buffer on this thread.
  99  m :    HANDLE heap = ::HeapCreate(0, 0, 0);                       // 1
 100  m :    void* alloc1 = ::HeapAlloc(heap, HEAP_ZERO_MEMORY, 1024);  // 2
 101    :  
 102    :    // Wait until the shared heap is initialized.
 103  m :    while (true) {
 104  m :      AcquireMutex();
 105  m :      if (shared_heap != nullptr)
 106  m :        break;
 107  m :      ::ReleaseMutex(shared_mutex);
 108  m :    }
 109    :  
 110    :    // Create an allocation on this thread that is only used on this thread,
 111    :    // but which references the shared heap.
 112  m :    HANDLE alloc2 = ::HeapAlloc(shared_heap, 0, 347);  // 3
 113    :  
 114    :    // Query and then free the shared allocation.
 115  m :    ::HeapSize(shared_heap, 0, shared_alloc);                         // 4
 116  m :    shared_alloc = ::HeapReAlloc(shared_heap, 0, shared_alloc, 500);  // 5
 117  m :    ::HeapFree(shared_heap, 0, shared_alloc);                         // 6
 118  m :    shared_alloc = nullptr;
 119    :  
 120    :    // Free the shared_heap allocation made on this thread.
 121  m :    ::HeapFree(shared_heap, 0, alloc2);  // 7
 122    :  
 123    :    // Free the shared heap.
 124  m :    ::HeapDestroy(shared_heap);  // 8
 125  m :    shared_heap = nullptr;
 126    :  
 127  m :    ::ReleaseMutex(shared_mutex);
 128    :  
 129  m :    ::HeapFree(heap, 0, alloc1);  // 9
 130  m :    alloc1 = nullptr;
 131  m :    ::HeapDestroy(heap);  // 10
 132  m :    heap = nullptr;
 133    :  
 134  m :    return 0;
 135  m :  }
 136    :  
 137  m :  }  // namespace
 138    :  
 139  m :  int main(int argc, const char* const* argv) {
 140    :    // The controlled tests (with known expectations) are run on independent
 141    :    // threads. This keeps them separated from the CRT code that runs on the main
 142    :    // thread and which we don't directly control.
 143    :  
 144    :    // Create a mutex not owned by anyone.
 145  m :    shared_mutex = ::CreateMutex(NULL, FALSE, NULL);
 146    :  
 147    :    // Run the two threads simultaneously and wait for them both to finish.
 148  m :    DWORD worker_thread_1_id = 0;
 149  m :    HANDLE worker_thread_1 = ::CreateThread(nullptr, 0, WorkerThread1Main,
 150  m :                                            nullptr, 0, &worker_thread_1_id);
 151  m :    DWORD worker_thread_2_id = 0;
 152  m :    HANDLE worker_thread_2 = ::CreateThread(nullptr, 0, WorkerThread2Main,
 153  m :                                            nullptr, 0, &worker_thread_2_id);
 154  m :    ::WaitForSingleObject(worker_thread_1, INFINITE);
 155  m :    ::WaitForSingleObject(worker_thread_2, INFINITE);
 156    :  
 157    :    // Destroy the mutex.
 158  m :    ::CloseHandle(shared_mutex);
 159    :  
 160  m :    return 0;
 161  m :  }

Coverage information generated Thu Jan 14 17:40:38 2016.