Go to the source code of this file.
Data Structures | |
struct | pb_cache_buffer |
Wrapper around a pipe buffer which adds delayed destruction. More... | |
struct | pb_cache_manager |
Defines | |
#define | SUPER(__derived) (&(__derived)->base) |
Convenience macro (type safe). | |
Functions | |
static struct pb_cache_buffer * | pb_cache_buffer (struct pb_buffer *buf) |
static struct pb_cache_manager * | pb_cache_manager (struct pb_manager *mgr) |
static void | _pb_cache_buffer_destroy (struct pb_cache_buffer *buf) |
Actually destroy the buffer. | |
static void | _pb_cache_buffer_list_check_free (struct pb_cache_manager *mgr) |
Free as many cache buffers from the list head as possible. | |
static void | pb_cache_buffer_destroy (struct pb_buffer *_buf) |
static void * | pb_cache_buffer_map (struct pb_buffer *_buf, unsigned flags) |
static void | pb_cache_buffer_unmap (struct pb_buffer *_buf) |
static void | pb_cache_buffer_get_base_buffer (struct pb_buffer *_buf, struct pb_buffer **base_buf, unsigned *offset) |
static boolean | pb_cache_is_buffer_compat (struct pb_cache_buffer *buf, size_t size, const struct pb_desc *desc) |
static struct pb_buffer * | pb_cache_manager_create_buffer (struct pb_manager *_mgr, size_t size, const struct pb_desc *desc) |
static void | pb_cache_manager_flush (struct pb_manager *_mgr) |
static void | pb_cache_manager_destroy (struct pb_manager *mgr) |
struct pb_manager * | pb_cache_manager_create (struct pb_manager *provider, unsigned usecs) |
Time-based buffer cache. | |
Variables | |
struct pb_vtbl | pb_cache_buffer_vtbl |
Definition in file pb_bufmgr_cache.c.
#define SUPER | ( | __derived | ) | (&(__derived)->base) |
static void _pb_cache_buffer_destroy | ( | struct pb_cache_buffer * | buf | ) | [static] |
Actually destroy the buffer.
Definition at line 109 of file pb_bufmgr_cache.c.
References assert, pb_buffer::base, pb_cache_buffer::base, pb_cache_buffer::buffer, FREE, pb_cache_buffer::head, LIST_DEL, pb_cache_buffer::mgr, pb_cache_manager::numDelayed, pb_reference(), and pipe_buffer::refcount.
00110 { 00111 struct pb_cache_manager *mgr = buf->mgr; 00112 00113 LIST_DEL(&buf->head); 00114 assert(mgr->numDelayed); 00115 --mgr->numDelayed; 00116 assert(!buf->base.base.refcount); 00117 pb_reference(&buf->buffer, NULL); 00118 FREE(buf); 00119 }
static void _pb_cache_buffer_list_check_free | ( | struct pb_cache_manager * | mgr | ) | [static] |
Free as many cache buffers from the list head as possible.
Definition at line 126 of file pb_bufmgr_cache.c.
References _pb_cache_buffer_destroy(), pb_cache_manager::delayed, pb_cache_buffer::end, LIST_ENTRY, list_head::next, util_time_get(), and util_time_timeout().
00127 { 00128 struct list_head *curr, *next; 00129 struct pb_cache_buffer *buf; 00130 struct util_time now; 00131 00132 util_time_get(&now); 00133 00134 curr = mgr->delayed.next; 00135 next = curr->next; 00136 while(curr != &mgr->delayed) { 00137 buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); 00138 00139 if(!util_time_timeout(&buf->start, &buf->end, &now)) 00140 break; 00141 00142 _pb_cache_buffer_destroy(buf); 00143 00144 curr = next; 00145 next = curr->next; 00146 } 00147 }
static struct pb_cache_buffer* pb_cache_buffer | ( | struct pb_buffer * | buf | ) | [static, read] |
Definition at line 90 of file pb_bufmgr_cache.c.
References assert.
00091 { 00092 assert(buf); 00093 return (struct pb_cache_buffer *)buf; 00094 }
static void pb_cache_buffer_destroy | ( | struct pb_buffer * | _buf | ) | [static] |
Definition at line 151 of file pb_bufmgr_cache.c.
References _pb_cache_buffer_list_check_free(), assert, pb_buffer::base, pb_cache_buffer::base, pb_cache_manager::delayed, pb_cache_buffer::end, pb_cache_buffer::head, LIST_ADDTAIL, pb_cache_buffer::mgr, pb_cache_manager::mutex, pb_cache_manager::numDelayed, pb_cache_buffer(), pipe_mutex_lock, pipe_mutex_unlock, pipe_buffer::refcount, pb_cache_manager::usecs, util_time_add(), and util_time_get().
00152 { 00153 struct pb_cache_buffer *buf = pb_cache_buffer(_buf); 00154 struct pb_cache_manager *mgr = buf->mgr; 00155 00156 pipe_mutex_lock(mgr->mutex); 00157 assert(buf->base.base.refcount == 0); 00158 00159 _pb_cache_buffer_list_check_free(mgr); 00160 00161 util_time_get(&buf->start); 00162 util_time_add(&buf->start, mgr->usecs, &buf->end); 00163 LIST_ADDTAIL(&buf->head, &mgr->delayed); 00164 ++mgr->numDelayed; 00165 pipe_mutex_unlock(mgr->mutex); 00166 }
static void pb_cache_buffer_get_base_buffer | ( | struct pb_buffer * | _buf, | |
struct pb_buffer ** | base_buf, | |||
unsigned * | offset | |||
) | [static] |
Definition at line 187 of file pb_bufmgr_cache.c.
References pb_cache_buffer::buffer, pb_cache_buffer(), and pb_get_base_buffer().
00190 { 00191 struct pb_cache_buffer *buf = pb_cache_buffer(_buf); 00192 pb_get_base_buffer(buf->buffer, base_buf, offset); 00193 }
static void* pb_cache_buffer_map | ( | struct pb_buffer * | _buf, | |
unsigned | flags | |||
) | [static] |
Definition at line 170 of file pb_bufmgr_cache.c.
References pb_cache_buffer::buffer, pb_cache_buffer(), and pb_map().
00172 { 00173 struct pb_cache_buffer *buf = pb_cache_buffer(_buf); 00174 return pb_map(buf->buffer, flags); 00175 }
static void pb_cache_buffer_unmap | ( | struct pb_buffer * | _buf | ) | [static] |
Definition at line 179 of file pb_bufmgr_cache.c.
References pb_cache_buffer::buffer, pb_cache_buffer(), and pb_unmap().
00180 { 00181 struct pb_cache_buffer *buf = pb_cache_buffer(_buf); 00182 pb_unmap(buf->buffer); 00183 }
static boolean pb_cache_is_buffer_compat | ( | struct pb_cache_buffer * | buf, | |
size_t | size, | |||
const struct pb_desc * | desc | |||
) | [static] |
Definition at line 206 of file pb_bufmgr_cache.c.
References pipe_buffer::alignment, pb_desc::alignment, pb_buffer::base, pb_cache_buffer::base, FALSE, pb_check_alignment(), pb_check_usage(), pipe_buffer::size, TRUE, pipe_buffer::usage, and pb_desc::usage.
00209 { 00210 if(buf->base.base.size < size) 00211 return FALSE; 00212 00213 /* be lenient with size */ 00214 if(buf->base.base.size >= 2*size) 00215 return FALSE; 00216 00217 if(!pb_check_alignment(desc->alignment, buf->base.base.alignment)) 00218 return FALSE; 00219 00220 if(!pb_check_usage(desc->usage, buf->base.base.usage)) 00221 return FALSE; 00222 00223 return TRUE; 00224 }
static struct pb_cache_manager* pb_cache_manager | ( | struct pb_manager * | mgr | ) | [static, read] |
Definition at line 98 of file pb_bufmgr_cache.c.
References assert.
00099 { 00100 assert(mgr); 00101 return (struct pb_cache_manager *)mgr; 00102 }
struct pb_manager* pb_cache_manager_create | ( | struct pb_manager * | provider, | |
unsigned | usecs | |||
) | [read] |
Time-based buffer cache.
This manager keeps a cache of destroyed buffers during a time interval.
Definition at line 342 of file pb_bufmgr_cache.c.
References pb_cache_manager::base, CALLOC_STRUCT, pb_manager::create_buffer, pb_cache_manager::delayed, pb_manager::destroy, pb_manager::flush, LIST_INITHEAD, pb_cache_manager::mutex, pb_cache_manager::numDelayed, pb_cache_manager_create_buffer(), pb_cache_manager_destroy(), pb_cache_manager_flush(), pipe_mutex_init, pb_cache_manager::provider, and pb_cache_manager::usecs.
00344 { 00345 struct pb_cache_manager *mgr; 00346 00347 if(!provider) 00348 return NULL; 00349 00350 mgr = CALLOC_STRUCT(pb_cache_manager); 00351 if (!mgr) 00352 return NULL; 00353 00354 mgr->base.destroy = pb_cache_manager_destroy; 00355 mgr->base.create_buffer = pb_cache_manager_create_buffer; 00356 mgr->base.flush = pb_cache_manager_flush; 00357 mgr->provider = provider; 00358 mgr->usecs = usecs; 00359 LIST_INITHEAD(&mgr->delayed); 00360 mgr->numDelayed = 0; 00361 pipe_mutex_init(mgr->mutex); 00362 00363 return &mgr->base; 00364 }
static struct pb_buffer* pb_cache_manager_create_buffer | ( | struct pb_manager * | _mgr, | |
size_t | size, | |||
const struct pb_desc * | desc | |||
) | [static, read] |
Definition at line 228 of file pb_bufmgr_cache.c.
References _pb_cache_buffer_destroy(), pipe_buffer::alignment, pb_desc::alignment, assert, pb_buffer::base, pb_cache_buffer::base, pb_cache_buffer::buffer, CALLOC_STRUCT, pb_manager::create_buffer, pb_cache_manager::delayed, pb_cache_buffer::end, FREE, pb_cache_buffer::head, LIST_DEL, LIST_ENTRY, pb_cache_buffer::mgr, pb_cache_manager::mutex, list_head::next, pb_cache_is_buffer_compat(), pb_cache_manager(), pb_check_alignment(), pb_check_usage(), pipe_mutex_lock, pipe_mutex_unlock, pb_cache_manager::provider, pipe_buffer::refcount, pipe_buffer::size, pipe_buffer::usage, pb_desc::usage, util_time_get(), util_time_timeout(), and pb_buffer::vtbl.
00231 { 00232 struct pb_cache_manager *mgr = pb_cache_manager(_mgr); 00233 struct pb_cache_buffer *buf; 00234 struct pb_cache_buffer *curr_buf; 00235 struct list_head *curr, *next; 00236 struct util_time now; 00237 00238 pipe_mutex_lock(mgr->mutex); 00239 00240 buf = NULL; 00241 curr = mgr->delayed.next; 00242 next = curr->next; 00243 00244 /* search in the expired buffers, freeing them in the process */ 00245 util_time_get(&now); 00246 while(curr != &mgr->delayed) { 00247 curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); 00248 if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc)) 00249 buf = curr_buf; 00250 else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now)) 00251 _pb_cache_buffer_destroy(curr_buf); 00252 else 00253 /* This buffer (and all hereafter) are still hot in cache */ 00254 break; 00255 curr = next; 00256 next = curr->next; 00257 } 00258 00259 /* keep searching in the hot buffers */ 00260 if(!buf) { 00261 while(curr != &mgr->delayed) { 00262 curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); 00263 if(pb_cache_is_buffer_compat(curr_buf, size, desc)) { 00264 buf = curr_buf; 00265 break; 00266 } 00267 /* no need to check the timeout here */ 00268 curr = next; 00269 next = curr->next; 00270 } 00271 } 00272 00273 if(buf) { 00274 LIST_DEL(&buf->head); 00275 pipe_mutex_unlock(mgr->mutex); 00276 ++buf->base.base.refcount; 00277 return &buf->base; 00278 } 00279 00280 pipe_mutex_unlock(mgr->mutex); 00281 00282 buf = CALLOC_STRUCT(pb_cache_buffer); 00283 if(!buf) 00284 return NULL; 00285 00286 buf->buffer = mgr->provider->create_buffer(mgr->provider, size, desc); 00287 if(!buf->buffer) { 00288 FREE(buf); 00289 return NULL; 00290 } 00291 00292 assert(buf->buffer->base.refcount >= 1); 00293 assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment)); 00294 assert(pb_check_usage(desc->usage, buf->buffer->base.usage)); 00295 assert(buf->buffer->base.size >= size); 00296 00297 buf->base.base.refcount = 1; 00298 buf->base.base.alignment = buf->buffer->base.alignment; 00299 buf->base.base.usage = buf->buffer->base.usage; 00300 buf->base.base.size = buf->buffer->base.size; 00301 00302 buf->base.vtbl = &pb_cache_buffer_vtbl; 00303 buf->mgr = mgr; 00304 00305 return &buf->base; 00306 }
static void pb_cache_manager_destroy | ( | struct pb_manager * | mgr | ) | [static] |
Definition at line 334 of file pb_bufmgr_cache.c.
References FREE, and pb_cache_manager_flush().
00335 { 00336 pb_cache_manager_flush(mgr); 00337 FREE(mgr); 00338 }
static void pb_cache_manager_flush | ( | struct pb_manager * | _mgr | ) | [static] |
Definition at line 310 of file pb_bufmgr_cache.c.
References _pb_cache_buffer_destroy(), assert, pb_cache_manager::delayed, pb_manager::flush, pb_cache_buffer::head, LIST_ENTRY, pb_cache_manager::mutex, list_head::next, pb_cache_manager(), pipe_mutex_lock, pipe_mutex_unlock, and pb_cache_manager::provider.
00311 { 00312 struct pb_cache_manager *mgr = pb_cache_manager(_mgr); 00313 struct list_head *curr, *next; 00314 struct pb_cache_buffer *buf; 00315 00316 pipe_mutex_lock(mgr->mutex); 00317 curr = mgr->delayed.next; 00318 next = curr->next; 00319 while(curr != &mgr->delayed) { 00320 buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); 00321 _pb_cache_buffer_destroy(buf); 00322 curr = next; 00323 next = curr->next; 00324 } 00325 pipe_mutex_unlock(mgr->mutex); 00326 00327 assert(mgr->provider->flush); 00328 if(mgr->provider->flush) 00329 mgr->provider->flush(mgr->provider); 00330 }
struct pb_vtbl pb_cache_buffer_vtbl |
Initial value:
{ pb_cache_buffer_destroy, pb_cache_buffer_map, pb_cache_buffer_unmap, pb_cache_buffer_get_base_buffer }
Definition at line 197 of file pb_bufmgr_cache.c.