LCOV - code coverage report
Current view: directory - src/shared/platform/win - lock.cc (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 54 54 100.0 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2008 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : 
       8                 : // Provide place to put profiling methods for the
       9                 : // Lock class.
      10                 : // The Lock class is used everywhere, and hence any changes
      11                 : // to lock.h tend to require a complete rebuild.  To facilitate
      12                 : // profiler development, all the profiling methods are listed
      13                 : // here.  Note that they are only instantiated in a debug
      14                 : // build, and the header provides all the trivial implementations
      15                 : // in a production build.
      16                 : #include "native_client/src/include/portability.h"
      17                 : #include "native_client/src/shared/platform/win/lock.h"
      18                 : #include "native_client/src/shared/platform/nacl_log.h"
      19                 : #include "native_client/src/shared/platform/nacl_check.h"
      20                 : 
      21                 : NaCl::Lock::Lock()
      22                 :     : lock_()
      23              28 :     , recursion_count_shadow_(0) {
      24                 : #ifndef NDEBUG
      25              28 :   recursion_used_ = false;
      26              28 :   acquisition_count_ = 0;
      27              28 :   contention_count_ = 0;
      28                 : #endif
      29              28 : }
      30                 : 
      31              23 : NaCl::Lock::~Lock() {
      32                 : #ifndef NDEBUG
      33                 :   // There should be no one to contend for the lock,
      34                 :   // ...but we need the memory barrier to get a good value.
      35              23 :   lock_.Lock();
      36              23 :   int final_recursion_count = recursion_count_shadow_;
      37              23 :   lock_.Unlock();
      38                 : 
      39                 :   // Allow unit test exception only at end of method.
      40              23 :   DCHECK(0 == final_recursion_count);
      41                 : #endif
      42              23 : }
      43                 : 
      44              28 : void NaCl::Lock::Acquire() {
      45                 : #ifdef NDEBUG
      46                 :   lock_.Lock();
      47                 :   recursion_count_shadow_++;
      48                 : #else  // NDEBUG
      49              28 :   if (!lock_.Try()) {
      50                 :     // We have contention.
      51               3 :     lock_.Lock();
      52               3 :     contention_count_++;
      53                 :   }
      54                 :   // ONLY access data after locking.
      55              28 :   recursion_count_shadow_++;
      56              28 :   if (1 == recursion_count_shadow_)
      57              28 :     acquisition_count_++;
      58               1 :   else if (2 == recursion_count_shadow_ && !recursion_used_)
      59                 :     // Usage Note: Set a break point to debug.
      60               1 :     recursion_used_ = true;
      61                 : #endif  // NDEBUG
      62              28 : }
      63                 : 
      64              28 : void NaCl::Lock::Release() {
      65              28 :   --recursion_count_shadow_;  // ONLY access while lock is still held.
      66                 : #ifndef NDEBUG
      67                 :   // DCHECK(0 <= recursion_count_shadow_);
      68                 : #endif
      69              28 :   lock_.Unlock();
      70              28 : }
      71                 : 
      72               1 : bool NaCl::Lock::Try() {
      73                 :   bool res;
      74                 : #ifdef NDEBUG
      75                 :   res = lock_.Try();
      76                 :   if (res)
      77                 :     recursion_count_shadow_++;
      78                 : #else  // NDEBUG
      79               1 :   res = lock_.Try();
      80                 :   // ONLY access data after locking.
      81               1 :   if (res) {
      82               1 :     recursion_count_shadow_++;
      83               1 :     if (1 == recursion_count_shadow_)
      84               1 :       acquisition_count_++;
      85               1 :     else if (2 == recursion_count_shadow_ && !recursion_used_)
      86                 :       // Usage Note: Set a break point to debug.
      87               1 :       recursion_used_ = true;
      88                 :   }
      89                 : #endif  // NDEBUG
      90               1 :   return res;
      91               1 : }
      92                 : 
      93                 : // GetCurrentThreadRecursionCount returns the number of nested Acquire() calls
      94                 : // that have been made by the current thread holding this lock.  The calling
      95                 : // thread is ***REQUIRED*** to be *currently* holding the lock.   If that
      96                 : // calling requirement is violated, the return value is not well defined.
      97                 : // Return results are guaranteed correct if the caller has acquired this lock.
      98                 : // The return results might be incorrect otherwise.
      99                 : // This method is designed to be fast in non-debug mode by co-opting
     100                 : // synchronization using lock_ (no additional synchronization is used), but in
     101                 : // debug mode it slowly and carefully validates the requirement (and fires a
     102                 : // a DCHECK if it was called incorrectly).
     103               2 : int32_t NaCl::Lock::GetCurrentThreadRecursionCount() {
     104                 :   // We hold lock, so this *is* correct value.
     105               2 :   int32_t temp = recursion_count_shadow_;
     106                 : 
     107                 : #ifndef NDEBUG
     108               2 :   lock_.Lock();
     109               2 :   temp = recursion_count_shadow_;
     110               2 :   lock_.Unlock();
     111                 :   // Unit tests catch an exception, so we need to be careful to test
     112                 :   // outside the critical section, since the Leave would be skipped!?!
     113                 : 
     114                 :   // If this DCHECK fails, then the most probable cause is:
     115                 :   // This method was called by class AutoUnlock during processing of a
     116                 :   // Wait() call made into the ConditonVariable class. That call to
     117                 :   // Wait() was made (incorrectly) without first Aquiring this Lock
     118                 :   // instance.
     119               2 :   DCHECK(temp >= 1);  // Allow unit test exception only at end of method.
     120                 : #endif  // DEBUG
     121                 : 
     122               2 :   return temp;
     123               2 : }
     124                 : 
     125                 : 
     126               2 : NaCl::AutoUnlock::AutoUnlock(Lock& lock) : lock_(&lock), release_count_(0) {
     127                 :   // We require our caller have the lock, so we can call for recursion count.
     128                 :   // CRITICALLY: Fetch value before we release the lock.
     129               2 :   int32_t count = lock_->GetCurrentThreadRecursionCount();
     130                 :   // DCHECK(count > 0);  // Make sure we owned the lock.
     131               2 :   while (count-- > 0) {
     132               2 :     release_count_++;
     133               2 :     lock_->Release();
     134               2 :   }
     135               2 : }
     136                 : 
     137               2 : NaCl::AutoUnlock::~AutoUnlock() {
     138                 :   // DCHECK(release_count_ >= 0);
     139               2 :   while (release_count_-- > 0)
     140               2 :     lock_->Acquire();
     141               2 : }

Generated by: LCOV version 1.7