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
00028
00038 #include "pipe/p_compiler.h"
00039 #include "pipe/p_debug.h"
00040 #include "pipe/p_thread.h"
00041 #include "pipe/p_defines.h"
00042 #include "util/u_memory.h"
00043 #include "util/u_double_list.h"
00044
00045 #include "pb_buffer.h"
00046 #include "pb_bufmgr.h"
00047
00048
00052 #define SUPER(__derived) (&(__derived)->base)
00053
00054
00055 struct pool_pb_manager
00056 {
00057 struct pb_manager base;
00058
00059 pipe_mutex mutex;
00060
00061 size_t bufSize;
00062 size_t bufAlign;
00063
00064 size_t numFree;
00065 size_t numTot;
00066
00067 struct list_head free;
00068
00069 struct pb_buffer *buffer;
00070 void *map;
00071
00072 struct pool_buffer *bufs;
00073 };
00074
00075
00076 static INLINE struct pool_pb_manager *
00077 pool_pb_manager(struct pb_manager *mgr)
00078 {
00079 assert(mgr);
00080 return (struct pool_pb_manager *)mgr;
00081 }
00082
00083
00084 struct pool_buffer
00085 {
00086 struct pb_buffer base;
00087
00088 struct pool_pb_manager *mgr;
00089
00090 struct list_head head;
00091
00092 size_t start;
00093 };
00094
00095
00096 static INLINE struct pool_buffer *
00097 pool_buffer(struct pb_buffer *buf)
00098 {
00099 assert(buf);
00100 return (struct pool_buffer *)buf;
00101 }
00102
00103
00104
00105 static void
00106 pool_buffer_destroy(struct pb_buffer *buf)
00107 {
00108 struct pool_buffer *pool_buf = pool_buffer(buf);
00109 struct pool_pb_manager *pool = pool_buf->mgr;
00110
00111 assert(pool_buf->base.base.refcount == 0);
00112
00113 pipe_mutex_lock(pool->mutex);
00114 LIST_ADD(&pool_buf->head, &pool->free);
00115 pool->numFree++;
00116 pipe_mutex_unlock(pool->mutex);
00117 }
00118
00119
00120 static void *
00121 pool_buffer_map(struct pb_buffer *buf, unsigned flags)
00122 {
00123 struct pool_buffer *pool_buf = pool_buffer(buf);
00124 struct pool_pb_manager *pool = pool_buf->mgr;
00125 void *map;
00126
00127 pipe_mutex_lock(pool->mutex);
00128 map = (unsigned char *) pool->map + pool_buf->start;
00129 pipe_mutex_unlock(pool->mutex);
00130 return map;
00131 }
00132
00133
00134 static void
00135 pool_buffer_unmap(struct pb_buffer *buf)
00136 {
00137
00138 }
00139
00140
00141 static void
00142 pool_buffer_get_base_buffer(struct pb_buffer *buf,
00143 struct pb_buffer **base_buf,
00144 unsigned *offset)
00145 {
00146 struct pool_buffer *pool_buf = pool_buffer(buf);
00147 struct pool_pb_manager *pool = pool_buf->mgr;
00148 pb_get_base_buffer(pool->buffer, base_buf, offset);
00149 *offset += pool_buf->start;
00150 }
00151
00152
00153 static const struct pb_vtbl
00154 pool_buffer_vtbl = {
00155 pool_buffer_destroy,
00156 pool_buffer_map,
00157 pool_buffer_unmap,
00158 pool_buffer_get_base_buffer
00159 };
00160
00161
00162 static struct pb_buffer *
00163 pool_bufmgr_create_buffer(struct pb_manager *mgr,
00164 size_t size,
00165 const struct pb_desc *desc)
00166 {
00167 struct pool_pb_manager *pool = pool_pb_manager(mgr);
00168 struct pool_buffer *pool_buf;
00169 struct list_head *item;
00170
00171 assert(size == pool->bufSize);
00172 assert(pool->bufAlign % desc->alignment == 0);
00173
00174 pipe_mutex_lock(pool->mutex);
00175
00176 if (pool->numFree == 0) {
00177 pipe_mutex_unlock(pool->mutex);
00178 debug_printf("warning: out of fixed size buffer objects\n");
00179 return NULL;
00180 }
00181
00182 item = pool->free.next;
00183
00184 if (item == &pool->free) {
00185 pipe_mutex_unlock(pool->mutex);
00186 debug_printf("error: fixed size buffer pool corruption\n");
00187 return NULL;
00188 }
00189
00190 LIST_DEL(item);
00191 --pool->numFree;
00192
00193 pipe_mutex_unlock(pool->mutex);
00194
00195 pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
00196 assert(pool_buf->base.base.refcount == 0);
00197 pool_buf->base.base.refcount = 1;
00198 pool_buf->base.base.alignment = desc->alignment;
00199 pool_buf->base.base.usage = desc->usage;
00200
00201 return SUPER(pool_buf);
00202 }
00203
00204
00205 static void
00206 pool_bufmgr_flush(struct pb_manager *mgr)
00207 {
00208
00209 }
00210
00211
00212 static void
00213 pool_bufmgr_destroy(struct pb_manager *mgr)
00214 {
00215 struct pool_pb_manager *pool = pool_pb_manager(mgr);
00216 pipe_mutex_lock(pool->mutex);
00217
00218 FREE(pool->bufs);
00219
00220 pb_unmap(pool->buffer);
00221 pb_reference(&pool->buffer, NULL);
00222
00223 pipe_mutex_unlock(pool->mutex);
00224
00225 FREE(mgr);
00226 }
00227
00228
00229 struct pb_manager *
00230 pool_bufmgr_create(struct pb_manager *provider,
00231 size_t numBufs,
00232 size_t bufSize,
00233 const struct pb_desc *desc)
00234 {
00235 struct pool_pb_manager *pool;
00236 struct pool_buffer *pool_buf;
00237 size_t i;
00238
00239 if(!provider)
00240 return NULL;
00241
00242 pool = CALLOC_STRUCT(pool_pb_manager);
00243 if (!pool)
00244 return NULL;
00245
00246 pool->base.destroy = pool_bufmgr_destroy;
00247 pool->base.create_buffer = pool_bufmgr_create_buffer;
00248 pool->base.flush = pool_bufmgr_flush;
00249
00250 LIST_INITHEAD(&pool->free);
00251
00252 pool->numTot = numBufs;
00253 pool->numFree = numBufs;
00254 pool->bufSize = bufSize;
00255 pool->bufAlign = desc->alignment;
00256
00257 pipe_mutex_init(pool->mutex);
00258
00259 pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc);
00260 if (!pool->buffer)
00261 goto failure;
00262
00263 pool->map = pb_map(pool->buffer,
00264 PIPE_BUFFER_USAGE_CPU_READ |
00265 PIPE_BUFFER_USAGE_CPU_WRITE);
00266 if(!pool->map)
00267 goto failure;
00268
00269 pool->bufs = (struct pool_buffer *)CALLOC(numBufs, sizeof(*pool->bufs));
00270 if (!pool->bufs)
00271 goto failure;
00272
00273 pool_buf = pool->bufs;
00274 for (i = 0; i < numBufs; ++i) {
00275 pool_buf->base.base.refcount = 0;
00276 pool_buf->base.base.alignment = 0;
00277 pool_buf->base.base.usage = 0;
00278 pool_buf->base.base.size = bufSize;
00279 pool_buf->base.vtbl = &pool_buffer_vtbl;
00280 pool_buf->mgr = pool;
00281 pool_buf->start = i * bufSize;
00282 LIST_ADDTAIL(&pool_buf->head, &pool->free);
00283 pool_buf++;
00284 }
00285
00286 return SUPER(pool);
00287
00288 failure:
00289 if(pool->bufs)
00290 FREE(pool->bufs);
00291 if(pool->map)
00292 pb_unmap(pool->buffer);
00293 if(pool->buffer)
00294 pb_reference(&pool->buffer, NULL);
00295 if(pool)
00296 FREE(pool);
00297 return NULL;
00298 }