From: Enlightenment S. <no-...@en...> - 2010-10-06 13:01:41
|
Log: * ecore: fix typo. Author: cedric Date: 2010-10-06 06:01:35 -0700 (Wed, 06 Oct 2010) New Revision: 53098 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-06 12:24:14 UTC (rev 53097) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-06 13:01:35 UTC (rev 53098) @@ -590,7 +590,7 @@ /* Delay the destruction */ on_exit: - work->cancel = EINA_TRUE; + ((Ecore_Pthread_Worker *)thread)->cancel = EINA_TRUE; return EINA_FALSE; #else return EINA_TRUE; |
From: Enlightenment S. <no-...@en...> - 2010-10-11 13:27:09
|
Log: ecore: return more information on pipe_read error. Author: cedric Date: 2010-10-11 06:27:03 -0700 (Mon, 11 Oct 2010) New Revision: 53263 Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_pipe.c 2010-10-11 12:40:20 UTC (rev 53262) +++ trunk/ecore/src/lib/ecore/ecore_pipe.c 2010-10-11 13:27:03 UTC (rev 53263) @@ -512,9 +512,9 @@ return ECORE_CALLBACK_RENEW; else { - ERR("An unhandled error (ret: %zd errno: %d)" + ERR("An unhandled error (ret: %zd errno: %d [%s])" "occurred while reading from the pipe the length", - ret, errno); + ret, errno, strerror(errno)); return ECORE_CALLBACK_RENEW; } #else |
From: Enlightenment S. <no-...@en...> - 2010-10-13 16:44:23
|
Log: * ecore: turn on and off eina threads support when needed. Author: cedric Date: 2010-10-13 09:44:15 -0700 (Wed, 13 Oct 2010) New Revision: 53364 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-13 16:40:52 UTC (rev 53363) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-13 16:44:15 UTC (rev 53364) @@ -124,6 +124,8 @@ if (pthread_join(pth->thread, (void **) &p) != 0) return ; + eina_threads_shutdown(); + _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth); ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL); @@ -479,9 +481,13 @@ pth->p = ecore_pipe_add(_ecore_thread_handler, NULL); if (!pth->p) goto on_error; + eina_threads_init(); + if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0) return (Ecore_Thread *) work; + eina_threads_shutdown(); + on_error: if (pth) { @@ -562,6 +568,8 @@ work->func_cancel((void *) work->data); free(work); + eina_threads_shutdown(); + return EINA_TRUE; } } @@ -578,6 +586,8 @@ work->func_cancel((void *) work->data); free(work); + eina_threads_shutdown(); + return EINA_TRUE; } } @@ -698,9 +708,13 @@ pth->p = ecore_pipe_add(_ecore_thread_handler, NULL); if (!pth->p) goto on_error; + eina_threads_init(); + if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0) return (Ecore_Thread *) worker; + eina_threads_shutdown(); + on_error: if (pth) { |
From: Enlightenment S. <no-...@en...> - 2010-10-13 17:45:14
|
Log: * ecore: fix possible race. It also make ecore_thread_run match ecore_thread_feedback_run better. NOTE: I know it breaks API/ABI compatibility for that call, but that's the only sane solution I could found. Author: cedric Date: 2010-10-13 10:45:07 -0700 (Wed, 13 Oct 2010) New Revision: 53370 Modified: trunk/ecore/src/lib/ecore/Ecore.h trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/Ecore.h =================================================================== --- trunk/ecore/src/lib/ecore/Ecore.h 2010-10-13 17:42:09 UTC (rev 53369) +++ trunk/ecore/src/lib/ecore/Ecore.h 2010-10-13 17:45:07 UTC (rev 53370) @@ -408,14 +408,14 @@ - EAPI Ecore_Thread *ecore_thread_run(Ecore_Cb, - Ecore_Cb, - Ecore_Cb, + EAPI Ecore_Thread *ecore_thread_run(Ecore_Thread_Heavy_Cb func_blocking, + Ecore_Cb func_end, + Ecore_Cb func_cancel, const void *data); - EAPI Ecore_Thread *ecore_thread_feedback_run(Ecore_Thread_Heavy_Cb, - Ecore_Thread_Notify_Cb, - Ecore_Cb, - Ecore_Cb, + EAPI Ecore_Thread *ecore_thread_feedback_run(Ecore_Thread_Heavy_Cb func_heavy, + Ecore_Thread_Notify_Cb func_notify, + Ecore_Cb func_end, + Ecore_Cb func_cancel, const void *data, Eina_Bool try_no_queue); EAPI Eina_Bool ecore_thread_cancel(Ecore_Thread *thread); Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-13 17:42:09 UTC (rev 53369) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-13 17:45:07 UTC (rev 53370) @@ -35,7 +35,7 @@ { union { struct { - Ecore_Cb func_blocking; + Ecore_Thread_Heavy_Cb func_blocking; } short_run; struct { Ecore_Thread_Heavy_Cb func_heavy; @@ -218,7 +218,7 @@ pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); if (!work->cancel) - work->u.short_run.func_blocking((void *) work->data); + work->u.short_run.func_blocking((Ecore_Thread*) work, (void *) work->data); ecore_pipe_write(end_pipe, &work, sizeof (Ecore_Pthread_Worker *)); } @@ -434,7 +434,7 @@ * host CPU can handle. */ EAPI Ecore_Thread * -ecore_thread_run(Ecore_Cb func_blocking, +ecore_thread_run(Ecore_Thread_Heavy_Cb func_blocking, Ecore_Cb func_end, Ecore_Cb func_cancel, const void *data) @@ -508,7 +508,7 @@ If no thread and as we don't want to break app that rely on this facility, we will lock the interface until we are done. */ - func_blocking((void *)data); + func_blocking((Ecore_Thread *) work, (void *)data); func_end((void *)data); return NULL; @@ -525,7 +525,9 @@ * will return EINA_FALSE, if the destruction is delayed or EINA_TRUE if it is * cancelled after this call. * - * You should use this function only in the main loop. + * This function work in the main loop and in the thread, but you should not pass + * the Ecore_Thread variable from main loop to the worker thread in any structure. + * You should always use the one passed to the Ecore_Thread_Heavy_Cb. * * func_end, func_cancel will destroy the handler, so don't use it after. * And if ecore_thread_cancel return EINA_TRUE, you should not use Ecore_Thread also. |
From: Enlightenment S. <no-...@en...> - 2010-10-14 16:45:24
|
Log: * ecore: don't leak pipe. Author: cedric Date: 2010-10-14 09:45:17 -0700 (Thu, 14 Oct 2010) New Revision: 53410 Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_pipe.c 2010-10-14 16:19:17 UTC (rev 53409) +++ trunk/ecore/src/lib/ecore/ecore_pipe.c 2010-10-14 16:45:17 UTC (rev 53410) @@ -524,6 +524,8 @@ /* XXX What should we do here? */ ERR("Only read %zd bytes from the pipe, although" " we need to read %zd bytes.", ret, sizeof(p->len)); + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_CANCEL; } else if (ret == 0) { @@ -536,7 +538,10 @@ } #ifndef _WIN32 else if ((ret == PIPE_FD_ERROR) && ((errno == EINTR) || (errno == EAGAIN))) - return ECORE_CALLBACK_RENEW; + { + _ecore_pipe_unhandle(p); + return ECORE_CALLBACK_RENEW; + } else { ERR("An unhandled error (ret: %zd errno: %d [%s])" @@ -596,7 +601,9 @@ } #ifndef _WIN32 else if (ret == PIPE_FD_ERROR && (errno == EINTR || errno == EAGAIN)) - return ECORE_CALLBACK_RENEW; + { + return ECORE_CALLBACK_RENEW; + } else { ERR("An unhandled error (ret: %zd errno: %d)" |
From: Enlightenment S. <no-...@en...> - 2010-10-14 16:45:54
|
Log: * ecore: improve and fix ecore_thread destruction. Author: cedric Date: 2010-10-14 09:45:48 -0700 (Thu, 14 Oct 2010) New Revision: 53411 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-14 16:45:17 UTC (rev 53410) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-14 16:45:48 UTC (rev 53411) @@ -92,6 +92,7 @@ static pthread_cond_t _ecore_thread_global_hash_cond = PTHREAD_COND_INITIALIZER; static pthread_t main_loop_thread; static Eina_Bool have_main_loop_thread = 0; + static void _ecore_thread_data_free(void *data) { @@ -107,6 +108,7 @@ Ecore_Pipe *p = event; ecore_pipe_del(p); + eina_threads_shutdown(); } static Eina_Bool @@ -124,8 +126,6 @@ if (pthread_join(pth->thread, (void **) &p) != 0) return ; - eina_threads_shutdown(); - _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth); ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL); @@ -213,7 +213,8 @@ } 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); + _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, + _ecore_pending_job_threads); pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); @@ -240,7 +241,8 @@ } work = eina_list_data_get(_ecore_pending_job_threads_feedback); - _ecore_pending_job_threads_feedback = eina_list_remove_list(_ecore_pending_job_threads_feedback, _ecore_pending_job_threads_feedback); + _ecore_pending_job_threads_feedback = eina_list_remove_list(_ecore_pending_job_threads_feedback, + _ecore_pending_job_threads_feedback); pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); @@ -314,7 +316,7 @@ _ecore_thread_count++; pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); - on_error: + restart: if (_ecore_pending_job_threads) _ecore_short_job(pth->p); if (_ecore_pending_job_threads_feedback) _ecore_feedback_job(pth->p, pth->thread); @@ -324,16 +326,30 @@ if (_ecore_pending_job_threads) { pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); - goto on_error; + goto restart; } if (_ecore_pending_job_threads_feedback) { pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); - goto on_error; + goto restart; } + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + /* Sleep a little to prevent premature death */ + usleep(200); + + pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + if (_ecore_pending_job_threads) + { + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + goto restart; + } + if (_ecore_pending_job_threads_feedback) + { + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + goto restart; + } _ecore_thread_count--; - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); work = malloc(sizeof (Ecore_Pthread_Worker)); @@ -389,6 +405,13 @@ free(work); } + EINA_LIST_FREE(_ecore_pending_job_threads_feedback, work) + { + if (work->func_cancel) + work->func_cancel((void *)work->data); + free(work); + } + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); EINA_LIST_FREE(_ecore_active_job_threads, pth) @@ -492,11 +515,16 @@ if (pth) { if (pth->p) ecore_pipe_del(pth->p); + pth->p = NULL; free(pth); } if (_ecore_thread_count == 0) { + pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + _ecore_pending_job_threads = eina_list_remove(_ecore_pending_job_threads, work); + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + if (work->func_cancel) work->func_cancel((void *) work->data); free(work); @@ -570,8 +598,6 @@ work->func_cancel((void *) work->data); free(work); - eina_threads_shutdown(); - return EINA_TRUE; } } @@ -588,8 +614,6 @@ work->func_cancel((void *) work->data); free(work); - eina_threads_shutdown(); - return EINA_TRUE; } } @@ -726,6 +750,11 @@ if (_ecore_thread_count == 0) { + pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + _ecore_pending_job_threads_feedback = eina_list_remove(_ecore_pending_job_threads_feedback, + worker); + pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + if (func_cancel) func_cancel((void *) data); if (worker) |
From: Enlightenment S. <no-...@en...> - 2010-10-25 09:39:07
|
Log: * ecore: always check for func_cancel being not NULL before using it. Reported by Hugo Camboulive <hug...@gm...>. Author: cedric Date: 2010-10-25 02:39:00 -0700 (Mon, 25 Oct 2010) New Revision: 53851 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-25 09:14:19 UTC (rev 53850) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-10-25 09:39:00 UTC (rev 53851) @@ -481,7 +481,8 @@ work = malloc(sizeof (Ecore_Pthread_Worker)); if (!work) { - func_cancel((void *) data); + if (func_cancel) + func_cancel((void *) data); return NULL; } @@ -801,7 +802,7 @@ func_heavy((Ecore_Thread *) &worker, (void *)data); - if (worker.cancel) func_cancel((void *)data); + if (worker.func_cancel) func_cancel((void *)data); else func_end((void *)data); return NULL; |
From: Enlightenment S. <no-...@en...> - 2010-11-17 16:26:14
|
Log: * ecore: revert comment. This code is here to prevent the premature death of thread when apps killall of them, before recreating them again. This avoid call to pthread_create and increase throughput. The only information that I couldn't determine pragmatically is the timing. So that's the time the main loop has to create another Ecore_Thread, before needing to call pthread_create again. Author: cedric Date: 2010-11-17 08:26:08 -0800 (Wed, 17 Nov 2010) New Revision: 54633 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-17 16:19:01 UTC (rev 54632) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-17 16:26:08 UTC (rev 54633) @@ -336,10 +336,7 @@ pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); /* Sleep a little to prevent premature death */ -// any code with something like this in it to "avoid some race condition" -// especially with just 200micro-seconds is asking for trouble. disable -// this. -// usleep(200); + usleep(200); pthread_mutex_lock(&_ecore_pending_job_threads_mutex); if (_ecore_pending_job_threads) |
From: Enlightenment S. <no-...@en...> - 2010-11-23 16:52:28
|
Log: * ecore: small cleanup. Author: cedric Date: 2010-11-23 08:52:18 -0800 (Tue, 23 Nov 2010) New Revision: 54893 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-23 16:50:16 UTC (rev 54892) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-23 16:52:18 UTC (rev 54893) @@ -21,6 +21,49 @@ #include "Ecore.h" #include "ecore_private.h" +#ifdef EFL_HAVE_PTHREAD +# include <pthread.h> + +# define PH(x) pthread_t x +# define PHE(x, y) pthread_equal(x, y) +# define PHS() pthread_self() +# define PHC(x, f, d) pthread_create(&(x), NULL, (void*) f, d) +# define PHJ(x, p) pthread_join(x, (void**)(&(p))) +# define PHA(x) pthread_cancel(x) + +# define CD(x) pthread_cond_t x +# define CDI(x) pthread_cond_init(&(x), NULL); +# define CDD(x) pthread_cond_destroy(&(x)); +# define CDB(x) pthread_cond_broadcast(&(x)); +# define CDW(x, y, t) pthread_cond_timedwait(&(x), &(y), t); + +# define LK(x) pthread_mutex_t x +# define LKI(x) pthread_mutex_init(&(x), NULL); +# define LKD(x) pthread_mutex_destroy(&(x)); +# define LKL(x) pthread_mutex_lock(&(x)); +# define LKU(x) pthread_mutex_unlock(&(x)); + +# define LRWK(x) pthread_rwlock_t x +# define LRWKI(x) pthread_rwlock_init(&(x), NULL); +# define LRWKD(x) pthread_rwlock_destroy(&(x)); +# define LRWKWL(x) pthread_rwlock_wrlock(&(x)); +# define LRWKRL(x) pthread_rwlock_rdlock(&(x)); +# define LRWKU(x) pthread_rwlock_unlock(&(x)); + +#else /* EFL_HAVE_WIN32_THREADS */ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# undef WIN32_LEAN_AND_MEAN + +# error "Please define PH*, CD* and LRWK* on windows" + +# define LK(x) HANDLE x +# define LKI(x) x = CreateMutex(NULL, FALSE, NULL) +# define LKD(x) CloseHandle(x) +# define LKL(x) WaitForSingleObject(x, INFINITE) +# define LKU(x) ReleaseMutex(x) +#endif + typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker; typedef struct _Ecore_Pthread Ecore_Pthread; typedef struct _Ecore_Thread_Data Ecore_Thread_Data; @@ -50,10 +93,10 @@ Ecore_Thread_Cb func_cancel; Ecore_Thread_Cb func_end; #ifdef EFL_HAVE_PTHREAD - pthread_t self; + PH(self); Eina_Hash *hash; - pthread_cond_t cond; - pthread_mutex_t mutex; + CD(cond); + LK(mutex); #endif const void *data; @@ -70,7 +113,7 @@ { Ecore_Pipe *p; void *data; - pthread_t thread; + PH(thread); }; #endif @@ -80,17 +123,18 @@ #ifdef EFL_HAVE_PTHREAD static int _ecore_thread_count = 0; +static Ecore_Event_Handler *del_handler = NULL; static Eina_List *_ecore_active_job_threads = NULL; static Eina_List *_ecore_pending_job_threads = NULL; static Eina_List *_ecore_pending_job_threads_feedback = NULL; -static Ecore_Event_Handler *del_handler = NULL; -static pthread_mutex_t _ecore_pending_job_threads_mutex = PTHREAD_MUTEX_INITIALIZER; +static LK(_ecore_pending_job_threads_mutex); static Eina_Hash *_ecore_thread_global_hash = NULL; -static pthread_rwlock_t _ecore_thread_global_hash_lock = PTHREAD_RWLOCK_INITIALIZER; -static pthread_mutex_t _ecore_thread_global_hash_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t _ecore_thread_global_hash_cond = PTHREAD_COND_INITIALIZER; -static pthread_t main_loop_thread; +static LRWK(_ecore_thread_global_hash_lock); +static LK(_ecore_thread_global_hash_mutex); +static CD(_ecore_thread_global_hash_cond); + +static PH(main_loop_thread); static Eina_Bool have_main_loop_thread = 0; static void @@ -123,7 +167,7 @@ { Ecore_Pipe *p; - if (pthread_join(pth->thread, (void **) &p) != 0) + if (PHJ(pth->thread, p) != 0) return ; _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth); @@ -148,8 +192,8 @@ if (work->feedback_run) ecore_pipe_del(work->u.feedback_run.notify); - pthread_cond_destroy(&work->cond); - pthread_mutex_destroy(&work->mutex); + CDD(work->cond); + LKD(work->mutex); if (work->hash) eina_hash_free(work->hash); free(work); @@ -204,11 +248,11 @@ while (_ecore_pending_job_threads) { - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); if (!_ecore_pending_job_threads) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); break; } @@ -216,7 +260,7 @@ _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, _ecore_pending_job_threads); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); if (!work->cancel) work->u.short_run.func_blocking((void *) work->data, (Ecore_Thread*) work); @@ -226,17 +270,17 @@ } static void -_ecore_feedback_job(Ecore_Pipe *end_pipe, pthread_t thread) +_ecore_feedback_job(Ecore_Pipe *end_pipe, PH(thread)) { Ecore_Pthread_Worker *work; while (_ecore_pending_job_threads_feedback) { - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); if (!_ecore_pending_job_threads_feedback) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); break; } @@ -244,7 +288,7 @@ _ecore_pending_job_threads_feedback = eina_list_remove_list(_ecore_pending_job_threads_feedback, _ecore_pending_job_threads_feedback); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); work->self = thread; if (!work->cancel) @@ -272,7 +316,7 @@ free(pth); return NULL; } - pth->thread = pthread_self(); + pth->thread = PHS(); work->self = pth->thread; work->u.feedback_run.func_heavy((void *) work->data, (Ecore_Thread *) work); @@ -295,8 +339,8 @@ work->feedback_run = EINA_FALSE; work->kill = EINA_FALSE; work->hash = NULL; - pthread_cond_init(&work->cond, NULL); - pthread_mutex_init(&work->mutex, NULL); + CDI(work->cond); + LKI(work->mutex); ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *)); @@ -312,9 +356,9 @@ pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); eina_sched_prio_drop(); - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); _ecore_thread_count++; - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); restart: if (_ecore_pending_job_threads) _ecore_short_job(pth->p); @@ -322,35 +366,25 @@ /* FIXME: Check if there is feedback running task todo, and switch to feedback run handler. */ - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); - if (_ecore_pending_job_threads) + LKL(_ecore_pending_job_threads_mutex); + if (_ecore_pending_job_threads || _ecore_pending_job_threads_feedback) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); goto restart; } - if (_ecore_pending_job_threads_feedback) - { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); - goto restart; - } - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); /* Sleep a little to prevent premature death */ usleep(200); - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); - if (_ecore_pending_job_threads) + LKL(_ecore_pending_job_threads_mutex); + if (_ecore_pending_job_threads || _ecore_pending_job_threads_feedback) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); goto restart; } - if (_ecore_pending_job_threads_feedback) - { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); - goto restart; - } _ecore_thread_count--; - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); work = malloc(sizeof (Ecore_Pthread_Worker)); if (!work) return NULL; @@ -363,8 +397,8 @@ work->feedback_run = EINA_FALSE; work->kill = EINA_FALSE; work->hash = NULL; - pthread_cond_init(&work->cond, NULL); - pthread_mutex_init(&work->mutex, NULL); + CDI(work->cond); + LKI(work->mutex); ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *)); @@ -383,8 +417,13 @@ ECORE_THREAD_PIPE_DEL = ecore_event_type_new(); #ifdef EFL_HAVE_PTHREAD del_handler = ecore_event_handler_add(ECORE_THREAD_PIPE_DEL, _ecore_thread_pipe_del, NULL); - main_loop_thread = pthread_self(); + main_loop_thread = PHS(); have_main_loop_thread = 1; + + LKI(_ecore_pending_job_threads_mutex); + LRWKI(_ecore_thread_global_hash_lock); + LKI(_ecore_thread_global_hash_mutex); + CDI(_ecore_thread_global_hash_cond); #endif } @@ -396,7 +435,7 @@ Ecore_Pthread_Worker *work; Ecore_Pthread_Data *pth; - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); EINA_LIST_FREE(_ecore_pending_job_threads, work) { @@ -412,14 +451,15 @@ free(work); } - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); + /* Improve emergency shutdown */ EINA_LIST_FREE(_ecore_active_job_threads, pth) { Ecore_Pipe *p; - pthread_cancel(pth->thread); - pthread_join(pth->thread, (void **) &p); + PHA(pth->thread); + PHJ(pth->thread, p); ecore_pipe_del(pth->p); } @@ -428,6 +468,11 @@ ecore_event_handler_del(del_handler); have_main_loop_thread = 0; del_handler = NULL; + + LKD(_ecore_pending_job_threads_mutex); + LRWKD(_ecore_thread_global_hash_lock); + LKD(_ecore_thread_global_hash_mutex); + CDD(_ecore_thread_global_hash_cond); #endif } @@ -496,19 +541,19 @@ #ifdef EFL_HAVE_PTHREAD work->hash = NULL; - pthread_cond_init(&work->cond, NULL); - pthread_mutex_init(&work->mutex, NULL); + CDI(work->cond); + LKI(work->mutex); - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); _ecore_pending_job_threads = eina_list_append(_ecore_pending_job_threads, work); if (_ecore_thread_count == _ecore_thread_count_max) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return (Ecore_Thread *) work; } - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); /* One more thread could be created. */ pth = malloc(sizeof (Ecore_Pthread_Data)); @@ -519,7 +564,7 @@ eina_threads_init(); - if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0) + if (PHC(pth->thread, _ecore_thread_worker, pth) == 0) return (Ecore_Thread *) work; eina_threads_shutdown(); @@ -534,9 +579,9 @@ if (_ecore_thread_count == 0) { - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); _ecore_pending_job_threads = eina_list_remove(_ecore_pending_job_threads, work); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); if (work->func_cancel) work->func_cancel((void *) work->data, (Ecore_Thread *) work); @@ -596,10 +641,10 @@ goto on_exit; } - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); if ((have_main_loop_thread) && - (pthread_equal(main_loop_thread, pthread_self()))) + (PHE(main_loop_thread, PHS()))) { if (!work->feedback_run) EINA_LIST_FOREACH(_ecore_pending_job_threads, l, work) @@ -608,7 +653,7 @@ { _ecore_pending_job_threads = eina_list_remove_list(_ecore_pending_job_threads, l); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); if (work->func_cancel) work->func_cancel((void *) work->data, (Ecore_Thread *) work); @@ -624,7 +669,7 @@ { _ecore_pending_job_threads_feedback = eina_list_remove_list(_ecore_pending_job_threads_feedback, l); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); if (work->func_cancel) work->func_cancel((void *) work->data, (Ecore_Thread *) work); @@ -635,7 +680,7 @@ } } - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); /* Delay the destruction */ on_exit: @@ -711,8 +756,8 @@ worker->u.feedback_run.func_heavy = func_heavy; worker->u.feedback_run.func_notify = func_notify; worker->hash = NULL; - pthread_cond_init(&worker->cond, NULL); - pthread_mutex_init(&worker->mutex, NULL); + CDI(worker->cond); + LKI(worker->mutex); worker->func_cancel = func_cancel; worker->func_end = func_end; worker->data = data; @@ -726,22 +771,22 @@ if (!try_no_queue) { - pthread_t t; + PH(t); - if (pthread_create(&t, NULL, (void *) _ecore_direct_worker, worker) == 0) + if (PHC(t, _ecore_direct_worker, worker) == 0) return (Ecore_Thread *) worker; } - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); _ecore_pending_job_threads_feedback = eina_list_append(_ecore_pending_job_threads_feedback, worker); if (_ecore_thread_count == _ecore_thread_count_max) { - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return (Ecore_Thread *) worker; } - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); /* One more thread could be created. */ pth = malloc(sizeof (Ecore_Pthread_Data)); @@ -752,7 +797,7 @@ eina_threads_init(); - if (pthread_create(&pth->thread, NULL, (void *) _ecore_thread_worker, pth) == 0) + if (PHC(pth->thread, _ecore_thread_worker, pth) == 0) return (Ecore_Thread *) worker; eina_threads_shutdown(); @@ -766,10 +811,10 @@ if (_ecore_thread_count == 0) { - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); _ecore_pending_job_threads_feedback = eina_list_remove(_ecore_pending_job_threads_feedback, worker); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); if (func_cancel) func_cancel((void *) data, NULL); @@ -833,7 +878,7 @@ if (!worker->feedback_run) return EINA_FALSE; #ifdef EFL_HAVE_PTHREAD - if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE; + if (!PHE(worker->self, PHS())) return EINA_FALSE; worker->u.feedback_run.send++; ecore_pipe_write(worker->u.feedback_run.notify, &data, sizeof (void *)); @@ -873,9 +918,9 @@ { int ret; #ifdef EFL_HAVE_PTHREAD - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); ret = eina_list_count(_ecore_pending_job_threads); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return ret; #else return 0; @@ -893,9 +938,9 @@ { int ret; #ifdef EFL_HAVE_PTHREAD - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); ret = eina_list_count(_ecore_pending_job_threads_feedback); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return ret; #else return 0; @@ -913,9 +958,9 @@ { int ret; #ifdef EFL_HAVE_PTHREAD - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); ret = eina_list_count(_ecore_pending_job_threads) + eina_list_count(_ecore_pending_job_threads_feedback); - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return ret; #else return 0; @@ -973,9 +1018,9 @@ { int ret; #ifdef EFL_HAVE_PTHREAD - pthread_mutex_lock(&_ecore_pending_job_threads_mutex); + LKL(_ecore_pending_job_threads_mutex); ret = _ecore_thread_count_max - _ecore_thread_count; - pthread_mutex_unlock(&_ecore_pending_job_threads_mutex); + LKU(_ecore_pending_job_threads_mutex); return ret; #else return 0; @@ -1007,7 +1052,7 @@ if ((!thread) || (!key) || (!value)) return EINA_FALSE; #ifdef EFL_HAVE_PTHREAD - if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE; + if (!PHE(worker->self, PHS())) return EINA_FALSE; if (!worker->hash) worker->hash = eina_hash_string_small_new(_ecore_thread_data_free); @@ -1025,7 +1070,7 @@ ret = eina_hash_direct_add(worker->hash, key, d); else ret = eina_hash_add(worker->hash, key, d); - pthread_cond_broadcast(&worker->cond); + CDB(worker->cond); return ret; #else return EINA_TRUE; @@ -1054,7 +1099,7 @@ if ((!thread) || (!key) || (!value)) return NULL; #ifdef EFL_HAVE_PTHREAD - if (!pthread_equal(worker->self, pthread_self())) return NULL; + if (!PHE(worker->self, PHS())) return NULL; if (!worker->hash) worker->hash = eina_hash_string_small_new(_ecore_thread_data_free); @@ -1069,7 +1114,7 @@ d->cb = cb; r = eina_hash_set(worker->hash, key, d); - pthread_cond_broadcast(&worker->cond); + CDB(worker->cond); ret = r->data; free(r); return ret; @@ -1097,7 +1142,7 @@ if ((!thread) || (!key)) return NULL; #ifdef EFL_HAVE_PTHREAD - if (!pthread_equal(worker->self, pthread_self())) return NULL; + if (!PHE(worker->self, PHS())) return NULL; if (!worker->hash) return NULL; @@ -1126,7 +1171,7 @@ if ((!thread) || (!key)) return EINA_FALSE; #ifdef EFL_HAVE_PTHREAD - if (!pthread_equal(worker->self, pthread_self())) return EINA_FALSE; + if (!PHE(worker->self, PHS())) return EINA_FALSE; if (!worker->hash) return EINA_FALSE; @@ -1159,10 +1204,10 @@ if ((!key) || (!value)) return EINA_FALSE; #ifdef EFL_HAVE_PTHREAD - pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock); + LRWKWL(_ecore_thread_global_hash_lock); if (!_ecore_thread_global_hash) _ecore_thread_global_hash = eina_hash_string_small_new(_ecore_thread_data_free); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); + LRWKU(_ecore_thread_global_hash_lock); if (!(d = malloc(sizeof(Ecore_Thread_Data)))) return EINA_FALSE; @@ -1172,13 +1217,13 @@ if (!_ecore_thread_global_hash) return EINA_FALSE; - pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock); + LRWKWL(_ecore_thread_global_hash_lock); if (direct) ret = eina_hash_direct_add(_ecore_thread_global_hash, key, d); else ret = eina_hash_add(_ecore_thread_global_hash, key, d); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); - pthread_cond_broadcast(&_ecore_thread_global_hash_cond); + LRWKU(_ecore_thread_global_hash_lock); + CDB(_ecore_thread_global_hash_cond); return ret; #else return EINA_TRUE; @@ -1207,10 +1252,10 @@ if ((!key) || (!value)) return NULL; #ifdef EFL_HAVE_PTHREAD - pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock); + LRWKWL(_ecore_thread_global_hash_lock); if (!_ecore_thread_global_hash) _ecore_thread_global_hash = eina_hash_string_small_new(_ecore_thread_data_free); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); + LRWKU(_ecore_thread_global_hash_lock); if (!_ecore_thread_global_hash) return NULL; @@ -1221,10 +1266,10 @@ d->data = value; d->cb = cb; - pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock); + LRWKWL(_ecore_thread_global_hash_lock); r = eina_hash_set(_ecore_thread_global_hash, key, d); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); - pthread_cond_broadcast(&_ecore_thread_global_hash_cond); + LRWKU(_ecore_thread_global_hash_lock); + CDB(_ecore_thread_global_hash_cond); ret = r->data; free(r); @@ -1256,9 +1301,9 @@ #ifdef EFL_HAVE_PTHREAD if (!_ecore_thread_global_hash) return NULL; - pthread_rwlock_rdlock(&_ecore_thread_global_hash_lock); + LRWKRL(_ecore_thread_global_hash_lock); ret = eina_hash_find(_ecore_thread_global_hash, key); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); + LRWKU(_ecore_thread_global_hash_lock); return ret->data; #else return NULL; @@ -1285,11 +1330,11 @@ if (!_ecore_thread_global_hash) return EINA_FALSE; - pthread_rwlock_wrlock(&_ecore_thread_global_hash_lock); + LRWKWL(_ecore_thread_global_hash_lock); if ((d = eina_hash_find(_ecore_thread_global_hash, key))) _ecore_thread_data_free(d); ret = eina_hash_del_by_key(_ecore_thread_global_hash, key); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); + LRWKU(_ecore_thread_global_hash_lock); return ret; #else return EINA_TRUE; @@ -1327,14 +1372,14 @@ t.tv_sec = (long int)time; t.tv_nsec = (long int)((time - (double)t.tv_sec) * 1000000000); - pthread_rwlock_rdlock(&_ecore_thread_global_hash_lock); + LRWKRL(_ecore_thread_global_hash_lock); ret = eina_hash_find(_ecore_thread_global_hash, key); - pthread_rwlock_unlock(&_ecore_thread_global_hash_lock); + LRWKU(_ecore_thread_global_hash_lock); if ((ret) || (!seconds) || ((seconds > 0) && (time <= ecore_time_get()))) break; - pthread_mutex_lock(&_ecore_thread_global_hash_mutex); - pthread_cond_timedwait(&_ecore_thread_global_hash_cond, &_ecore_thread_global_hash_mutex, &t); - pthread_mutex_unlock(&_ecore_thread_global_hash_mutex); + LKL(_ecore_thread_global_hash_mutex); + CDW(_ecore_thread_global_hash_cond, _ecore_thread_global_hash_mutex, &t); + LKU(_ecore_thread_global_hash_mutex); } if (ret) return ret->data; return NULL; |
From: Enlightenment S. <no-...@en...> - 2010-11-23 18:32:24
|
Log: * ecore: improve speed by reusing pipe and allocated structure. Author: cedric Date: 2010-11-23 10:32:17 -0800 (Tue, 23 Nov 2010) New Revision: 54896 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-23 18:13:00 UTC (rev 54895) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2010-11-23 18:32:17 UTC (rev 54896) @@ -85,6 +85,9 @@ Ecore_Thread_Notify_Cb func_notify; Ecore_Pipe *notify; + Ecore_Pipe *direct_pipe; + Ecore_Pthread_Worker *direct_worker; + int send; int received; } feedback_run; @@ -111,15 +114,28 @@ struct _Ecore_Pthread_Data { + Ecore_Pthread_Worker *death_job; Ecore_Pipe *p; void *data; PH(thread); }; #endif +static void _ecore_thread_handler(void *data __UNUSED__, void *buffer, unsigned int nbyte); + static int _ecore_thread_count_max = 0; static int ECORE_THREAD_PIPE_DEL = 0; +static Eina_Array *_ecore_thread_pipe = NULL; +static Ecore_Pipe* +_ecore_thread_pipe_get(void) +{ + if (eina_array_count_get(_ecore_thread_pipe) > 0) + return eina_array_pop(_ecore_thread_pipe); + + return ecore_pipe_add(_ecore_thread_handler, NULL); +} + #ifdef EFL_HAVE_PTHREAD static int _ecore_thread_count = 0; @@ -137,7 +153,35 @@ static PH(main_loop_thread); static Eina_Bool have_main_loop_thread = 0; +static Eina_Trash *_ecore_thread_worker_trash = NULL; +static int _ecore_thread_worker_count = 0; + +static Ecore_Pthread_Worker * +_ecore_thread_worker_new(void) +{ + Ecore_Pthread_Worker *result; + + result = eina_trash_pop(&_ecore_thread_worker_trash); + + if (!result) result = malloc(sizeof (Ecore_Pthread_Worker)); + else _ecore_thread_worker_count--; + + return result; +} + static void +_ecore_thread_worker_free(Ecore_Pthread_Worker *worker) +{ + if (_ecore_thread_worker_count > (_ecore_thread_count_max + 1) * 16) + { + free(worker); + return ; + } + + eina_trash_push(&_ecore_thread_worker_trash, worker); +} + +static void _ecore_thread_data_free(void *data) { Ecore_Thread_Data *d = data; @@ -151,7 +195,7 @@ { Ecore_Pipe *p = event; - ecore_pipe_del(p); + eina_array_push(_ecore_thread_pipe, p); eina_threads_shutdown(); } @@ -191,7 +235,14 @@ } if (work->feedback_run) - ecore_pipe_del(work->u.feedback_run.notify); + { + ecore_pipe_del(work->u.feedback_run.notify); + + if (work->u.feedback_run.direct_pipe) + eina_array_push(_ecore_thread_pipe, work->u.feedback_run.direct_pipe); + if (work->u.feedback_run.direct_worker) + _ecore_thread_worker_free(work->u.feedback_run.direct_worker); + } CDD(work->cond); LKD(work->mutex); if (work->hash) @@ -310,7 +361,7 @@ pth = malloc(sizeof (Ecore_Pthread_Data)); if (!pth) return NULL; - pth->p = ecore_pipe_add(_ecore_thread_handler, NULL); + pth->p = work->u.feedback_run.direct_pipe; if (!pth->p) { free(pth); @@ -323,10 +374,9 @@ ecore_pipe_write(pth->p, &work, sizeof (Ecore_Pthread_Worker *)); - work = malloc(sizeof (Ecore_Pthread_Worker)); + work = work->u.feedback_run.direct_worker; if (!work) { - ecore_pipe_del(pth->p); free(pth); return NULL; } @@ -386,7 +436,7 @@ _ecore_thread_count--; LKU(_ecore_pending_job_threads_mutex); - work = malloc(sizeof (Ecore_Pthread_Worker)); + work = pth->death_job; if (!work) return NULL; work->data = pth; @@ -415,6 +465,8 @@ _ecore_thread_count_max = 1; ECORE_THREAD_PIPE_DEL = ecore_event_type_new(); + _ecore_thread_pipe = eina_array_new(8); + #ifdef EFL_HAVE_PTHREAD del_handler = ecore_event_handler_add(ECORE_THREAD_PIPE_DEL, _ecore_thread_pipe_del, NULL); main_loop_thread = PHS(); @@ -431,6 +483,10 @@ _ecore_thread_shutdown(void) { /* FIXME: If function are still running in the background, should we kill them ? */ + Ecore_Pipe *p; + Eina_Array_Iterator it; + unsigned int i; + #ifdef EFL_HAVE_PTHREAD Ecore_Pthread_Worker *work; Ecore_Pthread_Data *pth; @@ -474,6 +530,12 @@ LKD(_ecore_thread_global_hash_mutex); CDD(_ecore_thread_global_hash_cond); #endif + + EINA_ARRAY_ITER_NEXT(_ecore_thread_pipe, i, p, it) + ecore_pipe_del(p); + + eina_array_free(_ecore_thread_pipe); + _ecore_thread_pipe = NULL; } /** @@ -523,7 +585,7 @@ if (!func_blocking) return NULL; - work = malloc(sizeof (Ecore_Pthread_Worker)); + work = _ecore_thread_worker_new(); if (!work) { if (func_cancel) @@ -559,8 +621,9 @@ pth = malloc(sizeof (Ecore_Pthread_Data)); if (!pth) goto on_error; - pth->p = ecore_pipe_add(_ecore_thread_handler, NULL); - if (!pth->p) goto on_error; + pth->p = _ecore_thread_pipe_get(); + pth->death_job = _ecore_thread_worker_new(); + if (!pth->p || !pth->death_job) goto on_error; eina_threads_init(); @@ -572,8 +635,8 @@ on_error: if (pth) { - if (pth->p) ecore_pipe_del(pth->p); - pth->p = NULL; + if (pth->p) eina_array_push(_ecore_thread_pipe, pth->p); + if (pth->death_job) _ecore_thread_worker_free(pth->death_job); free(pth); } @@ -750,7 +813,7 @@ if (!func_heavy) return NULL; - worker = malloc(sizeof (Ecore_Pthread_Worker)); + worker = _ecore_thread_worker_new(); if (!worker) goto on_error; worker->u.feedback_run.func_heavy = func_heavy; @@ -768,11 +831,16 @@ worker->u.feedback_run.received = 0; worker->u.feedback_run.notify = ecore_pipe_add(_ecore_notify_handler, worker); + worker->u.feedback_run.direct_pipe = NULL; + worker->u.feedback_run.direct_worker = NULL; if (!try_no_queue) { PH(t); + worker->u.feedback_run.direct_pipe = _ecore_thread_pipe_get(); + worker->u.feedback_run.direct_worker = _ecore_thread_worker_new(); + if (PHC(t, _ecore_direct_worker, worker) == 0) return (Ecore_Thread *) worker; } @@ -792,8 +860,9 @@ pth = malloc(sizeof (Ecore_Pthread_Data)); if (!pth) goto on_error; - pth->p = ecore_pipe_add(_ecore_thread_handler, NULL); - if (!pth->p) goto on_error; + pth->p = _ecore_thread_pipe_get(); + pth->death_job = _ecore_thread_worker_new(); + if (!pth->p || !pth->death_job) goto on_error; eina_threads_init(); @@ -805,7 +874,8 @@ on_error: if (pth) { - if (pth->p) ecore_pipe_del(pth->p); + if (pth->p) eina_array_push(_ecore_thread_pipe, pth->p); + if (pth->death_job) _ecore_thread_worker_free(pth->death_job); free(pth); } |
From: Enlightenment S. <no-...@en...> - 2011-05-19 15:38:37
|
Log: ecore: improve ecore_timer_dump. Now E17 msgbus module will provide an usefull way to list all the running timer and see if we are not waking up to often. Use d-feet to see that information. Author: cedric Date: 2011-05-19 08:38:30 -0700 (Thu, 19 May 2011) New Revision: 59542 Trac: http://trac.enlightenment.org/e/changeset/59542 Modified: trunk/ecore/src/lib/ecore/ecore_timer.c Modified: trunk/ecore/src/lib/ecore/ecore_timer.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_timer.c 2011-05-19 15:24:39 UTC (rev 59541) +++ trunk/ecore/src/lib/ecore/ecore_timer.c 2011-05-19 15:38:30 UTC (rev 59542) @@ -175,6 +175,12 @@ if (!timer) return NULL; ECORE_MAGIC_SET(timer, ECORE_MAGIC_TIMER); now = ecore_loop_time_get(); + +#ifdef WANT_ECORE_TIMER_DUMP + timer->timer_bt_num = backtrace((void**) (timer->timer_bt), + ECORE_TIMER_DEBUG_BT_NUM); +#endif + _ecore_timer_set(timer, now + in, in, func, (void *)data); return timer; } @@ -368,6 +374,8 @@ char *out; Ecore_Timer *tm; Eina_List *tmp = NULL; + int living_timer = 0; + int unknow_timer = 0; result = eina_strbuf_new(); @@ -379,9 +387,15 @@ char **strings; int j; + if (!tm->frozen && !tm->delete_me) + living_timer++; + strings = backtrace_symbols((void**) tm->timer_bt, tm->timer_bt_num); - if (strings == NULL) - continue ; + if (tm->timer_bt_num <= 0 || strings == NULL) + { + unknow_timer++; + continue ; + } eina_strbuf_append_printf(result, "*** timer: %f ***\n", tm->in); if (tm->frozen) @@ -394,6 +408,8 @@ free(strings); } + eina_strbuf_append_printf(result, "\n***\nThere is %i living timer.\nWe did lost track of %i timers.\n", living_timer, unknow_timer); + out = eina_strbuf_string_steal(result); eina_strbuf_free(result); @@ -669,5 +685,5 @@ const Ecore_Timer *t1 = d1; const Ecore_Timer *t2 = d2; - return (int) t1->in - t2->in; + return (int) ((t1->in - t2->in) * 100); } |
From: Enlightenment S. <no-...@en...> - 2011-06-09 15:32:14
|
Log: ecore: since... Author: cedric Date: 2011-06-09 08:32:08 -0700 (Thu, 09 Jun 2011) New Revision: 60136 Trac: http://trac.enlightenment.org/e/changeset/60136 Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c Modified: trunk/ecore/src/lib/ecore/ecore_pipe.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_pipe.c 2011-06-09 14:54:24 UTC (rev 60135) +++ trunk/ecore/src/lib/ecore/ecore_pipe.c 2011-06-09 15:32:08 UTC (rev 60136) @@ -395,6 +395,7 @@ * for monitoring it again. * * @param p The Ecore_Pipe object. + * @since 1.1 */ EAPI void ecore_pipe_freeze(Ecore_Pipe *p) @@ -417,6 +418,7 @@ * ecore_pipe_read_close() was previously called on the same pipe. * * @param p The Ecore_Pipe object. + * @since 1.1 */ EAPI void ecore_pipe_thaw(Ecore_Pipe *p) @@ -443,6 +445,7 @@ * @param message_count The minimal number of message to wait before exiting. * @param wait The amount of time in second to wait before exiting. * @return the number of message catched during that wait call. + * @since 1.1 * * Negative value for @p wait means infite wait. */ |
From: Enlightenment S. <no-...@en...> - 2011-06-28 14:53:41
|
Log: ecore: actually limit the number of pipe in the cache. Author: cedric Date: 2011-06-28 07:53:34 -0700 (Tue, 28 Jun 2011) New Revision: 60763 Trac: http://trac.enlightenment.org/e/changeset/60763 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-28 14:38:17 UTC (rev 60762) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-28 14:53:34 UTC (rev 60763) @@ -420,7 +420,10 @@ { Ecore_Pipe *p = event; - eina_array_push(_ecore_thread_pipe, p); + if (eina_array_count_get(_ecore_thread_pipe) < 50) + eina_array_push(_ecore_thread_pipe, p); + else + ecore_pipe_del(p); eina_threads_shutdown(); } |
From: Enlightenment S. <no-...@en...> - 2011-06-28 15:53:26
|
Log: ecore: do count threads only in the main loop. NOTE: for an unknow reason I always get the wrong number of threads when doing the computation from the thread. Even if I use volatile and mutex. So to avoid that move that stuff in the main loop. It increase the complexity of the code, but at least it work. Author: cedric Date: 2011-06-28 08:53:19 -0700 (Tue, 28 Jun 2011) New Revision: 60767 Trac: http://trac.enlightenment.org/e/changeset/60767 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-28 15:05:29 UTC (rev 60766) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-28 15:53:19 UTC (rev 60767) @@ -345,6 +345,7 @@ Eina_Bool feedback_run : 1; Eina_Bool kill : 1; Eina_Bool reschedule : 1; + Eina_Bool no_queue : 1; }; #ifdef EFL_HAVE_THREADS @@ -394,6 +395,9 @@ static Eina_Trash *_ecore_thread_worker_trash = NULL; static int _ecore_thread_worker_count = 0; +static void *_ecore_thread_worker(Ecore_Pthread_Data *pth); +static Ecore_Pthread_Worker *_ecore_thread_worker_new(void); + static void _ecore_thread_worker_free(Ecore_Pthread_Worker *worker) { @@ -435,13 +439,41 @@ } static void -_ecore_thread_end(Ecore_Pthread_Data *pth, __UNUSED__ Ecore_Thread *work) +_ecore_thread_end(Ecore_Pthread_Data *pth, Ecore_Thread *work) { + Ecore_Pthread_Worker *worker = (Ecore_Pthread_Worker *) work; Ecore_Pipe *p; + if (!worker->message_run || !worker->feedback_run || (worker->feedback_run && !worker->no_queue)) + _ecore_thread_count--; + if (PHJ(pth->thread, p) != 0) return ; + if (eina_list_count(_ecore_pending_job_threads) > 0 + && (unsigned int) _ecore_thread_count < eina_list_count(_ecore_pending_job_threads) + && _ecore_thread_count < _ecore_thread_count_max) + { + /* One more thread should be created. */ + INF("spawning threads because of still pending jobs."); + + pth->death_job = _ecore_thread_worker_new(); + if (!pth->p || !pth->death_job) goto end; + + eina_threads_init(); + + if (PHC(pth->thread, _ecore_thread_worker, pth) == 0) + { + _ecore_thread_count++; + return ; + } + + eina_threads_shutdown(); + + end: + if (pth->death_job) _ecore_thread_worker_free(pth->death_job); + } + _ecore_active_job_threads = eina_list_remove(_ecore_active_job_threads, pth); ecore_event_add(ECORE_THREAD_PIPE_DEL, pth->p, _ecore_thread_pipe_free, NULL); @@ -662,10 +694,6 @@ eina_sched_prio_drop(); - LKL(_ecore_pending_job_threads_mutex); - _ecore_thread_count++; - LKU(_ecore_pending_job_threads_mutex); - restart: if (_ecore_pending_job_threads) _ecore_short_job(pth->p); if (_ecore_pending_job_threads_feedback) _ecore_feedback_job(pth->p, pth->thread); @@ -693,7 +721,6 @@ LKU(_ecore_pending_job_threads_mutex); goto restart; } - _ecore_thread_count--; LKU(_ecore_pending_job_threads_mutex); work = pth->death_job; @@ -906,7 +933,10 @@ eina_threads_init(); if (PHC(pth->thread, _ecore_thread_worker, pth) == 0) - return (Ecore_Thread *) work; + { + _ecore_thread_count++; + return (Ecore_Thread *) work; + } eina_threads_shutdown(); @@ -1129,11 +1159,14 @@ worker->u.feedback_run.direct_pipe = _ecore_thread_pipe_get(); worker->u.feedback_run.direct_worker = _ecore_thread_worker_new(); + worker->no_queue = EINA_TRUE; if (PHC(t, _ecore_direct_worker, worker) == 0) return (Ecore_Thread *) worker; } + worker->no_queue = EINA_FALSE; + LKL(_ecore_pending_job_threads_mutex); _ecore_pending_job_threads_feedback = eina_list_append(_ecore_pending_job_threads_feedback, worker); @@ -1156,7 +1189,10 @@ eina_threads_init(); if (PHC(pth->thread, _ecore_thread_worker, pth) == 0) - return (Ecore_Thread *) worker; + { + _ecore_thread_count++; + return (Ecore_Thread *) worker; + } eina_threads_shutdown(); |
From: Enlightenment S. <no-...@en...> - 2011-06-29 08:24:20
|
Log: ecore: forgotten eina_threads_init/shutdown. Author: cedric Date: 2011-06-29 01:24:13 -0700 (Wed, 29 Jun 2011) New Revision: 60801 Trac: http://trac.enlightenment.org/e/changeset/60801 Modified: trunk/ecore/src/lib/ecore/ecore_thread.c Modified: trunk/ecore/src/lib/ecore/ecore_thread.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-29 07:11:54 UTC (rev 60800) +++ trunk/ecore/src/lib/ecore/ecore_thread.c 2011-06-29 08:24:13 UTC (rev 60801) @@ -1161,8 +1161,12 @@ worker->u.feedback_run.direct_worker = _ecore_thread_worker_new(); worker->no_queue = EINA_TRUE; + eina_threads_init(); + if (PHC(t, _ecore_direct_worker, worker) == 0) return (Ecore_Thread *) worker; + + eina_threads_shutdown(); } worker->no_queue = EINA_FALSE; |
From: Enlightenment S. <no-...@en...> - 2011-07-29 14:59:52
|
Log: ecore: now you don't need to care if you are in the main loop or not when you call ecore_main_loop_thread_safe_call. Author: cedric Date: 2011-07-29 07:59:43 -0700 (Fri, 29 Jul 2011) New Revision: 61897 Trac: http://trac.enlightenment.org/e/changeset/61897 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-07-29 14:56:42 UTC (rev 61896) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-07-29 14:59:43 UTC (rev 61897) @@ -225,6 +225,12 @@ { Ecore_Safe_Call *order; + if (eina_main_loop_is()) + { + callback(data); + return ; + } + order = malloc(sizeof (Ecore_Safe_Call)); if (!order) return ; |
From: Enlightenment S. <no-...@en...> - 2011-08-01 12:16:45
|
Log: ecore: merge call to main loop together to reduce number of main loop wakeup. Author: cedric Date: 2011-08-01 05:16:39 -0700 (Mon, 01 Aug 2011) New Revision: 61947 Trac: http://trac.enlightenment.org/e/changeset/61947 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-08-01 11:16:27 UTC (rev 61946) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-08-01 12:16:39 UTC (rev 61947) @@ -61,6 +61,7 @@ }; static void _thread_callback(void *data, void *buffer, unsigned int nbyte); +static Eina_List *_thread_cb = NULL; static Ecore_Pipe *_thread_call = NULL; static Eina_Lock _thread_safety; @@ -224,6 +225,8 @@ ecore_main_loop_thread_safe_call(Ecore_Cb callback, void *data) { Ecore_Safe_Call *order; + int wakeup = 42; + Eina_Bool count; if (eina_main_loop_is()) { @@ -238,7 +241,11 @@ order->data = data; eina_lock_take(&_thread_safety); - ecore_pipe_write(_thread_call, &order, sizeof (Ecore_Safe_Call*)); + + count = _thread_cb ? 0 : 1; + _thread_cb = eina_list_append(_thread_cb, order); + if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int)); + eina_lock_release(&_thread_safety); } @@ -469,16 +476,21 @@ #endif static void -_thread_callback(void *data __UNUSED__, void *buffer, unsigned int nbyte) +_thread_callback(void *data __UNUSED__, + void *buffer __UNUSED__, + unsigned int nbyte __UNUSED__) { - Ecore_Safe_Call *call = buffer; + Ecore_Safe_Call *call; + Eina_List *callback; - while (nbyte >= sizeof (Ecore_Safe_Call*)) + eina_lock_take(&_thread_safety); + callback = _thread_cb; + _thread_cb = NULL; + eina_lock_release(&_thread_safety); + + EINA_LIST_FREE(callback, call) { call->cb(call->data); free(call); - - call++; - nbyte -= sizeof (Ecore_Safe_Call*); } } |
From: Enlightenment S. <no-...@en...> - 2011-08-09 08:50:53
|
Log: ecore: remove bad macro from ecore. Author: cedric Date: 2011-08-09 01:50:47 -0700 (Tue, 09 Aug 2011) New Revision: 62241 Trac: http://trac.enlightenment.org/e/changeset/62241 Modified: trunk/ecore/src/lib/ecore/ecore_app.c trunk/ecore/src/lib/ecore/ecore_private.h Modified: trunk/ecore/src/lib/ecore/ecore_app.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore_app.c 2011-08-09 08:48:57 UTC (rev 62240) +++ trunk/ecore/src/lib/ecore/ecore_app.c 2011-08-09 08:50:47 UTC (rev 62241) @@ -43,7 +43,7 @@ EAPI void ecore_app_args_set(int argc, const char **argv) { - ECORE_MAIN_LOOP_ASSERT(); + EINA_MAIN_LOOP_CHECK_RETURN; if ((argc < 1) || (!argv)) return; @@ -65,7 +65,7 @@ EAPI void ecore_app_args_get(int *argc, char ***argv) { - ECORE_MAIN_LOOP_ASSERT(); + EINA_MAIN_LOOP_CHECK_RETURN; if (argc) *argc = app_argc; if (argv) *argv = app_argv; Modified: trunk/ecore/src/lib/ecore/ecore_private.h =================================================================== --- trunk/ecore/src/lib/ecore/ecore_private.h 2011-08-09 08:48:57 UTC (rev 62240) +++ trunk/ecore/src/lib/ecore/ecore_private.h 2011-08-09 08:50:47 UTC (rev 62241) @@ -187,10 +187,7 @@ void _ecore_thread_init(void); void _ecore_thread_shutdown(void); -void _ecore_thread_assert_main_loop_thread(const char *function); -#define ECORE_MAIN_LOOP_ASSERT() _ecore_thread_assert_main_loop_thread(__FUNCTION__) - void _ecore_glib_init(void); void _ecore_glib_shutdown(void); @@ -209,7 +206,7 @@ static inline void _ecore_lock(void) { /* at least check we're not being called from a thread */ - ECORE_MAIN_LOOP_ASSERT(); + EINA_MAIN_LOOP_CHECK_RETURN; } static inline void _ecore_unlock(void) |
From: Enlightenment S. <no-...@en...> - 2011-08-17 09:43:55
|
Log: ecore: add clean thread safety mecanism. Author: cedric Date: 2011-08-17 02:43:49 -0700 (Wed, 17 Aug 2011) New Revision: 62531 Trac: http://trac.enlightenment.org/e/changeset/62531 Modified: trunk/ecore/src/lib/ecore/Ecore.h trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/Ecore.h =================================================================== --- trunk/ecore/src/lib/ecore/Ecore.h 2011-08-17 09:42:43 UTC (rev 62530) +++ trunk/ecore/src/lib/ecore/Ecore.h 2011-08-17 09:43:49 UTC (rev 62531) @@ -444,6 +444,34 @@ */ EAPI void *ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, void *data); + /** + * @brief This function suspend the main loop in a know state + * @since 1.1.0 + * + * @result EINA_TRUE if the main loop was suspended correcly. + * + * This function suspend the main loop in a know state, this let you + * use any EFL call you want after it return. Be carefull, the main loop + * is blocked until you call ecore_thread_main_loop_end(). This is + * the only sane way to achieve pseudo thread safety. + * + * Notice that until the main loop is blocked, the thread is blocked + * and their is noway around that. + * + * We still advise you, when possible, to use ecore_main_loop_thread_safe_call_async() + * as it will not block the thread nor the main loop. + */ + EAPI Eina_Bool ecore_thread_main_loop_begin(void); + + /** + * @brief Unlock the main loop. + * @since 1.1.0 + * + * After a call to ecore_thread_main_loop_begin(), you need to absolutly + * call ecore_thread_main_loop_end(), or you application will stay frozen. + */ + EAPI void ecore_thread_main_loop_end(void); + /** * @} */ Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-08-17 09:42:43 UTC (rev 62530) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-08-17 09:43:49 UTC (rev 62531) @@ -66,6 +66,7 @@ Eina_Condition c; Eina_Bool sync : 1; + Eina_Bool suspend : 1; }; static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order); @@ -74,6 +75,11 @@ static Eina_List *_thread_cb = NULL; static Ecore_Pipe *_thread_call = NULL; static Eina_Lock _thread_safety; + +static Eina_Bool _thread_loop = EINA_FALSE; +static Eina_Lock _thread_mutex; +static Eina_Condition _thread_cond; + Eina_Lock _ecore_main_loop_lock; int _ecore_main_lock_count; @@ -151,9 +157,12 @@ _ecore_time_init(); eina_lock_new(&_thread_safety); - eina_lock_new(&_ecore_main_loop_lock); + eina_lock_new(&_thread_mutex); + eina_condition_new(&_thread_cond, &_thread_mutex); _thread_call = ecore_pipe_add(_thread_callback, NULL); + eina_lock_new(&_ecore_main_loop_lock); + #if HAVE_MALLINFO if (getenv("ECORE_MEM_STAT")) { @@ -265,6 +274,7 @@ order->cb.async = callback; order->data = data; order->sync = EINA_FALSE; + order->suspend = EINA_FALSE; _ecore_main_loop_thread_safe_call(order); } @@ -290,6 +300,7 @@ eina_lock_new(&order->m); eina_condition_new(&order->c, &order->m); order->sync = EINA_TRUE; + order->suspend = EINA_FALSE; _ecore_main_loop_thread_safe_call(order); @@ -308,7 +319,45 @@ return ret; } +EAPI Eina_Bool +ecore_thread_main_loop_begin(void) +{ + Ecore_Safe_Call *order; + + if (eina_main_loop_is()) + return EINA_FALSE; + + order = malloc(sizeof (Ecore_Safe_Call)); + if (!order) return EINA_FALSE; + + eina_lock_new(&order->m); + eina_condition_new(&order->c, &order->m); + order->suspend = EINA_TRUE; + + _ecore_main_loop_thread_safe_call(order); + + eina_lock_take(&order->m); + eina_condition_wait(&order->c); + eina_lock_release(&order->m); + + eina_main_loop_define(); + + _thread_loop = EINA_TRUE; + + return EINA_TRUE; +} + EAPI void +ecore_thread_main_loop_end(void) +{ + if (!_thread_loop) return ; + /* until we unlock the main loop, this thread has the main loop id */ + if (!eina_main_loop_is()) return ; + + eina_condition_broadcast(&_thread_cond); +} + +EAPI void ecore_print_warning(const char *function, const char *sparam) { WRN("***** Developer Warning ***** :\n" @@ -568,8 +617,21 @@ EINA_LIST_FREE(callback, call) { - if (call->sync) + if (call->suspend) { + eina_condition_broadcast(&call->c); + + eina_lock_take(&_thread_mutex); + eina_condition_wait(&_thread_cond); + eina_lock_release(&_thread_mutex); + + eina_main_loop_define(); + + _thread_safe_cleanup(call); + free(call); + } + else if (call->sync) + { call->data = call->cb.sync(call->data); eina_condition_broadcast(&call->c); } |
From: Enlightenment S. <no-...@en...> - 2011-08-22 09:47:23
|
Log: ecore: make ecore_thread_main_loop_begin/end() recursive. Author: cedric Date: 2011-08-22 02:47:17 -0700 (Mon, 22 Aug 2011) New Revision: 62687 Trac: http://trac.enlightenment.org/e/changeset/62687 Modified: trunk/ecore/src/lib/ecore/Ecore.h trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/Ecore.h =================================================================== --- trunk/ecore/src/lib/ecore/Ecore.h 2011-08-22 09:44:19 UTC (rev 62686) +++ trunk/ecore/src/lib/ecore/Ecore.h 2011-08-22 09:47:17 UTC (rev 62687) @@ -448,7 +448,8 @@ * @brief This function suspend the main loop in a know state * @since 1.1.0 * - * @result EINA_TRUE if the main loop was suspended correctly. + * @result the number of time ecore_thread_main_loop_begin() has been called + * in this thread, if the main loop was suspended correctly. If not, it return @c -1. * * This function suspend the main loop in a know state, this let you * use any EFL call you want after it return. Be carefull, the main loop @@ -461,16 +462,20 @@ * We still advise you, when possible, to use ecore_main_loop_thread_safe_call_async() * as it will not block the thread nor the main loop. */ - EAPI Eina_Bool ecore_thread_main_loop_begin(void); + EAPI int ecore_thread_main_loop_begin(void); /** * @brief Unlock the main loop. * @since 1.1.0 * + * @result the number of time ecore_thread_main_loop_end() need to be called before + * the main loop is unlocked again. @c -1 will be returned if you are trying to unlock + * when there wasn't enough call to ecore_thread_main_loop_begin(). + * * After a call to ecore_thread_main_loop_begin(), you need to absolutly * call ecore_thread_main_loop_end(), or you application will stay frozen. */ - EAPI void ecore_thread_main_loop_end(void); + EAPI int ecore_thread_main_loop_end(void); /** * @} Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-08-22 09:44:19 UTC (rev 62686) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-08-22 09:47:17 UTC (rev 62687) @@ -76,7 +76,7 @@ static Ecore_Pipe *_thread_call = NULL; static Eina_Lock _thread_safety; -static Eina_Bool _thread_loop = EINA_FALSE; +static int _thread_loop = 0; static Eina_Lock _thread_mutex; static Eina_Condition _thread_cond; @@ -319,16 +319,18 @@ return ret; } -EAPI Eina_Bool +EAPI int ecore_thread_main_loop_begin(void) { Ecore_Safe_Call *order; if (eina_main_loop_is()) - return EINA_FALSE; + { + return ++_thread_loop; + } order = malloc(sizeof (Ecore_Safe_Call)); - if (!order) return EINA_FALSE; + if (!order) return -1; eina_lock_new(&order->m); eina_condition_new(&order->c, &order->m); @@ -342,19 +344,34 @@ eina_main_loop_define(); - _thread_loop = EINA_TRUE; + _thread_loop = 1; return EINA_TRUE; } -EAPI void +EAPI int ecore_thread_main_loop_end(void) { - if (!_thread_loop) return ; + if (_thread_loop == 0) + { + ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin()."); + return -1; + } + /* until we unlock the main loop, this thread has the main loop id */ - if (!eina_main_loop_is()) return ; + if (!eina_main_loop_is()) + { + ERR("Not in a locked thread !"); + return -1; + } + _thread_loop--; + if (_thread_loop > 0) + return _thread_loop; + eina_condition_broadcast(&_thread_cond); + + return 0; } EAPI void |
From: Enlightenment S. <no-...@en...> - 2011-09-15 11:15:53
|
Log: ecore: prevent race condition when using sync call after begin/end. Author: cedric Date: 2011-09-15 04:15:46 -0700 (Thu, 15 Sep 2011) New Revision: 63407 Trac: http://trac.enlightenment.org/e/changeset/63407 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-09-15 07:33:23 UTC (rev 63406) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-09-15 11:15:46 UTC (rev 63407) @@ -79,6 +79,8 @@ static int _thread_loop = 0; static Eina_Lock _thread_mutex; static Eina_Condition _thread_cond; +static Eina_Lock _thread_feedback_mutex; +static Eina_Condition _thread_feedback_cond; Eina_Lock _ecore_main_loop_lock; int _ecore_main_lock_count; @@ -159,6 +161,8 @@ eina_lock_new(&_thread_safety); eina_lock_new(&_thread_mutex); eina_condition_new(&_thread_cond, &_thread_mutex); + eina_lock_new(&_thread_feedback_mutex); + eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex); _thread_call = ecore_pipe_add(_thread_callback, NULL); eina_lock_new(&_ecore_main_loop_lock); @@ -208,6 +212,10 @@ ecore_pipe_del(_thread_call); eina_lock_free(&_thread_safety); + eina_condition_free(&_thread_cond); + eina_lock_free(&_thread_mutex); + eina_condition_free(&_thread_feedback_cond); + eina_lock_free(&_thread_feedback_mutex); if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); _ecore_poller_shutdown(); @@ -371,6 +379,10 @@ eina_condition_broadcast(&_thread_cond); + eina_lock_take(&_thread_feedback_mutex); + eina_condition_wait(&_thread_feedback_cond); + eina_lock_release(&_thread_feedback_mutex); + return 0; } @@ -636,14 +648,17 @@ { if (call->suspend) { + eina_lock_take(&_thread_mutex); + eina_condition_broadcast(&call->c); - eina_lock_take(&_thread_mutex); eina_condition_wait(&_thread_cond); eina_lock_release(&_thread_mutex); eina_main_loop_define(); + eina_condition_broadcast(&_thread_feedback_cond); + _thread_safe_cleanup(call); free(call); } |
From: Enlightenment S. <no-...@en...> - 2011-09-16 09:31:56
|
Log: ecore: reduce race condition. Author: cedric Date: 2011-09-16 02:31:47 -0700 (Fri, 16 Sep 2011) New Revision: 63436 Trac: http://trac.enlightenment.org/e/changeset/63436 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-09-16 09:15:27 UTC (rev 63435) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-09-16 09:31:47 UTC (rev 63436) @@ -377,9 +377,8 @@ if (_thread_loop > 0) return _thread_loop; - eina_condition_broadcast(&_thread_cond); - eina_lock_take(&_thread_feedback_mutex); + eina_condition_broadcast(&_thread_cond); eina_condition_wait(&_thread_feedback_cond); eina_lock_release(&_thread_feedback_mutex); |
From: Enlightenment S. <no-...@en...> - 2011-09-23 10:47:39
|
Log: ecore: prevent spurious wakeup and lock the right mutex. Author: cedric Date: 2011-09-23 03:47:33 -0700 (Fri, 23 Sep 2011) New Revision: 63565 Trac: http://trac.enlightenment.org/e/changeset/63565 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-09-23 10:37:30 UTC (rev 63564) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-09-23 10:47:33 UTC (rev 63565) @@ -65,6 +65,8 @@ Eina_Lock m; Eina_Condition c; + int current_id; + Eina_Bool sync : 1; Eina_Bool suspend : 1; }; @@ -82,6 +84,10 @@ static Eina_Lock _thread_feedback_mutex; static Eina_Condition _thread_feedback_cond; +static Eina_Lock _thread_id_lock; +static int _thread_id = -1; +static int _thread_id_max = 0; + Eina_Lock _ecore_main_loop_lock; int _ecore_main_lock_count; @@ -164,6 +170,7 @@ eina_lock_new(&_thread_feedback_mutex); eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex); _thread_call = ecore_pipe_add(_thread_callback, NULL); + eina_lock_new(&_thread_id_lock); eina_lock_new(&_ecore_main_loop_lock); @@ -216,6 +223,7 @@ eina_lock_free(&_thread_mutex); eina_condition_free(&_thread_feedback_cond); eina_lock_free(&_thread_feedback_mutex); + eina_lock_free(&_thread_id_lock); if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); _ecore_poller_shutdown(); @@ -340,14 +348,24 @@ order = malloc(sizeof (Ecore_Safe_Call)); if (!order) return -1; + eina_lock_take(&_thread_id_lock); + order->current_id = ++_thread_id_max; + if (order->current_id < 0) + { + _thread_id_max = 0; + order->current_id = ++_thread_id_max; + } + eina_lock_release(&_thread_id_lock); + eina_lock_new(&order->m); eina_condition_new(&order->c, &order->m); order->suspend = EINA_TRUE; + eina_lock_take(&order->m); _ecore_main_loop_thread_safe_call(order); - eina_lock_take(&order->m); - eina_condition_wait(&order->c); + while (order->current_id != _thread_id) + eina_condition_wait(&order->c); eina_lock_release(&order->m); eina_main_loop_define(); @@ -360,6 +378,8 @@ EAPI int ecore_thread_main_loop_end(void) { + int current_id; + if (_thread_loop == 0) { ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin()."); @@ -377,9 +397,15 @@ if (_thread_loop > 0) return _thread_loop; + current_id = _thread_id; + + eina_lock_take(&_thread_mutex); + eina_condition_broadcast(&_thread_cond); + eina_lock_release(&_thread_mutex); + eina_lock_take(&_thread_feedback_mutex); - eina_condition_broadcast(&_thread_cond); - eina_condition_wait(&_thread_feedback_cond); + while (current_id == _thread_id) + eina_condition_wait(&_thread_feedback_cond); eina_lock_release(&_thread_feedback_mutex); return 0; @@ -649,14 +675,20 @@ { eina_lock_take(&_thread_mutex); + _thread_id = call->current_id; + eina_condition_broadcast(&call->c); eina_condition_wait(&_thread_cond); eina_lock_release(&_thread_mutex); + _thread_id = -1; + eina_main_loop_define(); + eina_lock_take(&_thread_feedback_mutex); eina_condition_broadcast(&_thread_feedback_cond); + eina_lock_release(&_thread_feedback_mutex); _thread_safe_cleanup(call); free(call); |
From: Enlightenment S. <no-...@en...> - 2011-09-23 13:27:06
|
Log: ecore: lock all broadcast. Author: cedric Date: 2011-09-23 06:26:54 -0700 (Fri, 23 Sep 2011) New Revision: 63567 Trac: http://trac.enlightenment.org/e/changeset/63567 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-09-23 13:17:12 UTC (rev 63566) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-09-23 13:26:54 UTC (rev 63567) @@ -87,6 +87,7 @@ static Eina_Lock _thread_id_lock; static int _thread_id = -1; static int _thread_id_max = 0; +static int _thread_id_update = 0; Eina_Lock _ecore_main_loop_lock; int _ecore_main_lock_count; @@ -361,9 +362,9 @@ eina_condition_new(&order->c, &order->m); order->suspend = EINA_TRUE; - eina_lock_take(&order->m); _ecore_main_loop_thread_safe_call(order); + eina_lock_take(&order->m); while (order->current_id != _thread_id) eina_condition_wait(&order->c); eina_lock_release(&order->m); @@ -400,6 +401,7 @@ current_id = _thread_id; eina_lock_take(&_thread_mutex); + _thread_id_update = _thread_id; eina_condition_broadcast(&_thread_cond); eina_lock_release(&_thread_mutex); @@ -675,11 +677,13 @@ { eina_lock_take(&_thread_mutex); + eina_lock_take(&call->m); _thread_id = call->current_id; - eina_condition_broadcast(&call->c); + eina_lock_release(&call->m); - eina_condition_wait(&_thread_cond); + while (_thread_id_update != _thread_id) + eina_condition_wait(&_thread_cond); eina_lock_release(&_thread_mutex); _thread_id = -1; |
From: Enlightenment S. <no-...@en...> - 2011-09-27 06:16:18
|
Log: ecore: prevent one last spurious wakeup. Author: cedric Date: 2011-09-26 23:16:11 -0700 (Mon, 26 Sep 2011) New Revision: 63619 Trac: http://trac.enlightenment.org/e/changeset/63619 Modified: trunk/ecore/src/lib/ecore/ecore.c Modified: trunk/ecore/src/lib/ecore/ecore.c =================================================================== --- trunk/ecore/src/lib/ecore/ecore.c 2011-09-27 04:05:41 UTC (rev 63618) +++ trunk/ecore/src/lib/ecore/ecore.c 2011-09-27 06:16:11 UTC (rev 63619) @@ -406,7 +406,7 @@ eina_lock_release(&_thread_mutex); eina_lock_take(&_thread_feedback_mutex); - while (current_id == _thread_id) + while (current_id == _thread_id && _thread_id != -1) eina_condition_wait(&_thread_feedback_cond); eina_lock_release(&_thread_feedback_mutex); @@ -686,11 +686,12 @@ eina_condition_wait(&_thread_cond); eina_lock_release(&_thread_mutex); - _thread_id = -1; - eina_main_loop_define(); eina_lock_take(&_thread_feedback_mutex); + + _thread_id = -1; + eina_condition_broadcast(&_thread_feedback_cond); eina_lock_release(&_thread_feedback_mutex); |