From 5233af2142e5fd045f922a82fef0c76c62684a7b Mon Sep 17 00:00:00 2001 From: Thibaut Mattern Date: Tue, 14 Oct 2003 22:16:32 +0000 Subject: Add a callback to the buffer_pool_alloc function. The goal is to detect in the net_buf_ctrl if there is no more free buffer in a fifo, which indicates there will be a deadlock if the engine is not unpaused. Currently this detection is done from the "put" callback, it's not a safe solution, nothing prevents a demuxer to allocate 2 buffers before calling put(). The impact is low, only one test per buffer_pool_alloc call if no callback is registered. It's done exactly the same way as the put and get callbacks. CVS patchset: 5520 CVS date: 2003/10/14 22:16:32 --- src/xine-engine/buffer.c | 78 ++++++++++++++++++++++++++++++++++++++---------- src/xine-engine/buffer.h | 11 +++++-- 2 files changed, 70 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c index fb12fca94..f32ff4b84 100644 --- a/src/xine-engine/buffer.c +++ b/src/xine-engine/buffer.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.c,v 1.30 2003/05/15 20:23:18 miguelfreitas Exp $ + * $Id: buffer.c,v 1.31 2003/10/14 22:16:32 tmattern Exp $ * * * contents: @@ -72,9 +72,13 @@ static void buffer_pool_free (buf_element_t *element) { static buf_element_t *buffer_pool_alloc (fifo_buffer_t *this) { buf_element_t *buf; + int i; pthread_mutex_lock (&this->buffer_pool_mutex); + for(i = 0; this->alloc_cb[i]; i++) + this->alloc_cb[i](this, this->alloc_cb_data[i]); + /* we always keep one free buffer for emergency situations like * decoder flushes that would need a buffer in buffer_pool_try_alloc() */ while (this->buffer_pool_num_free < 2) { @@ -335,6 +339,25 @@ static void fifo_buffer_dispose (fifo_buffer_t *this) { free (this); } +/* + * Register an "alloc" callback + */ +static void fifo_register_alloc_cb (fifo_buffer_t *this, + void (*cb)(fifo_buffer_t *this, + void *data_cb), + void *data_cb) { + int i; + pthread_mutex_lock(&this->mutex); + for(i = 0; this->alloc_cb[i]; i++) + ; + if( i != BUF_MAX_CALLBACKS-1 ) { + this->alloc_cb[i] = cb; + this->alloc_cb_data[i] = data_cb; + this->alloc_cb[i+1] = NULL; + } + pthread_mutex_unlock(&this->mutex); +} + /* * Register a "put" callback */ @@ -375,6 +398,25 @@ static void fifo_register_get_cb (fifo_buffer_t *this, pthread_mutex_unlock(&this->mutex); } +/* + * Unregister an "alloc" callback + */ +static void fifo_unregister_alloc_cb (fifo_buffer_t *this, + void (*cb)(fifo_buffer_t *this, + void *data_cb) ) { + int i,j; + pthread_mutex_lock(&this->mutex); + for(i = 0; this->alloc_cb[i]; i++) { + if( this->alloc_cb[i] == cb ) { + for(j = i; this->alloc_cb[j]; j++) { + this->alloc_cb[j] = this->alloc_cb[j+1]; + this->alloc_cb_data[j] = this->alloc_cb_data[j+1]; + } + } + } + pthread_mutex_unlock(&this->mutex); +} + /* * Unregister a "put" callback */ @@ -427,21 +469,23 @@ fifo_buffer_t *fifo_buffer_new (int num_buffers, uint32_t buf_size) { this = xine_xmalloc (sizeof (fifo_buffer_t)); - this->first = NULL; - this->last = NULL; - this->fifo_size = 0; - this->put = fifo_buffer_put; - this->insert = fifo_buffer_insert; - this->get = fifo_buffer_get; - this->clear = fifo_buffer_clear; - this->size = fifo_buffer_size; - this->num_free = fifo_buffer_num_free; - this->data_size = fifo_buffer_data_size; - this->dispose = fifo_buffer_dispose; - this->register_get_cb = fifo_register_get_cb; - this->register_put_cb = fifo_register_put_cb; - this->unregister_get_cb = fifo_unregister_get_cb; - this->unregister_put_cb = fifo_unregister_put_cb; + this->first = NULL; + this->last = NULL; + this->fifo_size = 0; + this->put = fifo_buffer_put; + this->insert = fifo_buffer_insert; + this->get = fifo_buffer_get; + this->clear = fifo_buffer_clear; + this->size = fifo_buffer_size; + this->num_free = fifo_buffer_num_free; + this->data_size = fifo_buffer_data_size; + this->dispose = fifo_buffer_dispose; + this->register_alloc_cb = fifo_register_alloc_cb; + this->register_get_cb = fifo_register_get_cb; + this->register_put_cb = fifo_register_put_cb; + this->unregister_alloc_cb = fifo_unregister_alloc_cb; + this->unregister_get_cb = fifo_unregister_get_cb; + this->unregister_put_cb = fifo_unregister_put_cb; pthread_mutex_init (&this->mutex, NULL); pthread_cond_init (&this->not_empty, NULL); @@ -486,8 +530,10 @@ fifo_buffer_t *fifo_buffer_new (int num_buffers, uint32_t buf_size) { buffer_pool_free (buf); } + this->alloc_cb[0] = NULL; this->get_cb[0] = NULL; this->put_cb[0] = NULL; + this->alloc_cb_data[0] = NULL; this->get_cb_data[0] = NULL; this->put_cb_data[0] = NULL; return this; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index da2afa28f..abe3457b7 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.h,v 1.120 2003/08/05 15:20:00 mroi Exp $ + * $Id: buffer.h,v 1.121 2003/10/14 22:16:32 tmattern Exp $ * * * contents: @@ -467,8 +467,11 @@ struct fifo_buffer_s /* the same as put but insert at the head of the fifo */ void (*insert) (fifo_buffer_t *fifo, buf_element_t *buf); + /* callbacks */ + void (*register_alloc_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, void *), void *cb_data); void (*register_put_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *), void *cb_data); void (*register_get_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *), void *cb_data); + void (*unregister_alloc_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, void *)); void (*unregister_put_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *)); void (*unregister_get_cb) (fifo_buffer_t *fifo, void (*cb)(fifo_buffer_t *fifo, buf_element_t *buf, void *)); @@ -479,11 +482,13 @@ struct fifo_buffer_s pthread_mutex_t buffer_pool_mutex; pthread_cond_t buffer_pool_cond_not_empty; int buffer_pool_num_free; - int buffer_pool_capacity; - int buffer_pool_buf_size; + int buffer_pool_capacity; + int buffer_pool_buf_size; void *buffer_pool_base; /*used to free mem chunk */ + void (*alloc_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, void *data_cb); void (*put_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, buf_element_t *buf, void *data_cb); void (*get_cb[BUF_MAX_CALLBACKS])(fifo_buffer_t *fifo, buf_element_t *buf, void *data_cb); + void *alloc_cb_data[BUF_MAX_CALLBACKS]; void *put_cb_data[BUF_MAX_CALLBACKS]; void *get_cb_data[BUF_MAX_CALLBACKS]; } ; -- cgit v1.2.3