tbm_surface_queue: called need_attach when queue_dequeue
[platform/core/uifw/libtbm.git] / src / tbm_surface_queue.c
index ea5b09e..1dadcb0 100644 (file)
@@ -106,6 +106,13 @@ typedef struct {
        void *data;
 } queue_notify;
 
+typedef struct {
+       struct list_head link;
+
+       tbm_surface_queue_trace_cb cb;
+       void *data;
+} queue_trace;
+
 typedef struct _tbm_surface_queue_interface {
        void (*init)(tbm_surface_queue_h queue);
        void (*reset)(tbm_surface_queue_h queue);
@@ -133,8 +140,10 @@ struct _tbm_surface_queue {
        struct list_head destory_noti;
        struct list_head dequeuable_noti;
        struct list_head dequeue_noti;
+       struct list_head can_dequeue_noti;
        struct list_head acquirable_noti;
        struct list_head reset_noti;
+       struct list_head trace_noti;
 
        pthread_mutex_t lock;
        pthread_cond_t free_cond;
@@ -162,7 +171,7 @@ _tbm_surf_queue_mutex_init(void)
                return true;
 
        if (pthread_mutex_init(&tbm_surf_queue_lock, NULL)) {
-               TBM_LOG_E("fail: tbm_surf_queue mutex init\n");
+               TBM_LOG_E("fail: pthread_mutex_init\n");
                return false;
        }
 
@@ -174,8 +183,10 @@ _tbm_surf_queue_mutex_init(void)
 static void
 _tbm_surf_queue_mutex_lock(void)
 {
-       if (!_tbm_surf_queue_mutex_init())
+       if (!_tbm_surf_queue_mutex_init()) {
+               TBM_LOG_E("fail: _tbm_surf_queue_mutex_init\n");
                return;
+       }
 
        pthread_mutex_lock(&tbm_surf_queue_lock);
 }
@@ -207,13 +218,18 @@ _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
 {
        tbm_surface_queue_h old_data = NULL;
 
-       if (surface_queue == NULL || g_surf_queue_bufmgr == NULL) {
-               TBM_TRACE("error: surface_queue is NULL or not initialized\n");
+       if (surface_queue == NULL) {
+               TBM_LOG_E("error: surface_queue is NULL.\n");
+               return 0;
+       }
+
+       if (g_surf_queue_bufmgr == NULL) {
+               TBM_LOG_E("error: g_surf_queue_bufmgr is NULL.\n");
                return 0;
        }
 
        if (LIST_IS_EMPTY(&g_surf_queue_bufmgr->surf_queue_list)) {
-               TBM_TRACE("error: surf_queue_list is empty\n");
+               TBM_LOG_E("error: surf_queue_list is empty\n");
                return 0;
        }
 
@@ -225,7 +241,8 @@ _tbm_surface_queue_is_valid(tbm_surface_queue_h surface_queue)
                }
        }
 
-       TBM_TRACE("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
+       TBM_LOG_E("error: Invalid tbm_surface_queue(%p)\n", surface_queue);
+
        return 0;
 }
 
@@ -275,9 +292,12 @@ _queue_node_pop_front(queue *queue)
 {
        queue_node *node;
 
+       if (!queue->head.next) return NULL;
+       if (!queue->count) return NULL;
+
        node = LIST_ENTRY(queue_node, queue->head.next, item_link);
 
-       LIST_DEL(&node->item_link);
+       LIST_DELINIT(&node->item_link);
        queue->count--;
 
        return node;
@@ -286,7 +306,7 @@ _queue_node_pop_front(queue *queue)
 static queue_node *
 _queue_node_pop(queue *queue, queue_node *node)
 {
-       LIST_DEL(&node->item_link);
+       LIST_DELINIT(&node->item_link);
        queue->count--;
 
        return node;
@@ -338,6 +358,8 @@ _queue_get_node(tbm_surface_queue_h surface_queue, int type,
                }
        }
 
+       TBM_LOG_E("fail to get the queue_node.\n");
+
        return NULL;
 }
 
@@ -414,12 +436,77 @@ static void
 _notify_emit(tbm_surface_queue_h surface_queue,
             struct list_head *list)
 {
-       queue_notify *item = NULL;
+       queue_notify *item = NULL, *tmp;;
 
-       LIST_FOR_EACH_ENTRY(item, list, link)
+       /*
+               The item->cb is the outside function of the libtbm.
+               The tbm user may/can remove the item of the list,
+               so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
+       */
+       LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
                item->cb(surface_queue, item->data);
 }
 
+static void
+_trace_add(struct list_head *list, tbm_surface_queue_trace_cb cb,
+           void *data)
+{
+       TBM_RETURN_IF_FAIL(cb != NULL);
+
+       queue_trace *item = (queue_trace *)calloc(1, sizeof(queue_trace));
+
+       TBM_RETURN_IF_FAIL(item != NULL);
+
+       LIST_INITHEAD(&item->link);
+       item->cb = cb;
+       item->data = data;
+
+       LIST_ADDTAIL(&item->link, list);
+}
+
+static void
+_trace_remove(struct list_head *list,
+              tbm_surface_queue_trace_cb cb, void *data)
+{
+       queue_trace *item = NULL, *tmp;
+
+       LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
+               if (item->cb == cb && item->data == data) {
+                       LIST_DEL(&item->link);
+                       free(item);
+                       return;
+               }
+       }
+
+       TBM_LOG_E("Cannot find notifiy\n");
+}
+
+static void
+_trace_remove_all(struct list_head *list)
+{
+       queue_trace *item = NULL, *tmp;
+
+       LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link) {
+               LIST_DEL(&item->link);
+               free(item);
+       }
+}
+
+static void
+_trace_emit(tbm_surface_queue_h surface_queue,
+            struct list_head *list, tbm_surface_h surface, tbm_surface_queue_trace trace)
+{
+       queue_trace *item = NULL, *tmp;;
+
+       /*
+               The item->cb is the outside function of the libtbm.
+               The tbm user may/can remove the item of the list,
+               so we have to use the LIST_FOR_EACH_ENTRY_SAFE.
+       */
+       LIST_FOR_EACH_ENTRY_SAFE(item, tmp, list, link)
+               item->cb(surface_queue, surface, trace, item->data);
+}
+
 static int
 _tbm_surface_queue_get_node_count(tbm_surface_queue_h surface_queue, Queue_Node_Type type)
 {
@@ -480,14 +567,6 @@ _tbm_surface_queue_dequeue(tbm_surface_queue_h surface_queue)
 {
        queue_node *node;
 
-       if (_queue_is_empty(&surface_queue->free_queue)) {
-               if (surface_queue->impl && surface_queue->impl->need_attach)
-                       surface_queue->impl->need_attach(surface_queue);
-
-               if (_queue_is_empty(&surface_queue->free_queue))
-                       return NULL;
-       }
-
        node = _queue_node_pop_front(&surface_queue->free_queue);
 
        return node;
@@ -546,8 +625,10 @@ _tbm_surface_queue_init(tbm_surface_queue_h surface_queue,
        LIST_INITHEAD(&surface_queue->destory_noti);
        LIST_INITHEAD(&surface_queue->dequeuable_noti);
        LIST_INITHEAD(&surface_queue->dequeue_noti);
+       LIST_INITHEAD(&surface_queue->can_dequeue_noti);
        LIST_INITHEAD(&surface_queue->acquirable_noti);
        LIST_INITHEAD(&surface_queue->reset_noti);
+       LIST_INITHEAD(&surface_queue->trace_noti);
 
        if (surface_queue->impl && surface_queue->impl->init)
                surface_queue->impl->init(surface_queue);
@@ -694,6 +775,52 @@ tbm_surface_queue_remove_dequeue_cb(
 }
 
 tbm_surface_queue_error_e
+tbm_surface_queue_add_can_dequeue_cb(
+       tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
+       void *data)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       _notify_add(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
+tbm_surface_queue_remove_can_dequeue_cb(
+       tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb can_dequeue_cb,
+       void *data)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       _notify_remove(&surface_queue->can_dequeue_noti, can_dequeue_cb, data);
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
 tbm_surface_queue_add_acquirable_cb(
        tbm_surface_queue_h surface_queue, tbm_surface_queue_notify_cb acquirable_cb,
        void *data)
@@ -740,6 +867,52 @@ tbm_surface_queue_remove_acquirable_cb(
 }
 
 tbm_surface_queue_error_e
+tbm_surface_queue_add_trace_cb(
+       tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
+       void *data)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       _trace_add(&surface_queue->trace_noti, trace_cb, data);
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
+tbm_surface_queue_remove_trace_cb(
+       tbm_surface_queue_h surface_queue, tbm_surface_queue_trace_cb trace_cb,
+       void *data)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       _trace_remove(&surface_queue->trace_noti, trace_cb, data);
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
 tbm_surface_queue_set_alloc_cb(
        tbm_surface_queue_h surface_queue,
        tbm_surface_alloc_cb alloc_cb,
@@ -912,7 +1085,11 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h
                pthread_mutex_unlock(&surface_queue->lock);
 
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
+
+               if (!node)
+                       return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
+               else
+                       return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
        }
 
        if (surface_queue->impl && surface_queue->impl->enqueue)
@@ -925,7 +1102,7 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h
                pthread_mutex_unlock(&surface_queue->lock);
 
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
+               return TBM_SURFACE_QUEUE_ERROR_EMPTY;
        }
 
        node->type = QUEUE_NODE_TYPE_ENQUEUE;
@@ -935,6 +1112,8 @@ tbm_surface_queue_enqueue(tbm_surface_queue_h
 
        _tbm_surf_queue_mutex_unlock();
 
+       _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_ENQUEUE);
+
        _notify_emit(surface_queue, &surface_queue->acquirable_noti);
 
        return TBM_SURFACE_QUEUE_ERROR_NONE;
@@ -957,6 +1136,18 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h
 
        pthread_mutex_lock(&surface_queue->lock);
 
+       if (_queue_is_empty(&surface_queue->free_queue)) {
+               if (surface_queue->impl && surface_queue->impl->need_attach)
+                       surface_queue->impl->need_attach(surface_queue);
+
+               if (!_tbm_surface_queue_is_valid(surface_queue)) {
+                       TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+                       pthread_mutex_unlock(&surface_queue->lock);
+                       _tbm_surf_queue_mutex_unlock();
+                       return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
+               }
+       }
+
        if (surface_queue->impl && surface_queue->impl->dequeue)
                node = surface_queue->impl->dequeue(surface_queue);
        else
@@ -967,7 +1158,7 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h
                pthread_mutex_unlock(&surface_queue->lock);
 
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
+               return TBM_SURFACE_QUEUE_ERROR_EMPTY;
        }
 
        node->type = QUEUE_NODE_TYPE_DEQUEUE;
@@ -979,6 +1170,8 @@ tbm_surface_queue_dequeue(tbm_surface_queue_h
 
        _tbm_surf_queue_mutex_unlock();
 
+       _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_DEQUEUE);
+
        _notify_emit(surface_queue, &surface_queue->dequeue_noti);
 
        return TBM_SURFACE_QUEUE_ERROR_NONE;
@@ -991,6 +1184,14 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
 
        TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
 
+       _tbm_surf_queue_mutex_unlock();
+
+       _notify_emit(surface_queue, &surface_queue->can_dequeue_noti);
+
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue), 0);
+
        pthread_mutex_lock(&surface_queue->lock);
 
        TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
