1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2007-2008 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * \file 30bf215546Sopenharmony_ci * Debug buffer manager to detect buffer under- and overflows. 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * \author Jose Fonseca <jfonseca@vmware.com> 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "pipe/p_compiler.h" 37bf215546Sopenharmony_ci#include "util/u_debug.h" 38bf215546Sopenharmony_ci#include "os/os_thread.h" 39bf215546Sopenharmony_ci#include "util/u_math.h" 40bf215546Sopenharmony_ci#include "util/u_memory.h" 41bf215546Sopenharmony_ci#include "util/list.h" 42bf215546Sopenharmony_ci#include "util/u_debug_stack.h" 43bf215546Sopenharmony_ci#include <inttypes.h> 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#include "pb_buffer.h" 46bf215546Sopenharmony_ci#include "pb_bufmgr.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci#ifdef DEBUG 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#define PB_DEBUG_CREATE_BACKTRACE 8 53bf215546Sopenharmony_ci#define PB_DEBUG_MAP_BACKTRACE 8 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci/** 57bf215546Sopenharmony_ci * Convenience macro (type safe). 58bf215546Sopenharmony_ci */ 59bf215546Sopenharmony_ci#define SUPER(__derived) (&(__derived)->base) 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistruct pb_debug_manager; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci/** 66bf215546Sopenharmony_ci * Wrapper around a pipe buffer which adds delayed destruction. 67bf215546Sopenharmony_ci */ 68bf215546Sopenharmony_cistruct pb_debug_buffer 69bf215546Sopenharmony_ci{ 70bf215546Sopenharmony_ci struct pb_buffer base; 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci struct pb_buffer *buffer; 73bf215546Sopenharmony_ci struct pb_debug_manager *mgr; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci pb_size underflow_size; 76bf215546Sopenharmony_ci pb_size overflow_size; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci struct debug_stack_frame create_backtrace[PB_DEBUG_CREATE_BACKTRACE]; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci mtx_t mutex; 81bf215546Sopenharmony_ci unsigned map_count; 82bf215546Sopenharmony_ci struct debug_stack_frame map_backtrace[PB_DEBUG_MAP_BACKTRACE]; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci struct list_head head; 85bf215546Sopenharmony_ci}; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistruct pb_debug_manager 89bf215546Sopenharmony_ci{ 90bf215546Sopenharmony_ci struct pb_manager base; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci struct pb_manager *provider; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci pb_size underflow_size; 95bf215546Sopenharmony_ci pb_size overflow_size; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci mtx_t mutex; 98bf215546Sopenharmony_ci struct list_head list; 99bf215546Sopenharmony_ci}; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic inline struct pb_debug_buffer * 103bf215546Sopenharmony_cipb_debug_buffer(struct pb_buffer *buf) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci assert(buf); 106bf215546Sopenharmony_ci return (struct pb_debug_buffer *)buf; 107bf215546Sopenharmony_ci} 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_cistatic inline struct pb_debug_manager * 111bf215546Sopenharmony_cipb_debug_manager(struct pb_manager *mgr) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci assert(mgr); 114bf215546Sopenharmony_ci return (struct pb_debug_manager *)mgr; 115bf215546Sopenharmony_ci} 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_cistatic const uint8_t random_pattern[32] = { 119bf215546Sopenharmony_ci 0xaf, 0xcf, 0xa5, 0xa2, 0xc2, 0x63, 0x15, 0x1a, 120bf215546Sopenharmony_ci 0x7e, 0xe2, 0x7e, 0x84, 0x15, 0x49, 0xa2, 0x1e, 121bf215546Sopenharmony_ci 0x49, 0x63, 0xf5, 0x52, 0x74, 0x66, 0x9e, 0xc4, 122bf215546Sopenharmony_ci 0x6d, 0xcf, 0x2c, 0x4a, 0x74, 0xe6, 0xfd, 0x94 123bf215546Sopenharmony_ci}; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_cistatic inline void 127bf215546Sopenharmony_cifill_random_pattern(uint8_t *dst, pb_size size) 128bf215546Sopenharmony_ci{ 129bf215546Sopenharmony_ci pb_size i = 0; 130bf215546Sopenharmony_ci while(size--) { 131bf215546Sopenharmony_ci *dst++ = random_pattern[i++]; 132bf215546Sopenharmony_ci i &= sizeof(random_pattern) - 1; 133bf215546Sopenharmony_ci } 134bf215546Sopenharmony_ci} 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_cistatic inline boolean 138bf215546Sopenharmony_cicheck_random_pattern(const uint8_t *dst, pb_size size, 139bf215546Sopenharmony_ci pb_size *min_ofs, pb_size *max_ofs) 140bf215546Sopenharmony_ci{ 141bf215546Sopenharmony_ci boolean result = TRUE; 142bf215546Sopenharmony_ci pb_size i; 143bf215546Sopenharmony_ci *min_ofs = size; 144bf215546Sopenharmony_ci *max_ofs = 0; 145bf215546Sopenharmony_ci for(i = 0; i < size; ++i) { 146bf215546Sopenharmony_ci if(*dst++ != random_pattern[i % sizeof(random_pattern)]) { 147bf215546Sopenharmony_ci *min_ofs = MIN2(*min_ofs, i); 148bf215546Sopenharmony_ci *max_ofs = MAX2(*max_ofs, i); 149bf215546Sopenharmony_ci result = FALSE; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci return result; 153bf215546Sopenharmony_ci} 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic void 157bf215546Sopenharmony_cipb_debug_buffer_fill(struct pb_debug_buffer *buf) 158bf215546Sopenharmony_ci{ 159bf215546Sopenharmony_ci uint8_t *map; 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci map = pb_map(buf->buffer, PB_USAGE_CPU_WRITE, NULL); 162bf215546Sopenharmony_ci assert(map); 163bf215546Sopenharmony_ci if (map) { 164bf215546Sopenharmony_ci fill_random_pattern(map, buf->underflow_size); 165bf215546Sopenharmony_ci fill_random_pattern(map + buf->underflow_size + buf->base.size, 166bf215546Sopenharmony_ci buf->overflow_size); 167bf215546Sopenharmony_ci pb_unmap(buf->buffer); 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci/** 173bf215546Sopenharmony_ci * Check for under/over flows. 174bf215546Sopenharmony_ci * 175bf215546Sopenharmony_ci * Should be called with the buffer unmaped. 176bf215546Sopenharmony_ci */ 177bf215546Sopenharmony_cistatic void 178bf215546Sopenharmony_cipb_debug_buffer_check(struct pb_debug_buffer *buf) 179bf215546Sopenharmony_ci{ 180bf215546Sopenharmony_ci uint8_t *map; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci map = pb_map(buf->buffer, 183bf215546Sopenharmony_ci PB_USAGE_CPU_READ | 184bf215546Sopenharmony_ci PB_USAGE_UNSYNCHRONIZED, NULL); 185bf215546Sopenharmony_ci assert(map); 186bf215546Sopenharmony_ci if (map) { 187bf215546Sopenharmony_ci boolean underflow, overflow; 188bf215546Sopenharmony_ci pb_size min_ofs, max_ofs; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci underflow = !check_random_pattern(map, buf->underflow_size, 191bf215546Sopenharmony_ci &min_ofs, &max_ofs); 192bf215546Sopenharmony_ci if(underflow) { 193bf215546Sopenharmony_ci debug_printf("buffer underflow (offset -%"PRIu64"%s to -%"PRIu64" bytes) detected\n", 194bf215546Sopenharmony_ci buf->underflow_size - min_ofs, 195bf215546Sopenharmony_ci min_ofs == 0 ? "+" : "", 196bf215546Sopenharmony_ci buf->underflow_size - max_ofs); 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci overflow = !check_random_pattern(map + buf->underflow_size + buf->base.size, 200bf215546Sopenharmony_ci buf->overflow_size, 201bf215546Sopenharmony_ci &min_ofs, &max_ofs); 202bf215546Sopenharmony_ci if(overflow) { 203bf215546Sopenharmony_ci debug_printf("buffer overflow (size %"PRIu64" plus offset %"PRIu64" to %"PRIu64"%s bytes) detected\n", 204bf215546Sopenharmony_ci buf->base.size, 205bf215546Sopenharmony_ci min_ofs, 206bf215546Sopenharmony_ci max_ofs, 207bf215546Sopenharmony_ci max_ofs == buf->overflow_size - 1 ? "+" : ""); 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci if(underflow || overflow) 211bf215546Sopenharmony_ci debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci assert(!underflow); 214bf215546Sopenharmony_ci assert(!overflow); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci /* re-fill if not aborted */ 217bf215546Sopenharmony_ci if(underflow) 218bf215546Sopenharmony_ci fill_random_pattern(map, buf->underflow_size); 219bf215546Sopenharmony_ci if(overflow) 220bf215546Sopenharmony_ci fill_random_pattern(map + buf->underflow_size + buf->base.size, 221bf215546Sopenharmony_ci buf->overflow_size); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci pb_unmap(buf->buffer); 224bf215546Sopenharmony_ci } 225bf215546Sopenharmony_ci} 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_cistatic void 229bf215546Sopenharmony_cipb_debug_buffer_destroy(void *winsys, struct pb_buffer *_buf) 230bf215546Sopenharmony_ci{ 231bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 232bf215546Sopenharmony_ci struct pb_debug_manager *mgr = buf->mgr; 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci assert(!pipe_is_referenced(&buf->base.reference)); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci pb_debug_buffer_check(buf); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci mtx_lock(&mgr->mutex); 239bf215546Sopenharmony_ci list_del(&buf->head); 240bf215546Sopenharmony_ci mtx_unlock(&mgr->mutex); 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci mtx_destroy(&buf->mutex); 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci pb_reference(&buf->buffer, NULL); 245bf215546Sopenharmony_ci FREE(buf); 246bf215546Sopenharmony_ci} 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_cistatic void * 250bf215546Sopenharmony_cipb_debug_buffer_map(struct pb_buffer *_buf, 251bf215546Sopenharmony_ci enum pb_usage_flags flags, void *flush_ctx) 252bf215546Sopenharmony_ci{ 253bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 254bf215546Sopenharmony_ci void *map; 255bf215546Sopenharmony_ci 256bf215546Sopenharmony_ci pb_debug_buffer_check(buf); 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci map = pb_map(buf->buffer, flags, flush_ctx); 259bf215546Sopenharmony_ci if (!map) 260bf215546Sopenharmony_ci return NULL; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci mtx_lock(&buf->mutex); 263bf215546Sopenharmony_ci ++buf->map_count; 264bf215546Sopenharmony_ci debug_backtrace_capture(buf->map_backtrace, 1, PB_DEBUG_MAP_BACKTRACE); 265bf215546Sopenharmony_ci mtx_unlock(&buf->mutex); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci return (uint8_t *)map + buf->underflow_size; 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_cistatic void 272bf215546Sopenharmony_cipb_debug_buffer_unmap(struct pb_buffer *_buf) 273bf215546Sopenharmony_ci{ 274bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci mtx_lock(&buf->mutex); 277bf215546Sopenharmony_ci assert(buf->map_count); 278bf215546Sopenharmony_ci if(buf->map_count) 279bf215546Sopenharmony_ci --buf->map_count; 280bf215546Sopenharmony_ci mtx_unlock(&buf->mutex); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci pb_unmap(buf->buffer); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci pb_debug_buffer_check(buf); 285bf215546Sopenharmony_ci} 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cistatic void 289bf215546Sopenharmony_cipb_debug_buffer_get_base_buffer(struct pb_buffer *_buf, 290bf215546Sopenharmony_ci struct pb_buffer **base_buf, 291bf215546Sopenharmony_ci pb_size *offset) 292bf215546Sopenharmony_ci{ 293bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 294bf215546Sopenharmony_ci pb_get_base_buffer(buf->buffer, base_buf, offset); 295bf215546Sopenharmony_ci *offset += buf->underflow_size; 296bf215546Sopenharmony_ci} 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_cistatic enum pipe_error 300bf215546Sopenharmony_cipb_debug_buffer_validate(struct pb_buffer *_buf, 301bf215546Sopenharmony_ci struct pb_validate *vl, 302bf215546Sopenharmony_ci enum pb_usage_flags flags) 303bf215546Sopenharmony_ci{ 304bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci assert((flags & ~PB_USAGE_ALL) == 0); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci mtx_lock(&buf->mutex); 309bf215546Sopenharmony_ci if(buf->map_count) { 310bf215546Sopenharmony_ci debug_printf("%s: attempting to validate a mapped buffer\n", __FUNCTION__); 311bf215546Sopenharmony_ci debug_printf("last map backtrace is\n"); 312bf215546Sopenharmony_ci debug_backtrace_dump(buf->map_backtrace, PB_DEBUG_MAP_BACKTRACE); 313bf215546Sopenharmony_ci } 314bf215546Sopenharmony_ci mtx_unlock(&buf->mutex); 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci pb_debug_buffer_check(buf); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci return pb_validate(buf->buffer, vl, flags); 319bf215546Sopenharmony_ci} 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci 322bf215546Sopenharmony_cistatic void 323bf215546Sopenharmony_cipb_debug_buffer_fence(struct pb_buffer *_buf, 324bf215546Sopenharmony_ci struct pipe_fence_handle *fence) 325bf215546Sopenharmony_ci{ 326bf215546Sopenharmony_ci struct pb_debug_buffer *buf = pb_debug_buffer(_buf); 327bf215546Sopenharmony_ci pb_fence(buf->buffer, fence); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ciconst struct pb_vtbl 332bf215546Sopenharmony_cipb_debug_buffer_vtbl = { 333bf215546Sopenharmony_ci pb_debug_buffer_destroy, 334bf215546Sopenharmony_ci pb_debug_buffer_map, 335bf215546Sopenharmony_ci pb_debug_buffer_unmap, 336bf215546Sopenharmony_ci pb_debug_buffer_validate, 337bf215546Sopenharmony_ci pb_debug_buffer_fence, 338bf215546Sopenharmony_ci pb_debug_buffer_get_base_buffer 339bf215546Sopenharmony_ci}; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_cistatic void 343bf215546Sopenharmony_cipb_debug_manager_dump_locked(struct pb_debug_manager *mgr) 344bf215546Sopenharmony_ci{ 345bf215546Sopenharmony_ci struct list_head *curr, *next; 346bf215546Sopenharmony_ci struct pb_debug_buffer *buf; 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci curr = mgr->list.next; 349bf215546Sopenharmony_ci next = curr->next; 350bf215546Sopenharmony_ci while(curr != &mgr->list) { 351bf215546Sopenharmony_ci buf = list_entry(curr, struct pb_debug_buffer, head); 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci debug_printf("buffer = %p\n", (void *) buf); 354bf215546Sopenharmony_ci debug_printf(" .size = 0x%"PRIx64"\n", buf->base.size); 355bf215546Sopenharmony_ci debug_backtrace_dump(buf->create_backtrace, PB_DEBUG_CREATE_BACKTRACE); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci curr = next; 358bf215546Sopenharmony_ci next = curr->next; 359bf215546Sopenharmony_ci } 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci} 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_cistatic struct pb_buffer * 365bf215546Sopenharmony_cipb_debug_manager_create_buffer(struct pb_manager *_mgr, 366bf215546Sopenharmony_ci pb_size size, 367bf215546Sopenharmony_ci const struct pb_desc *desc) 368bf215546Sopenharmony_ci{ 369bf215546Sopenharmony_ci struct pb_debug_manager *mgr = pb_debug_manager(_mgr); 370bf215546Sopenharmony_ci struct pb_debug_buffer *buf; 371bf215546Sopenharmony_ci struct pb_desc real_desc; 372bf215546Sopenharmony_ci pb_size real_size; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci assert(size); 375bf215546Sopenharmony_ci assert(desc->alignment); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci buf = CALLOC_STRUCT(pb_debug_buffer); 378bf215546Sopenharmony_ci if (!buf) 379bf215546Sopenharmony_ci return NULL; 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci real_size = mgr->underflow_size + size + mgr->overflow_size; 382bf215546Sopenharmony_ci real_desc = *desc; 383bf215546Sopenharmony_ci real_desc.usage |= PB_USAGE_CPU_WRITE; 384bf215546Sopenharmony_ci real_desc.usage |= PB_USAGE_CPU_READ; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci buf->buffer = mgr->provider->create_buffer(mgr->provider, 387bf215546Sopenharmony_ci real_size, 388bf215546Sopenharmony_ci &real_desc); 389bf215546Sopenharmony_ci if(!buf->buffer) { 390bf215546Sopenharmony_ci FREE(buf); 391bf215546Sopenharmony_ci#if 0 392bf215546Sopenharmony_ci mtx_lock(&mgr->mutex); 393bf215546Sopenharmony_ci debug_printf("%s: failed to create buffer\n", __FUNCTION__); 394bf215546Sopenharmony_ci if(!list_is_empty(&mgr->list)) 395bf215546Sopenharmony_ci pb_debug_manager_dump_locked(mgr); 396bf215546Sopenharmony_ci mtx_unlock(&mgr->mutex); 397bf215546Sopenharmony_ci#endif 398bf215546Sopenharmony_ci return NULL; 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci assert(pipe_is_referenced(&buf->buffer->reference)); 402bf215546Sopenharmony_ci assert(pb_check_alignment(real_desc.alignment, 1u << buf->buffer->alignment_log2)); 403bf215546Sopenharmony_ci assert(pb_check_usage(real_desc.usage, buf->buffer->usage)); 404bf215546Sopenharmony_ci assert(buf->buffer->size >= real_size); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci pipe_reference_init(&buf->base.reference, 1); 407bf215546Sopenharmony_ci buf->base.alignment_log2 = util_logbase2(desc->alignment); 408bf215546Sopenharmony_ci buf->base.usage = desc->usage; 409bf215546Sopenharmony_ci buf->base.size = size; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci buf->base.vtbl = &pb_debug_buffer_vtbl; 412bf215546Sopenharmony_ci buf->mgr = mgr; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci buf->underflow_size = mgr->underflow_size; 415bf215546Sopenharmony_ci buf->overflow_size = buf->buffer->size - buf->underflow_size - size; 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_ci debug_backtrace_capture(buf->create_backtrace, 1, PB_DEBUG_CREATE_BACKTRACE); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci pb_debug_buffer_fill(buf); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci (void) mtx_init(&buf->mutex, mtx_plain); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci mtx_lock(&mgr->mutex); 424bf215546Sopenharmony_ci list_addtail(&buf->head, &mgr->list); 425bf215546Sopenharmony_ci mtx_unlock(&mgr->mutex); 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci return &buf->base; 428bf215546Sopenharmony_ci} 429bf215546Sopenharmony_ci 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_cistatic void 432bf215546Sopenharmony_cipb_debug_manager_flush(struct pb_manager *_mgr) 433bf215546Sopenharmony_ci{ 434bf215546Sopenharmony_ci struct pb_debug_manager *mgr = pb_debug_manager(_mgr); 435bf215546Sopenharmony_ci assert(mgr->provider->flush); 436bf215546Sopenharmony_ci if(mgr->provider->flush) 437bf215546Sopenharmony_ci mgr->provider->flush(mgr->provider); 438bf215546Sopenharmony_ci} 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_cistatic void 442bf215546Sopenharmony_cipb_debug_manager_destroy(struct pb_manager *_mgr) 443bf215546Sopenharmony_ci{ 444bf215546Sopenharmony_ci struct pb_debug_manager *mgr = pb_debug_manager(_mgr); 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci mtx_lock(&mgr->mutex); 447bf215546Sopenharmony_ci if(!list_is_empty(&mgr->list)) { 448bf215546Sopenharmony_ci debug_printf("%s: unfreed buffers\n", __FUNCTION__); 449bf215546Sopenharmony_ci pb_debug_manager_dump_locked(mgr); 450bf215546Sopenharmony_ci } 451bf215546Sopenharmony_ci mtx_unlock(&mgr->mutex); 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci mtx_destroy(&mgr->mutex); 454bf215546Sopenharmony_ci mgr->provider->destroy(mgr->provider); 455bf215546Sopenharmony_ci FREE(mgr); 456bf215546Sopenharmony_ci} 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_cistruct pb_manager * 460bf215546Sopenharmony_cipb_debug_manager_create(struct pb_manager *provider, 461bf215546Sopenharmony_ci pb_size underflow_size, pb_size overflow_size) 462bf215546Sopenharmony_ci{ 463bf215546Sopenharmony_ci struct pb_debug_manager *mgr; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci if (!provider) 466bf215546Sopenharmony_ci return NULL; 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci mgr = CALLOC_STRUCT(pb_debug_manager); 469bf215546Sopenharmony_ci if (!mgr) 470bf215546Sopenharmony_ci return NULL; 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci mgr->base.destroy = pb_debug_manager_destroy; 473bf215546Sopenharmony_ci mgr->base.create_buffer = pb_debug_manager_create_buffer; 474bf215546Sopenharmony_ci mgr->base.flush = pb_debug_manager_flush; 475bf215546Sopenharmony_ci mgr->provider = provider; 476bf215546Sopenharmony_ci mgr->underflow_size = underflow_size; 477bf215546Sopenharmony_ci mgr->overflow_size = overflow_size; 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci (void) mtx_init(&mgr->mutex, mtx_plain); 480bf215546Sopenharmony_ci list_inithead(&mgr->list); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci return &mgr->base; 483bf215546Sopenharmony_ci} 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci#else /* !DEBUG */ 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_cistruct pb_manager * 490bf215546Sopenharmony_cipb_debug_manager_create(struct pb_manager *provider, 491bf215546Sopenharmony_ci pb_size underflow_size, pb_size overflow_size) 492bf215546Sopenharmony_ci{ 493bf215546Sopenharmony_ci return provider; 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci#endif /* !DEBUG */ 498