pb_bufmgr_pool.c revision 92fcbf6e7bc622dcace226bb70ff6d5cdbdbaecb
1/************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 * USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * The above copyright notice and this permission notice (including the 23 * next paragraph) shall be included in all copies or substantial portions 24 * of the Software. 25 * 26 * 27 **************************************************************************/ 28 29/** 30 * \file 31 * Batch buffer pool management. 32 * 33 * \author Jos� Fonseca <jrfonseca-at-tungstengraphics-dot-com> 34 * \author Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com> 35 */ 36 37 38#include "linked_list.h" 39 40#include "p_compiler.h" 41#include "p_debug.h" 42#include "p_thread.h" 43#include "p_defines.h" 44#include "p_util.h" 45 46#include "pb_buffer.h" 47#include "pb_bufmgr.h" 48 49 50/** 51 * Convenience macro (type safe). 52 */ 53#define SUPER(__derived) (&(__derived)->base) 54 55 56struct pool_pb_manager 57{ 58 struct pb_manager base; 59 60 _glthread_Mutex mutex; 61 62 size_t bufSize; 63 size_t bufAlign; 64 65 size_t numFree; 66 size_t numTot; 67 68 struct list_head free; 69 70 struct pb_buffer *buffer; 71 void *map; 72 73 struct pool_buffer *bufs; 74}; 75 76 77static INLINE struct pool_pb_manager * 78pool_pb_manager(struct pb_manager *mgr) 79{ 80 assert(mgr); 81 return (struct pool_pb_manager *)mgr; 82} 83 84 85struct pool_buffer 86{ 87 struct pb_buffer base; 88 89 struct pool_pb_manager *mgr; 90 91 struct list_head head; 92 93 size_t start; 94}; 95 96 97static INLINE struct pool_buffer * 98pool_buffer(struct pb_buffer *buf) 99{ 100 assert(buf); 101 return (struct pool_buffer *)buf; 102} 103 104 105 106static void 107pool_buffer_destroy(struct pb_buffer *buf) 108{ 109 struct pool_buffer *pool_buf = pool_buffer(buf); 110 struct pool_pb_manager *pool = pool_buf->mgr; 111 112 assert(pool_buf->base.base.refcount == 0); 113 114 _glthread_LOCK_MUTEX(pool->mutex); 115 LIST_ADD(&pool_buf->head, &pool->free); 116 pool->numFree++; 117 _glthread_UNLOCK_MUTEX(pool->mutex); 118} 119 120 121static void * 122pool_buffer_map(struct pb_buffer *buf, unsigned flags) 123{ 124 struct pool_buffer *pool_buf = pool_buffer(buf); 125 struct pool_pb_manager *pool = pool_buf->mgr; 126 void *map; 127 128 _glthread_LOCK_MUTEX(pool->mutex); 129 map = (unsigned char *) pool->map + pool_buf->start; 130 _glthread_UNLOCK_MUTEX(pool->mutex); 131 return map; 132} 133 134 135static void 136pool_buffer_unmap(struct pb_buffer *buf) 137{ 138 /* No-op */ 139} 140 141 142static void 143pool_buffer_get_base_buffer(struct pb_buffer *buf, 144 struct pb_buffer **base_buf, 145 unsigned *offset) 146{ 147 struct pool_buffer *pool_buf = pool_buffer(buf); 148 struct pool_pb_manager *pool = pool_buf->mgr; 149 pb_get_base_buffer(pool->buffer, base_buf, offset); 150 *offset += pool_buf->start; 151} 152 153 154static const struct pb_vtbl 155pool_buffer_vtbl = { 156 pool_buffer_destroy, 157 pool_buffer_map, 158 pool_buffer_unmap, 159 pool_buffer_get_base_buffer 160}; 161 162 163static struct pb_buffer * 164pool_bufmgr_create_buffer(struct pb_manager *mgr, 165 size_t size, 166 const struct pb_desc *desc) 167{ 168 struct pool_pb_manager *pool = pool_pb_manager(mgr); 169 struct pool_buffer *pool_buf; 170 struct list_head *item; 171 172 assert(size == pool->bufSize); 173 assert(pool->bufAlign % desc->alignment == 0); 174 175 _glthread_LOCK_MUTEX(pool->mutex); 176 177 if (pool->numFree == 0) { 178 _glthread_UNLOCK_MUTEX(pool->mutex); 179 debug_printf("warning: out of fixed size buffer objects\n"); 180 return NULL; 181 } 182 183 item = pool->free.next; 184 185 if (item == &pool->free) { 186 _glthread_UNLOCK_MUTEX(pool->mutex); 187 debug_printf("error: fixed size buffer pool corruption\n"); 188 return NULL; 189 } 190 191 LIST_DEL(item); 192 --pool->numFree; 193 194 _glthread_UNLOCK_MUTEX(pool->mutex); 195 196 pool_buf = LIST_ENTRY(struct pool_buffer, item, head); 197 assert(pool_buf->base.base.refcount == 0); 198 pool_buf->base.base.refcount = 1; 199 pool_buf->base.base.alignment = desc->alignment; 200 pool_buf->base.base.usage = desc->usage; 201 202 return SUPER(pool_buf); 203} 204 205 206static void 207pool_bufmgr_destroy(struct pb_manager *mgr) 208{ 209 struct pool_pb_manager *pool = pool_pb_manager(mgr); 210 _glthread_LOCK_MUTEX(pool->mutex); 211 212 FREE(pool->bufs); 213 214 pb_unmap(pool->buffer); 215 pb_reference(&pool->buffer, NULL); 216 217 _glthread_UNLOCK_MUTEX(pool->mutex); 218 219 FREE(mgr); 220} 221 222 223struct pb_manager * 224pool_bufmgr_create(struct pb_manager *provider, 225 size_t numBufs, 226 size_t bufSize, 227 const struct pb_desc *desc) 228{ 229 struct pool_pb_manager *pool; 230 struct pool_buffer *pool_buf; 231 size_t i; 232 233 pool = (struct pool_pb_manager *)CALLOC(1, sizeof(*pool)); 234 if (!pool) 235 return NULL; 236 237 pool->base.destroy = pool_bufmgr_destroy; 238 pool->base.create_buffer = pool_bufmgr_create_buffer; 239 240 LIST_INITHEAD(&pool->free); 241 242 pool->numTot = numBufs; 243 pool->numFree = numBufs; 244 pool->bufSize = bufSize; 245 pool->bufAlign = desc->alignment; 246 247 _glthread_INIT_MUTEX(pool->mutex); 248 249 pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc); 250 if (!pool->buffer) 251 goto failure; 252 253 pool->map = pb_map(pool->buffer, 254 PIPE_BUFFER_USAGE_CPU_READ | 255 PIPE_BUFFER_USAGE_CPU_WRITE); 256 if(!pool->map) 257 goto failure; 258 259 pool->bufs = (struct pool_buffer *)CALLOC(numBufs, sizeof(*pool->bufs)); 260 if (!pool->bufs) 261 goto failure; 262 263 pool_buf = pool->bufs; 264 for (i = 0; i < numBufs; ++i) { 265 pool_buf->base.base.refcount = 0; 266 pool_buf->base.base.alignment = 0; 267 pool_buf->base.base.usage = 0; 268 pool_buf->base.base.size = bufSize; 269 pool_buf->base.vtbl = &pool_buffer_vtbl; 270 pool_buf->mgr = pool; 271 pool_buf->start = i * bufSize; 272 LIST_ADDTAIL(&pool_buf->head, &pool->free); 273 pool_buf++; 274 } 275 276 return SUPER(pool); 277 278failure: 279 if(pool->bufs) 280 FREE(pool->bufs); 281 if(pool->map) 282 pb_unmap(pool->buffer); 283 if(pool->buffer) 284 pb_reference(&pool->buffer, NULL); 285 if(pool) 286 FREE(pool); 287 return NULL; 288} 289