output_status.base.sync = 1;
output_status.status = status;
- ret = tdm_thread_cb_call(private_output, &output_status.base);
+ ret = tdm_thread_cb_call(private_output, &output_status.base, 1);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return TDM_ERROR_NONE;
output_dpms.base.sync = 0;
output_dpms.dpms = dpms;
- ret = tdm_thread_cb_call(private_output, &output_dpms.base);
+ ret = tdm_thread_cb_call(private_output, &output_dpms.base, 1);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return TDM_ERROR_NONE;
if (tdm_debug_module & TDM_DEBUG_COMMIT)
TDM_INFO("output(%d) wait_vblank: handler(%p)", vblank_handler->private_output->pipe, vblank_handler);
- ret = tdm_thread_cb_call(vblank_handler->private_output, &output_vblank.base);
+ ret = tdm_thread_cb_call(vblank_handler->private_output, &output_vblank.base, 1);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
}
output_commit.tv_sec = tv_sec;
output_commit.tv_usec = tv_usec;
- ret = tdm_thread_cb_call(private_output, &output_commit.base);
+ ret = tdm_thread_cb_call(private_output, &output_commit.base, 1);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
}
ev.base.data = NULL;
ev.base.sync = 0;
- ret = tdm_thread_cb_call(private_output, &ev.base);
+ ret = tdm_thread_cb_call(private_output, &ev.base, 1);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
TDM_INFO("tdm-thread: get a 'need to revalidate' event for the ouptut:%p.", private_output);
case TDM_THREAD_CB_VBLANK_SW:
case TDM_THREAD_CB_VBLANK_CREATE:
case TDM_THREAD_CB_NEED_VALIDATE:
- ret = tdm_thread_cb_call(NULL, base);
+ /* this event comes from other thread. so we don't need to propagate this to other thread */
+ ret = tdm_thread_cb_call(NULL, base, 0);
TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
break;
default:
* because a callback is added with cb_type and cb_data.
*/
INTERN tdm_error
-tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base)
+tdm_thread_cb_call(void *object, tdm_thread_cb_base *cb_base, unsigned int propagation)
{
tdm_private_display *private_display = tdm_display_get();
tdm_private_thread_cb *cb = NULL, *hh = NULL;
struct list_head *list, *other_list;
struct list_head call_list;
static pid_t waiting_tid = 0;
- static tdm_thread_cb_type waiting_cb_type = TDM_THREAD_CB_NONE;
tdm_error ret;
TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
assert(find_funcs[cb_base->type] != NULL);
- /* handling only output-status as sync */
- if (cb_base->type == TDM_THREAD_CB_OUTPUT_STATUS) {
- TDM_RETURN_VAL_IF_FAIL(cb_base->sync == 1, TDM_ERROR_INVALID_PARAMETER);
- } else {
- TDM_RETURN_VAL_IF_FAIL(cb_base->sync == 0, TDM_ERROR_INVALID_PARAMETER);
- }
+ if (tdm_debug_module & TDM_DEBUG_THREAD)
+ TDM_INFO("'%s' thread_cb (sync:%d, propagation:%d) ------",
+ tdm_cb_type_str(cb_base->type), cb_base->sync, propagation);
+
+ /* handling only output-status as sync. below logic can't handle two sync-type events */
+ if (cb_base->type == TDM_THREAD_CB_OUTPUT_STATUS)
+ assert(cb_base->sync == 1);
+ else
+ assert(cb_base->sync == 0);
if (!object) {
object = find_funcs[cb_base->type](private_display, cb_base->object_stamp);
pthread_mutex_unlock(&cb_list_lock);
- assert(LIST_IS_EMPTY(&call_list));
-
- if (waiting_tid == 0 || waiting_cb_type != cb_base->type) {
+ if (propagation) {
LIST_FOR_EACH_ENTRY_SAFE(cb, hh, other_list, link) {
if (cb->object != object ||
cb->cb_type != cb_base->type ||
if (!handler_in_other_thread) {
if (keep_private_thread) {
- if (cb_base->sync) {
+ if (cb_base->sync && waiting_tid != 0) {
waiting_tid = 0;
- waiting_cb_type = TDM_THREAD_CB_NONE;
pthread_cond_signal(&keep_private_thread->event_cond);
if (tdm_debug_module & TDM_DEBUG_THREAD)
TDM_INFO("pthread broadcase");
}
}
if (tdm_debug_module & TDM_DEBUG_THREAD)
- TDM_INFO("'%s' thread_cb done(sync:%d)", tdm_cb_type_str(cb_base->type), cb_base->sync);
+ TDM_INFO("'%s' thread_cb (sync:%d, propagation:%d) ------...",
+ tdm_cb_type_str(cb_base->type), cb_base->sync, propagation);
return TDM_ERROR_NONE;
}
/* Once we reach here, it means that keep_private_thread is not NULL.
* Just make the crash. Avoiding it is not going to help us.
*/
+ assert(keep_private_thread != NULL);
+
ret = tdm_thread_send_cb(private_display->private_loop, cb_base);
TDM_RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, TDM_ERROR_OPERATION_FAILED);
/* waiting until all cb are done in another thread */
if (cb_base->sync) {
+ /* if waiting_tid is not 0, it means there are two sync-type events at the same time.
+ * and it would make deadlock issue.
+ */
+ assert(waiting_tid == 0);
+
if (tdm_debug_module & TDM_DEBUG_THREAD)
TDM_INFO("pthread wait");
*/
tdm_mutex_locked = 0;
waiting_tid = caller_tid;
- waiting_cb_type = cb_base->type;
-
pthread_cond_wait(&keep_private_thread->event_cond, &private_display->lock);
tdm_mutex_locked = 1;
}
if (tdm_debug_module & TDM_DEBUG_THREAD)
- TDM_INFO("'%s' thread_cb done(sync:%d)", tdm_cb_type_str(cb_base->type), cb_base->sync);
+ TDM_INFO("'%s' thread_cb (sync:%d, propagation:%d) ------...",
+ tdm_cb_type_str(cb_base->type), cb_base->sync, propagation);
return TDM_ERROR_NONE;
}