// 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 #include #include #include #include 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