Coverage for /Syzygy/agent/common/thread_state.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.7%75760.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 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    :  // Defines the members of the ThreadStateBase and ThreadStateManager classes
  16    :  
  17    :  #include "syzygy/agent/common/thread_state.h"
  18    :  
  19    :  namespace agent {
  20    :  namespace common {
  21    :  
  22    :  ThreadStateBase::ThreadStateBase()
  23  E :      : thread_handle_(::OpenThread(SYNCHRONIZE, FALSE, ::GetCurrentThreadId())) {
  24  E :    DCHECK(thread_handle_.IsValid());
  25  E :    InitializeListHead(&entry_);
  26  E :  }
  27    :  
  28  E :  ThreadStateBase::~ThreadStateBase() {
  29  E :    DCHECK(IsListEmpty(&entry_));
  30  E :  }
  31    :  
  32  E :  ThreadStateManager::ThreadStateManager() {
  33  E :    InitializeListHead(&active_items_);
  34  E :    InitializeListHead(&death_row_items_);
  35  E :  }
  36    :  
  37  E :  ThreadStateManager::~ThreadStateManager() {
  38  E :    bool has_leaked_items = false;
  39  E :    Scavenge(NULL, &has_leaked_items);
  40  E :    if (has_leaked_items)
  41  E :      LOG(WARNING) << "Leaking thread state items.";
  42  E :  }
  43    :  
  44  E :  void ThreadStateManager::Register(ThreadStateBase* item) {
  45  E :    DCHECK(item != NULL);
  46  E :    DCHECK(IsListEmpty(&item->entry_));
  47  E :    base::AutoLock auto_lock(lock_);
  48  E :    InsertTailList(&active_items_, &item->entry_);
  49  E :  }
  50    :  
  51  E :  void ThreadStateManager::Unregister(ThreadStateBase* item) {
  52  E :    DCHECK(item != NULL);
  53  E :    base::AutoLock auto_lock(lock_);
  54  E :    RemoveEntryList(&item->entry_);
  55  E :    InitializeListHead(&item->entry_);
  56  E :  }
  57    :  
  58  E :  void ThreadStateManager::MarkForDeath(ThreadStateBase* item) {
  59  E :    DCHECK(item != NULL);
  60  E :    Scavenge(item, NULL);
  61  E :  }
  62    :  
  63  E :  void ThreadStateManager::Scavenge(ThreadStateBase* item, bool* has_more_items) {
  64    :    // We'll store the list of scavenged items here.
  65    :    LIST_ENTRY dead_items;
  66  E :    InitializeListHead(&dead_items);
  67    :  
  68    :    // Acquire the lock when interacting with the internal data.
  69    :    {
  70  E :      base::AutoLock auto_lock(lock_);
  71    :  
  72    :      // Put all of the death row items belong to dead threads into dead_items.
  73  E :      GatherDeadItemsUnlocked(&dead_items);
  74    :  
  75    :      // If there's an item to mark for death, do so. We do this after gathering
  76    :      // the dead items because the item in question presumably belongs to the
  77    :      // current thread and so could never be gathered.
  78  E :      if (item != NULL) {
  79  E :        RemoveEntryList(&item->entry_);
  80  E :        InsertHeadList(&death_row_items_, &item->entry_);
  81    :      }
  82    :  
  83    :      // Return whether or not the thread state manager is no longer holding
  84    :      // any items.
  85  E :      if (has_more_items != NULL) {
  86    :        *has_more_items =
  87  E :            !IsListEmpty(&active_items_) || !IsListEmpty(&death_row_items_);
  88    :      }
  89  E :    }
  90    :  
  91    :    // We can delete any dead items we found outside of the lock.
  92  E :    DeleteDeadItems(&dead_items);
  93  E :    DCHECK(IsListEmpty(&dead_items));
  94  E :  }
  95    :  
  96  E :  void ThreadStateManager::GatherDeadItemsUnlocked(LIST_ENTRY* dead_items) {
  97  E :    DCHECK(dead_items != NULL);
  98  E :    DCHECK(IsListEmpty(dead_items));
  99  E :    lock_.AssertAcquired();
 100    :  
 101    :    // Return if the death row items list is empty.
 102  E :    if (IsListEmpty(&death_row_items_))
 103  E :      return;
 104    :  
 105    :    // Walk the death row items list, looking for items owned by dead threads.
 106    :    ThreadStateBase* item =
 107  E :        CONTAINING_RECORD(death_row_items_.Flink, ThreadStateBase, entry_);
 108  E :    while (item != NULL) {
 109  E :      ThreadStateBase* next_item = NULL;
 110  E :      if (item->entry_.Flink != &death_row_items_) {
 111    :        next_item =
 112  i :            CONTAINING_RECORD(item->entry_.Flink, ThreadStateBase, entry_);
 113    :      }
 114    :  
 115    :      // Move the item to the dead_items list if the associated thread is dead.
 116  E :      if (IsThreadDead(item)) {
 117  E :        RemoveEntryList(&item->entry_);
 118  E :        InsertTailList(dead_items, &item->entry_);
 119    :      }
 120    :  
 121  E :      item = next_item;
 122  E :    }
 123  E :  }
 124    :  
 125  E :  bool ThreadStateManager::IsThreadDead(ThreadStateBase* item) {
 126  E :    DCHECK(item != NULL);
 127  E :    return ::WaitForSingleObject(item->thread_handle_, 0)  == WAIT_OBJECT_0;
 128  E :  }
 129    :  
 130  E :  void ThreadStateManager::DeleteDeadItems(LIST_ENTRY* dead_items) {
 131  E :    DCHECK(dead_items != NULL);
 132    :    // Ok, let's kill any entries we scavenged.
 133  E :    while (!IsListEmpty(dead_items)) {
 134    :      ThreadStateBase* item =
 135  E :          CONTAINING_RECORD(dead_items->Flink, ThreadStateBase, entry_);
 136  E :      RemoveHeadList(dead_items);
 137  E :      InitializeListHead(&item->entry_);
 138  E :      delete item;
 139  E :    }
 140  E :  }
 141    :  
 142    :  }  // namespace common
 143    :  }  // namespace agent

Coverage information generated Thu Jul 04 09:34:53 2013.