@@ -1001,6 +1202,7 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
 
                if (!_tbm_surface_queue_is_valid(surface_queue)) {
                        TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+                       pthread_mutex_unlock(&surface_queue->lock);
                        _tbm_surf_queue_mutex_unlock();
                        return 0;
                }
@@ -1019,10 +1221,10 @@ tbm_surface_queue_can_dequeue(tbm_surface_queue_h surface_queue, int wait)
                _tbm_surf_queue_mutex_lock();
 
                if (!_tbm_surface_queue_is_valid(surface_queue)) {
-                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+                       TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
                        pthread_mutex_unlock(&surface_queue->lock);
-                         _tbm_surf_queue_mutex_unlock();
-                         return 0;
+                       _tbm_surf_queue_mutex_unlock();
+                       return 0;
                }
 
                pthread_mutex_unlock(&surface_queue->lock);
@@ -1060,7 +1262,11 @@ tbm_surface_queue_release(tbm_surface_queue_h
                pthread_mutex_unlock(&surface_queue->lock);
 
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
+
+               if (!node)
+                       return TBM_SURFACE_QUEUE_ERROR_UNKNOWN_SURFACE;
+               else
+                       return TBM_SURFACE_QUEUE_ERROR_ALREADY_EXIST;
        }
 
        if (surface_queue->queue_size < surface_queue->num_attached) {
@@ -1085,8 +1291,9 @@ tbm_surface_queue_release(tbm_surface_queue_h
        if (_queue_is_empty(&surface_queue->free_queue)) {
                pthread_mutex_unlock(&surface_queue->lock);
 
+               TBM_LOG_E("surface_queue->free_queue is empty.\n");
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_SURFACE;
+               return TBM_SURFACE_QUEUE_ERROR_EMPTY;
        }
 
        node->type = QUEUE_NODE_TYPE_RELEASE;
@@ -1096,6 +1303,8 @@ tbm_surface_queue_release(tbm_surface_queue_h
 
        _tbm_surf_queue_mutex_unlock();
 
+       _trace_emit(surface_queue, &surface_queue->trace_noti, surface, TBM_SURFACE_QUEUE_TRACE_RELEASE);
+
        _notify_emit(surface_queue, &surface_queue->dequeuable_noti);
 
        return TBM_SURFACE_QUEUE_ERROR_NONE;
@@ -1128,7 +1337,7 @@ tbm_surface_queue_acquire(tbm_surface_queue_h
                pthread_mutex_unlock(&surface_queue->lock);
 
                _tbm_surf_queue_mutex_unlock();
-               return TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE;
+               return TBM_SURFACE_QUEUE_ERROR_EMPTY;
        }
 
        node->type = QUEUE_NODE_TYPE_ACQUIRE;
@@ -1144,6 +1353,8 @@ tbm_surface_queue_acquire(tbm_surface_queue_h
        if (b_dump_queue)
                tbm_surface_internal_dump_buffer(*surface, "acquire");
 
+       _trace_emit(surface_queue, &surface_queue->trace_noti, *surface, TBM_SURFACE_QUEUE_TRACE_ACQUIRE);
+
        return TBM_SURFACE_QUEUE_ERROR_NONE;
 }
 
@@ -1171,10 +1382,10 @@ tbm_surface_queue_can_acquire(tbm_surface_queue_h surface_queue, int wait)
                _tbm_surf_queue_mutex_lock();
 
                if (!_tbm_surface_queue_is_valid(surface_queue)) {
-                         TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
+                       TBM_LOG_E("surface_queue:%p is invalid", surface_queue);
                        pthread_mutex_unlock(&surface_queue->lock);
-                         _tbm_surf_queue_mutex_unlock();
-                         return 0;
+                       _tbm_surf_queue_mutex_unlock();
+                       return 0;
                }
 
                pthread_mutex_unlock(&surface_queue->lock);
@@ -1211,8 +1422,10 @@ tbm_surface_queue_destroy(tbm_surface_queue_h surface_queue)
        _notify_remove_all(&surface_queue->destory_noti);
        _notify_remove_all(&surface_queue->dequeuable_noti);
        _notify_remove_all(&surface_queue->dequeue_noti);
+       _notify_remove_all(&surface_queue->can_dequeue_noti);
        _notify_remove_all(&surface_queue->acquirable_noti);
        _notify_remove_all(&surface_queue->reset_noti);
+       _trace_remove_all(&surface_queue->trace_noti);
 
        pthread_mutex_destroy(&surface_queue->lock);
 
@@ -1274,6 +1487,21 @@ tbm_surface_queue_reset(tbm_surface_queue_h
 }
 
 tbm_surface_queue_error_e
+tbm_surface_queue_notify_reset(tbm_surface_queue_h surface_queue)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       _notify_emit(surface_queue, &surface_queue->reset_noti);
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
 tbm_surface_queue_set_size(tbm_surface_queue_h
                        surface_queue, int queue_size, int flush)
 {
@@ -1348,6 +1576,42 @@ tbm_surface_queue_set_size(tbm_surface_queue_h
 }
 
 tbm_surface_queue_error_e
+tbm_surface_queue_free_flush(tbm_surface_queue_h surface_queue)
+{
+       queue_node *node = NULL;
+
+       _tbm_surf_queue_mutex_lock();
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+
+       TBM_QUEUE_TRACE("tbm_surface_queue(%p)\n", surface_queue);
+
+       if (surface_queue->num_attached == 0) {
+               _tbm_surf_queue_mutex_unlock();
+               return TBM_SURFACE_QUEUE_ERROR_NONE;
+       }
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       /* Destory surface in free_queue */
+       while ((node = _queue_node_pop_front(&surface_queue->free_queue))) {
+               if (surface_queue->impl && surface_queue->impl->need_detach)
+                       surface_queue->impl->need_detach(surface_queue, node);
+               else
+                       _tbm_surface_queue_detach(surface_queue, node->surface);
+       }
+
+       /* Reset queue */
+       _queue_init(&surface_queue->free_queue);
+
+       pthread_mutex_unlock(&surface_queue->lock);
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
+tbm_surface_queue_error_e
 tbm_surface_queue_flush(tbm_surface_queue_h surface_queue)
 {
        queue_node *node = NULL, *tmp;
@@ -1421,6 +1685,46 @@ tbm_surface_queue_get_surfaces(tbm_surface_queue_h surface_queue,
        return TBM_SURFACE_QUEUE_ERROR_NONE;
 }
 
+tbm_surface_queue_error_e
+tbm_surface_queue_get_trace_surface_num(
+                       tbm_surface_queue_h surface_queue, tbm_surface_queue_trace trace, int *num)
+{
+       _tbm_surf_queue_mutex_lock();
+
+       *num = 0;
+
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(_tbm_surface_queue_is_valid(surface_queue),
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_QUEUE);
+       TBM_SURF_QUEUE_RETURN_VAL_IF_FAIL(num != NULL,
+                              TBM_SURFACE_QUEUE_ERROR_INVALID_PARAMETER);
+
+       pthread_mutex_lock(&surface_queue->lock);
+
+       switch (trace) {
+       case TBM_SURFACE_QUEUE_TRACE_NONE:
+               *num = 0;
+               break;
+       case TBM_SURFACE_QUEUE_TRACE_DEQUEUE:
+               *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_DEQUEUE);
+               break;
+       case TBM_SURFACE_QUEUE_TRACE_ENQUEUE:
+               *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ENQUEUE);
+               break;
+       case TBM_SURFACE_QUEUE_TRACE_ACQUIRE:
+               *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_ACQUIRE);
+               break;
+       case TBM_SURFACE_QUEUE_TRACE_RELEASE:
+               *num = _tbm_surface_queue_get_node_count(surface_queue, QUEUE_NODE_TYPE_RELEASE);
+               break;
+       }
+
+       pthread_mutex_unlock(&surface_queue->lock);
+
+       _tbm_surf_queue_mutex_unlock();
+
+       return TBM_SURFACE_QUEUE_ERROR_NONE;
+}
+
 typedef struct {
        int flags;
 } tbm_queue_default;
@@ -1447,6 +1751,7 @@ __tbm_queue_default_need_attach(tbm_surface_queue_h surface_queue)
                _tbm_surf_queue_mutex_lock();
                pthread_mutex_lock(&surface_queue->lock);
 
+               /* silent return */
                if (!surface)
                        return;
 
@@ -1495,6 +1800,7 @@ tbm_surface_queue_create(int queue_size, int width,
        tbm_queue_default *data = (tbm_queue_default *) calloc(1,
                                  sizeof(tbm_queue_default));
        if (data == NULL) {
+               TBM_LOG_E("cannot allocate the tbm_queue_default.\n");
                free(surface_queue);
                _tbm_surf_queue_mutex_unlock();
                return NULL;
@@ -1554,6 +1860,7 @@ __tbm_queue_sequence_need_attach(tbm_surface_queue_h surface_queue)
                _tbm_surf_queue_mutex_lock();
                pthread_mutex_lock(&surface_queue->lock);
 
+               /* silent return */
                if (!surface)
                        return;
 
@@ -1635,6 +1942,7 @@ tbm_surface_queue_sequence_create(int queue_size, int width,
        tbm_queue_sequence *data = (tbm_queue_sequence *) calloc(1,
                                   sizeof(tbm_queue_sequence));
        if (data == NULL) {
+               TBM_LOG_E("cannot allocate the tbm_queue_sequence.\n");
                free(surface_queue);
                _tbm_surf_queue_mutex_unlock();
                return NULL;