diff options
Diffstat (limited to 'src/google/protobuf/new_delete_capture.cc')
-rw-r--r-- | src/google/protobuf/new_delete_capture.cc | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc new file mode 100644 index 00000000..baf42ffe --- /dev/null +++ b/src/google/protobuf/new_delete_capture.cc @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file exists for testing allocation behavior when using arenas by hooking +// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc. + +#include <google/protobuf/new_delete_capture.h> + +#include <pthread.h> + +#include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/malloc_hook.h> +#include <google/protobuf/stubs/spinlock.h> + +namespace google { +namespace { + +pthread_t gthread; +protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL; +SpinLock gspinlock(base::LINKER_INITIALIZED); + +} // namespace + +namespace protobuf_unittest { + +NewDeleteCapture::NewDeleteCapture() + : alloc_count_(0), + alloc_size_(0), + alloc_ptr_(NULL), + free_count_(0), + free_ptr_(NULL) {} + +NewDeleteCapture::~NewDeleteCapture() { Unhook(); } + +void NewDeleteCapture::Reset() { + alloc_count_ = 0; + alloc_size_ = 0; + free_count_ = 0; + alloc_ptr_ = NULL; + free_ptr_ = NULL; +} + +bool NewDeleteCapture::Hook(bool reset) { + SpinLockHolder spinlock(&gspinlock); + if (ghooked_instance != this) { + GOOGLE_CHECK(ghooked_instance == NULL) + << " NewDeleteCapture can have only 1 active instance"; + GOOGLE_CHECK(MallocHook::AddNewHook(NewHook)); + GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook)); + gthread = pthread_self(); + ghooked_instance = this; + if (reset) { + Reset(); + } + return true; + } + return false; +} + +bool NewDeleteCapture::Unhook() { + SpinLockHolder spinlock(&gspinlock); + if (ghooked_instance == this) { + gthread = pthread_t(); + ghooked_instance = NULL; + GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook)); + GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook)); + return true; + } + return false; +} + +void NewDeleteCapture::NewHook(const void *ptr, size_t size) { + SpinLockHolder spinlock(&gspinlock); + if (gthread == pthread_self()) { + auto &rthis = *ghooked_instance; + if (++rthis.alloc_count_ == 1) { + rthis.alloc_size_ = size; + rthis.alloc_ptr_ = ptr; + } + } +} + +void NewDeleteCapture::DeleteHook(const void *ptr) { + SpinLockHolder spinlock(&gspinlock); + if (gthread == pthread_self()) { + auto &rthis = *ghooked_instance; + if (++rthis.free_count_ == 1) { + rthis.free_ptr_ = ptr; + } + } +} + +} // namespace protobuf_unittest +} // namespace google |