From: Marcel Hollerbach Date: Thu, 2 Mar 2017 17:32:40 +0000 (+0100) Subject: ecore_thread: do not override the data field of a thread X-Git-Tag: submit/tizen/20170915.074959~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F80%2F149880%2F2;p=platform%2Fupstream%2Fefl.git ecore_thread: do not override the data field of a thread otherwise a currently executed ecore_thread is going to pass a complete wrong data to its callbacks. fix T5175 fix T5173 Upstream: 097f9cfe5fa601deaca1ed4c72c6311b4b893386 Change-Id: I427d6440c265e358cd0268f24e1c4f27bf23c4f0 --- diff --git a/src/lib/ecore/ecore_thread.c b/src/lib/ecore/ecore_thread.c index befb0fb..9ef8e3c 100644 --- a/src/lib/ecore/ecore_thread.c +++ b/src/lib/ecore/ecore_thread.c @@ -49,6 +49,14 @@ typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker; typedef struct _Ecore_Pthread Ecore_Pthread; typedef struct _Ecore_Thread_Data Ecore_Thread_Data; +typedef struct _Ecore_Thread_Waiter Ecore_Thread_Waiter; + +struct _Ecore_Thread_Waiter +{ + Ecore_Thread_Cb func_cancel; + Ecore_Thread_Cb func_end; + Eina_Bool waiting; +}; struct _Ecore_Thread_Data { @@ -87,6 +95,7 @@ struct _Ecore_Pthread_Worker } message_run; } u; + Ecore_Thread_Waiter *waiter; Ecore_Thread_Cb func_cancel; Ecore_Thread_Cb func_end; PH(self); @@ -326,13 +335,13 @@ _ecore_short_job(PH(thread)) int cancel; SLKL(_ecore_pending_job_threads_mutex); - + if (!_ecore_pending_job_threads) { SLKU(_ecore_pending_job_threads_mutex); return; } - + work = eina_list_data_get(_ecore_pending_job_threads); _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, _ecore_pending_job_threads); @@ -735,44 +744,36 @@ ecore_thread_cancel(Ecore_Thread *thread) return EINA_FALSE; } -typedef struct _Ecore_Thread_Waiter Ecore_Thread_Waiter; -struct _Ecore_Thread_Waiter -{ - Ecore_Thread_Cb func_cancel; - Ecore_Thread_Cb func_end; - const void *data; -}; - static void _ecore_thread_wait_reset(Ecore_Thread_Waiter *waiter, Ecore_Pthread_Worker *worker) { - worker->data = waiter->data; worker->func_cancel = waiter->func_cancel; worker->func_end = waiter->func_end; - // The waiter will be checked by _wait, NULL meaning it is done + worker->waiter = NULL; + waiter->func_end = NULL; waiter->func_cancel = NULL; - waiter->data = NULL; + waiter->waiting = EINA_FALSE; } static void -_ecore_thread_wait_cancel(void *data, Ecore_Thread *thread) +_ecore_thread_wait_cancel(void *data EINA_UNUSED, Ecore_Thread *thread) { Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread; - Ecore_Thread_Waiter *waiter = data; + Ecore_Thread_Waiter *waiter = worker->waiter; - waiter->func_cancel((void*) waiter->data, thread); + if (waiter->func_cancel) waiter->func_cancel(data, thread); _ecore_thread_wait_reset(waiter, worker); } static void -_ecore_thread_wait_end(void *data, Ecore_Thread *thread) +_ecore_thread_wait_end(void *data EINA_UNUSED, Ecore_Thread *thread) { Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker*) thread; - Ecore_Thread_Waiter *waiter = data; + Ecore_Thread_Waiter *waiter = worker->waiter; - waiter->func_end((void*) waiter->data, thread); + if (waiter->func_end) waiter->func_end(data, thread); _ecore_thread_wait_reset(waiter, worker); } @@ -784,15 +785,16 @@ ecore_thread_wait(Ecore_Thread *thread, double wait) if (!thread) return EINA_TRUE; - waiter.data = worker->data; waiter.func_end = worker->func_end; waiter.func_cancel = worker->func_cancel; + waiter.waiting = EINA_TRUE; + // Now trick the thread to call the wrapper function - worker->data = &waiter; + worker->waiter = &waiter; worker->func_cancel = _ecore_thread_wait_cancel; worker->func_end = _ecore_thread_wait_end; - while (waiter.data) + while (waiter.waiting == EINA_TRUE) { double start, end; @@ -805,7 +807,15 @@ ecore_thread_wait(Ecore_Thread *thread, double wait) if (wait <= 0) break; } - return (waiter.data == NULL) ? EINA_TRUE : EINA_FALSE; + if (waiter.waiting == EINA_FALSE) + { + return EINA_TRUE; + } + else + { + _ecore_thread_wait_reset(&waiter, worker); + return EINA_FALSE; + } } EAPI Eina_Bool