00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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