ecore: force pthread_join even when main loop isn't running.

pthread_create can fail if to much pthread are pending. As pthread_join
is only called when the main loop can flush the async call list, there was
a possibility for edje_cc to run out of thread due to that. We know
force the flush of the async call list and so call pthread_join when
pthread_create fail.


SVN revision: 71555
This commit is contained in:
Cedric BAIL 2012-05-30 12:14:34 +00:00
parent 7772b28002
commit 6d2b2f366f
5 changed files with 42 additions and 10 deletions

View File

@ -692,6 +692,7 @@
2012-05-30 Cedric Bail 2012-05-30 Cedric Bail
* Force cancel of all running Ecore_Thread on shutdown. * Force cancel of all running Ecore_Thread on shutdown.
* Make Ecore_Thread work reliabily when main loop isn't running.
2012-05-30 Mariusz Grzegorczyk 2012-05-30 Mariusz Grzegorczyk

View File

@ -16,6 +16,7 @@ Fixes:
- Send mouse move event before mouse down event in ecore_extn - Send mouse move event before mouse down event in ecore_extn
- Reduce race condition on shutdown of Ecore_Thread. - Reduce race condition on shutdown of Ecore_Thread.
- Force cancel of all running Ecore_Thread on shutdown. - Force cancel of all running Ecore_Thread on shutdown.
- Make Ecore_Thread work reliably when called without a running main loop.
Ecore 1.2.0 Ecore 1.2.0

View File

@ -709,10 +709,8 @@ _thread_safe_cleanup(void *data)
eina_lock_free(&call->m); eina_lock_free(&call->m);
} }
static void void
_thread_callback(void *data __UNUSED__, _ecore_main_call_flush(void)
void *buffer __UNUSED__,
unsigned int nbyte __UNUSED__)
{ {
Ecore_Safe_Call *call; Ecore_Safe_Call *call;
Eina_List *callback; Eina_List *callback;
@ -762,3 +760,11 @@ _thread_callback(void *data __UNUSED__,
} }
} }
static void
_thread_callback(void *data __UNUSED__,
void *buffer __UNUSED__,
unsigned int nbyte __UNUSED__)
{
_ecore_main_call_flush();
}

View File

@ -224,6 +224,8 @@ void _ecore_main_loop_shutdown(void);
void _ecore_throttle(void); void _ecore_throttle(void);
void _ecore_main_call_flush(void);
extern int _ecore_main_lock_count; extern int _ecore_main_lock_count;
extern Eina_Lock _ecore_main_loop_lock; extern Eina_Lock _ecore_main_loop_lock;

View File

@ -168,7 +168,7 @@ struct _Ecore_Pthread_Worker
const void *data; const void *data;
volatile int cancel; int cancel;
#ifdef EFL_HAVE_THREADS #ifdef EFL_HAVE_THREADS
LK(cancel_mutex); LK(cancel_mutex);
@ -280,7 +280,7 @@ _ecore_thread_data_free(void *data)
static void static void
_ecore_thread_join(PH(thread)) _ecore_thread_join(PH(thread))
{ {
PHJ(thread); PHJ(thread);
} }
static void static void
@ -674,6 +674,7 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
const void *data) const void *data)
{ {
Ecore_Pthread_Worker *work; Ecore_Pthread_Worker *work;
Eina_Bool tried = EINA_FALSE;
#ifdef EFL_HAVE_THREADS #ifdef EFL_HAVE_THREADS
PH(thread); PH(thread);
#endif #endif
@ -721,17 +722,20 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
LKL(_ecore_pending_job_threads_mutex); LKL(_ecore_pending_job_threads_mutex);
retry:
if (PHC(thread, _ecore_thread_worker, NULL) == 0) if (PHC(thread, _ecore_thread_worker, NULL) == 0)
{ {
_ecore_thread_count++; _ecore_thread_count++;
LKU(_ecore_pending_job_threads_mutex); LKU(_ecore_pending_job_threads_mutex);
return (Ecore_Thread *)work; return (Ecore_Thread *)work;
} }
LKU(_ecore_pending_job_threads_mutex); if (!tried)
{
_ecore_main_call_flush();
tried = EINA_TRUE;
goto retry;
}
eina_threads_shutdown();
LKL(_ecore_pending_job_threads_mutex);
if (_ecore_thread_count == 0) if (_ecore_thread_count == 0)
{ {
_ecore_pending_job_threads = eina_list_remove(_ecore_pending_job_threads, work); _ecore_pending_job_threads = eina_list_remove(_ecore_pending_job_threads, work);
@ -746,6 +750,9 @@ ecore_thread_run(Ecore_Thread_Cb func_blocking,
work = NULL; work = NULL;
} }
LKU(_ecore_pending_job_threads_mutex); LKU(_ecore_pending_job_threads_mutex);
eina_threads_shutdown();
return (Ecore_Thread *)work; return (Ecore_Thread *)work;
#else #else
/* /*
@ -882,6 +889,7 @@ ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
{ {
#ifdef EFL_HAVE_THREADS #ifdef EFL_HAVE_THREADS
Ecore_Pthread_Worker *worker; Ecore_Pthread_Worker *worker;
Eina_Bool tried = EINA_FALSE;
PH(thread); PH(thread);
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
@ -918,8 +926,15 @@ ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
eina_threads_init(); eina_threads_init();
retry_direct:
if (PHC(t, _ecore_direct_worker, worker) == 0) if (PHC(t, _ecore_direct_worker, worker) == 0)
return (Ecore_Thread *)worker; return (Ecore_Thread *)worker;
if (!tried)
{
_ecore_main_call_flush();
tried = EINA_TRUE;
goto retry_direct;
}
if (worker->u.feedback_run.direct_worker) if (worker->u.feedback_run.direct_worker)
{ {
@ -947,12 +962,19 @@ ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
eina_threads_init(); eina_threads_init();
LKL(_ecore_pending_job_threads_mutex); LKL(_ecore_pending_job_threads_mutex);
retry:
if (PHC(thread, _ecore_thread_worker, NULL) == 0) if (PHC(thread, _ecore_thread_worker, NULL) == 0)
{ {
_ecore_thread_count++; _ecore_thread_count++;
LKU(_ecore_pending_job_threads_mutex); LKU(_ecore_pending_job_threads_mutex);
return (Ecore_Thread *)worker; return (Ecore_Thread *)worker;
} }
if (!tried)
{
_ecore_main_call_flush();
tried = EINA_TRUE;
goto retry;
}
LKU(_ecore_pending_job_threads_mutex); LKU(_ecore_pending_job_threads_mutex);
eina_threads_shutdown(); eina_threads_shutdown();