u_debug_refcnt.c revision 52ad45677dd3d8a50836edea9f5841aa12d70419
169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com/************************************************************************** 2b0c97975894a5eebebf9d93147cdd941a3accb63fbarchard@google.com * 369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * Copyright 2010 Luca Barbieri 469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * 569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * Permission is hereby granted, free of charge, to any person obtaining 669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * a copy of this software and associated documentation files (the 7cde587092fef0dbed2c35602f30b79e7b892e766fbarchard@google.com * "Software"), to deal in the Software without restriction, including 869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * without limitation the rights to use, copy, modify, merge, publish, 969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * distribute, sublicense, and/or sell copies of the Software, and to 1069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * permit persons to whom the Software is furnished to do so, subject to 1169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * the following conditions: 1269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * 1364ce0ab544591b1e26ae6d276932cacdb8137071fbarchard@google.com * The above copyright notice and this permission notice (including the 1469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * next paragraph) shall be included in all copies or substantial 152c8108e6c2c6fa0c62670a70be7ef6f59cf03848fbarchard@google.com * portions of the Software. 162c8108e6c2c6fa0c62670a70be7ef6f59cf03848fbarchard@google.com * 172c8108e6c2c6fa0c62670a70be7ef6f59cf03848fbarchard@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18d7c7bfac57ce1775d6424865d8d4ec8b278070bafbarchard@google.com * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 21133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22d7c7bfac57ce1775d6424865d8d4ec8b278070bafbarchard@google.com * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com * 25ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com **************************************************************************/ 26ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com 27ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER)) 28ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com 2969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output 3069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * on Linux, use tools/addr2line.sh to postprocess it before anything else 31ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com **/ 32ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com#include <util/u_debug.h> 33ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com#include <util/u_debug_refcnt.h> 34ae997018e5c5f909e5400664052cb71ab097aa35fbarchard@google.com#include <util/u_debug_stack.h> 35d7c7bfac57ce1775d6424865d8d4ec8b278070bafbarchard@google.com#include <util/u_debug_symbol.h> 36e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com#include <util/u_string.h> 3769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com#include <util/u_hash_table.h> 3869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com#include <os/os_thread.h> 39133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com#include <os/os_stream.h> 4069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 4169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comint debug_refcnt_state; 4269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 4369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstruct os_stream* stream; 44133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com 4569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */ 4669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.compipe_static_mutex(serials_mutex); 4769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 4869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic struct util_hash_table* serials_hash; 4969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic unsigned serials_last; 5069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 5169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic unsigned hash_ptr(void* p) 5269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com{ 538b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com return (unsigned)(uintptr_t)p; 548b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com} 558b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com 568b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.comstatic int compare_ptr(void* a, void* b) 578b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com{ 588b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com if(a == b) 598b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com return 0; 608b857c0ac6f0e8cb0fc0b9410ea0d15b3afda4abfbarchard@google.com else if(a < b) 6169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com return -1; 62db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com else 6369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com return 1; 6469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com} 6569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 6669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic boolean debug_serial(void* p, unsigned* pserial) 6769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com{ 68e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com unsigned serial; 69e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com boolean found = TRUE; 70133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com#ifdef PIPE_SUBSYSTEM_WINDOWS_USER 71e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com static boolean first = TRUE; 7269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 7369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if (first) { 7469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com pipe_mutex_init(serials_mutex); 75133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com first = FALSE; 7669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 7769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com#endif 7869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 7969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com pipe_mutex_lock(serials_mutex); 8069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(!serials_hash) 8169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com serials_hash = util_hash_table_create(hash_ptr, compare_ptr); 82e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p); 83e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com if(!serial) 8469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 8569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com /* time to stop logging... (you'll have a 100 GB logfile at least at this point) 8669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com * TODO: avoid this 8769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com */ 8869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com serial = ++serials_last; 89e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com if(!serial) 90e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com { 91e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com debug_error("More than 2^32 objects detected, aborting.\n"); 92133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com os_abort(); 93e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com } 94133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com 9569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial); 9669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com found = FALSE; 9769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 98db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com pipe_mutex_unlock(serials_mutex); 9969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com *pserial = serial; 100db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com return found; 10169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com} 10269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 10369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic void debug_serial_delete(void* p) 104a1f5254a955c5c32484b56822596a4e3368e8eb7fbarchard@google.com{ 10569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com pipe_mutex_lock(serials_mutex); 10669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com util_hash_table_remove(serials_hash, p); 107133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com pipe_mutex_unlock(serials_mutex); 10869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com} 10969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 11069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com#define STACK_LEN 64 111db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com 11269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comstatic void dump_stack(const char* symbols[STACK_LEN]) 113133adc46470722b24fdac30d7537d5009e61ef0cfbarchard@google.com{ 114e2a55aff59ffa81d553a31c0f0b735f9baa40749fbarchard@google.com unsigned i; 11569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com for(i = 0; i < STACK_LEN; ++i) 116db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com { 11769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(symbols[i]) 11869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_printf(stream, "%s\n", symbols[i]); 11969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 12069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_write(stream, "\n", 1); 12169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com} 12269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 12369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.comvoid debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change) 12469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com{ 12569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(debug_refcnt_state < 0) 12669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com return; 12769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 12869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(!debug_refcnt_state) 12969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 13069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL); 13169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(filename && filename[0]) 13269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com stream = os_file_stream_create(filename); 13369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 13469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(stream) 13569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com debug_refcnt_state = 1; 13669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com else 13769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com debug_refcnt_state = -1; 13869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 13969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 14069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(debug_refcnt_state > 0) 14169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 14269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com struct debug_stack_frame frames[STACK_LEN]; 14369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com const char* symbols[STACK_LEN]; 14469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com char buf[1024]; 14569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 146db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com unsigned i; 14769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com unsigned refcnt = p->count; 14869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com unsigned serial; 149db73518b19f73a3975b4fd58e9d17c8215a39d98fbarchard@google.com boolean existing = debug_serial((void*)p, &serial); 15069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 15169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com debug_backtrace_capture(frames, 1, STACK_LEN); 15269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com for(i = 0; i < STACK_LEN; ++i) 15369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 15469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(frames[i].function) 15569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com symbols[i] = debug_symbol_name_cached(frames[i].function); 15669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com else 15769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com symbols[i] = 0; 15869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 15969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 16069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com get_desc(buf, p); 16169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 16269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(!existing) 16369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 16469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_printf(stream, "<%s> %p %u Create\n", buf, p, serial); 16569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com dump_stack(symbols); 16669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 16769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com /* this is there to provide a gradual change even if we don't see the initialization */ 16869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com for(i = 1; i <= refcnt - change; ++i) 16969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 17069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_printf(stream, "<%s> %p %u AddRef %u\n", buf, p, serial, i); 17169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com dump_stack(symbols); 17269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 17369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 17469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 17569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(change) 17669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 17769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_printf(stream, "<%s> %p %u %s %u\n", buf, p, serial, change > 0 ? "AddRef" : "Release", refcnt); 17869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com dump_stack(symbols); 17969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 18069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 18169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com if(!refcnt) 18269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com { 18369fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com debug_serial_delete((void*)p); 18469fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_printf(stream, "<%s> %p %u Destroy\n", buf, p, serial); 18569fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com dump_stack(symbols); 18669fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 18769fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com 18869fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com os_stream_flush(stream); 18969fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com } 19069fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com} 19169fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com#endif 19269fe6bd1ff8234b3535a3fe9266d2f973fd5e414fbarchard@google.com