pb_bufmgr_debug.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  *
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00036 #include "pipe/p_compiler.h"
00037 #include "pipe/p_debug.h"
00038 #include "pipe/p_winsys.h"
00039 #include "pipe/p_thread.h"
00040 #include "util/u_math.h"
00041 #include "util/u_memory.h"
00042 #include "util/u_double_list.h"
00043 #include "util/u_time.h"
00044 
00045 #include "pb_buffer.h"
00046 #include "pb_bufmgr.h"
00047 
00048 
00049 #ifdef DEBUG
00050 
00051 
00055 #define SUPER(__derived) (&(__derived)->base)
00056 
00057 
00058 struct pb_debug_manager;
00059 
00060 
00064 struct pb_debug_buffer
00065 {
00066    struct pb_buffer base;
00067    
00068    struct pb_buffer *buffer;
00069    struct pb_debug_manager *mgr;
00070    
00071    size_t underflow_size;
00072    size_t overflow_size;
00073 };
00074 
00075 
00076 struct pb_debug_manager
00077 {
00078    struct pb_manager base;
00079 
00080    struct pb_manager *provider;
00081 
00082    size_t band_size;
00083 };
00084 
00085 
00086 static INLINE struct pb_debug_buffer *
00087 pb_debug_buffer(struct pb_buffer *buf)
00088 {
00089    assert(buf);
00090    return (struct pb_debug_buffer *)buf;
00091 }
00092 
00093 
00094 static INLINE struct pb_debug_manager *
00095 pb_debug_manager(struct pb_manager *mgr)
00096 {
00097    assert(mgr);
00098    return (struct pb_debug_manager *)mgr;
00099 }
00100 
00101 
00102 static const uint8_t random_pattern[32] = {
00103    0xaf, 0xcf, 0xa5, 0xa2, 0xc2, 0x63, 0x15, 0x1a, 
00104    0x7e, 0xe2, 0x7e, 0x84, 0x15, 0x49, 0xa2, 0x1e,
00105    0x49, 0x63, 0xf5, 0x52, 0x74, 0x66, 0x9e, 0xc4, 
00106    0x6d, 0xcf, 0x2c, 0x4a, 0x74, 0xe6, 0xfd, 0x94
00107 };
00108 
00109 
00110 static INLINE void 
00111 fill_random_pattern(uint8_t *dst, size_t size)
00112 {
00113    size_t i = 0;
00114    while(size--) {
00115       *dst++ = random_pattern[i++];
00116       i &= sizeof(random_pattern) - 1;
00117    }
00118 }
00119 
00120 
00121 static INLINE boolean 
00122 check_random_pattern(const uint8_t *dst, size_t size, 
00123                      size_t *min_ofs, size_t *max_ofs) 
00124 {
00125    boolean result = TRUE;
00126    size_t i;
00127    *min_ofs = size;
00128    *max_ofs = 0;
00129    for(i = 0; i < size; ++i) {
00130       if(*dst++ != random_pattern[i % sizeof(random_pattern)]) {
00131          *min_ofs = MIN2(*min_ofs, i);
00132          *max_ofs = MAX2(*max_ofs, i);
00133          result = FALSE;
00134       }
00135    }
00136    return result;
00137 }
00138 
00139 
00140 static void
00141 pb_debug_buffer_fill(struct pb_debug_buffer *buf)
00142 {
00143    uint8_t *map;
00144    
00145    map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
00146    assert(map);
00147    if(map) {
00148       fill_random_pattern(map, buf->underflow_size);
00149       fill_random_pattern(map + buf->underflow_size + buf->base.base.size, 
00150                           buf->overflow_size);
00151       pb_unmap(buf->buffer);
00152    }
00153 }
00154 
00155 
00161 static void
00162 pb_debug_buffer_check(struct pb_debug_buffer *buf)
00163 {
00164    uint8_t *map;
00165    
00166    map = pb_map(buf->buffer, PIPE_BUFFER_USAGE_CPU_READ);
00167    assert(map);
00168    if(map) {
00169       boolean underflow, overflow;
00170       size_t min_ofs, max_ofs;
00171       
00172       underflow = !check_random_pattern(map, buf->underflow_size, 
00173                                         &min_ofs, &max_ofs);
00174       if(underflow) {
00175          debug_printf("buffer underflow (offset -%u%s to -%u bytes) detected\n",
00176                       buf->underflow_size - min_ofs,
00177                       min_ofs == 0 ? "+" : "",
00178                       buf->underflow_size - max_ofs);
00179       }
00180       
00181       overflow = !check_random_pattern(map + buf->underflow_size + buf->base.base.size, 
00182                                        buf->overflow_size, 
00183                                        &min_ofs, &max_ofs);
00184       if(overflow) {
00185          debug_printf("buffer overflow (size %u plus offset %u to %u%s bytes) detected\n",
00186                       buf->base.base.size,
00187                       min_ofs,
00188                       max_ofs,
00189                       max_ofs == buf->overflow_size - 1 ? "+" : "");
00190       }
00191       
00192       debug_assert(!underflow && !overflow);
00193 
00194       /* re-fill if not aborted */
00195       if(underflow)
00196          fill_random_pattern(map, buf->underflow_size);
00197       if(overflow)
00198          fill_random_pattern(map + buf->underflow_size + buf->base.base.size, 
00199                              buf->overflow_size);
00200 
00201       pb_unmap(buf->buffer);
00202    }
00203 }
00204 
00205 
00206 static void
00207 pb_debug_buffer_destroy(struct pb_buffer *_buf)
00208 {
00209    struct pb_debug_buffer *buf = pb_debug_buffer(_buf);  
00210    
00211    assert(!buf->base.base.refcount);
00212    
00213    pb_debug_buffer_check(buf);
00214 
00215    pb_reference(&buf->buffer, NULL);
00216    FREE(buf);
00217 }
00218 
00219 
00220 static void *
00221 pb_debug_buffer_map(struct pb_buffer *_buf, 
00222                     unsigned flags)
00223 {
00224    struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
00225    void *map;
00226    
00227    pb_debug_buffer_check(buf);
00228 
00229    map = pb_map(buf->buffer, flags);
00230    if(!map)
00231       return NULL;
00232    
00233    return (uint8_t *)map + buf->underflow_size;
00234 }
00235 
00236 
00237 static void
00238 pb_debug_buffer_unmap(struct pb_buffer *_buf)
00239 {
00240    struct pb_debug_buffer *buf = pb_debug_buffer(_buf);   
00241    pb_unmap(buf->buffer);
00242    
00243    pb_debug_buffer_check(buf);
00244 }
00245 
00246 
00247 static void
00248 pb_debug_buffer_get_base_buffer(struct pb_buffer *_buf,
00249                                 struct pb_buffer **base_buf,
00250                                 unsigned *offset)
00251 {
00252    struct pb_debug_buffer *buf = pb_debug_buffer(_buf);
00253    pb_get_base_buffer(buf->buffer, base_buf, offset);
00254    *offset += buf->underflow_size;
00255 }
00256 
00257 
00258 const struct pb_vtbl 
00259 pb_debug_buffer_vtbl = {
00260       pb_debug_buffer_destroy,
00261       pb_debug_buffer_map,
00262       pb_debug_buffer_unmap,
00263       pb_debug_buffer_get_base_buffer
00264 };
00265 
00266 
00267 static struct pb_buffer *
00268 pb_debug_manager_create_buffer(struct pb_manager *_mgr, 
00269                                size_t size,
00270                                const struct pb_desc *desc)
00271 {
00272    struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
00273    struct pb_debug_buffer *buf;
00274    struct pb_desc real_desc;
00275    size_t real_size;
00276    
00277    buf = CALLOC_STRUCT(pb_debug_buffer);
00278    if(!buf)
00279       return NULL;
00280    
00281    real_size = size + 2*mgr->band_size;
00282    real_desc = *desc;
00283    real_desc.usage |= PIPE_BUFFER_USAGE_CPU_WRITE;
00284    real_desc.usage |= PIPE_BUFFER_USAGE_CPU_READ;
00285 
00286    buf->buffer = mgr->provider->create_buffer(mgr->provider, 
00287                                               real_size, 
00288                                               &real_desc);
00289    if(!buf->buffer) {
00290       FREE(buf);
00291       return NULL;
00292    }
00293    
00294    assert(buf->buffer->base.refcount >= 1);
00295    assert(pb_check_alignment(real_desc.alignment, buf->buffer->base.alignment));
00296    assert(pb_check_usage(real_desc.usage, buf->buffer->base.usage));
00297    assert(buf->buffer->base.size >= real_size);
00298    
00299    buf->base.base.refcount = 1;
00300    buf->base.base.alignment = desc->alignment;
00301    buf->base.base.usage = desc->usage;
00302    buf->base.base.size = size;
00303    
00304    buf->base.vtbl = &pb_debug_buffer_vtbl;
00305    buf->mgr = mgr;
00306 
00307    buf->underflow_size = mgr->band_size;
00308    buf->overflow_size = buf->buffer->base.size - buf->underflow_size - size;
00309    
00310    pb_debug_buffer_fill(buf);
00311    
00312    return &buf->base;
00313 }
00314 
00315 
00316 static void
00317 pb_debug_manager_flush(struct pb_manager *_mgr)
00318 {
00319    struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
00320    assert(mgr->provider->flush);
00321    if(mgr->provider->flush)
00322       mgr->provider->flush(mgr->provider);
00323 }
00324 
00325 
00326 static void
00327 pb_debug_manager_destroy(struct pb_manager *_mgr)
00328 {
00329    struct pb_debug_manager *mgr = pb_debug_manager(_mgr);
00330    mgr->provider->destroy(mgr->provider);
00331    FREE(mgr);
00332 }
00333 
00334 
00335 struct pb_manager *
00336 pb_debug_manager_create(struct pb_manager *provider, size_t band_size) 
00337 {
00338    struct pb_debug_manager *mgr;
00339 
00340    if(!provider)
00341       return NULL;
00342    
00343    mgr = CALLOC_STRUCT(pb_debug_manager);
00344    if (!mgr)
00345       return NULL;
00346 
00347    mgr->base.destroy = pb_debug_manager_destroy;
00348    mgr->base.create_buffer = pb_debug_manager_create_buffer;
00349    mgr->base.flush = pb_debug_manager_flush;
00350    mgr->provider = provider;
00351    mgr->band_size = band_size;
00352       
00353    return &mgr->base;
00354 }
00355 
00356 
00357 #else /* !DEBUG */
00358 
00359 
00360 struct pb_manager *
00361 pb_debug_manager_create(struct pb_manager *provider, size_t band_size) 
00362 {
00363    return provider;
00364 }
00365 
00366 
00367 #endif /* !DEBUG */

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4