Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Tue, 20 Sep 2016 00:56:24 -0300 Gustavo Sverzut Barbierisaid: > On Mon, Sep 19, 2016 at 8:08 PM, Carsten Haitzler > wrote: > > On Mon, 19 Sep 2016 09:04:15 -0300 Gustavo Sverzut Barbieri > > said: > > > >> On Sun, Sep 18, 2016 at 2:03 PM, Carsten Haitzler > >> wrote: > >> > On Thu, 15 Sep 2016 08:00:46 -0300 Gustavo Sverzut Barbieri > >> > said: > >> > > >> >> isn't it better to check in ecore_thread_cancel() if the thread was > >> >> already created? > >> > > >> > that'd require keeping track of every thread we create, looking up in > >> > that list/table ever time etc. ... like eoid does. eina_thread stuff is > >> > are ally a tiny tiny tiny thin wrapper over posix (or windows or osx) > >> > threading - same with locks/semaphores etc. at this level such a complex > >> > check isn't really worth it. > >> > >> there is a single place inside ecore_thread_cancel() that calls this > >> function and it knows if t->self is 0 before calling. > > > > ummm... you're mixing ecore_thread and eina_thread. different things. :) > > this here is about eina_thread which has no t->self. t (thread) *IS* > > pthread_t. it's opaque. well it hapens to be pthread_t but we could change > > it and alloc a struct in future as long as abi remains the same. > > > > so how do we check if t (Eina_Thread) has been created. basically we'd need > > to > > > > if (eina_list_find(all_eina_threads, t)) > > return pthread_cancel((pthread_t)t) == 0; > > return EINA_FALSE; > > > > that means a list walk every time to go find the handle. every > > eina_thread_create() has to: > > > > all_eina_threads = eina_list_append(all_eina_threads, t); > > > > We could use a hash. an array. point is we don't track all threads. we'd > > have to start tracking them and to do a check would be a lookup like above. > > we're talking about different things for different reasons :-D i'm JUST talking eina_thread_cancel(). nothing else :) > I've added eina_thread_cancel() just to not expose pthread_cancel(). > Most of users should never ever call that directly as they will do > mistakes with the threads. pthread_cancel() should return ESRCH if the > thread couldn't be found... not SEGV. And it's doing that for other > stuff, like pthread_join()... which we simply call without doing any > check on given Eina_Thread (thus would crash as well). > > Users should use Ecore_Thread or something we may put on top (like > some Eo object). Ecore_Thread always provided ecore_thread_cancel(), > that only queues a request so users may ecore_thread_check() and stop > working. > > With my change, ecore_thread_cancel() will call eina_thread_cancel(), > usually that's innocuous as thread cancellation is disabled. If the > user choose to enable thread cancellation, that is going to cancel the > thread preemptively at some well known points (man:pthreads(7)). > > THUS, ecore_thread_cancel() does know if it create the thread, if the > thread was already joined, etc. It can easily check and do not call > eina_thread_cancel(). > > Alternatively we may EINA_SAFETY_CHECK all entry point of > eina_thread.h, but I don't think we should do that given how low level > it is. > > > > -- > Gustavo Sverzut Barbieri > -- > Mobile: +55 (16) 99354-9890 > -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Mon, Sep 19, 2016 at 8:08 PM, Carsten Haitzlerwrote: > On Mon, 19 Sep 2016 09:04:15 -0300 Gustavo Sverzut Barbieri > said: > >> On Sun, Sep 18, 2016 at 2:03 PM, Carsten Haitzler >> wrote: >> > On Thu, 15 Sep 2016 08:00:46 -0300 Gustavo Sverzut Barbieri >> > said: >> > >> >> isn't it better to check in ecore_thread_cancel() if the thread was >> >> already created? >> > >> > that'd require keeping track of every thread we create, looking up in that >> > list/table ever time etc. ... like eoid does. eina_thread stuff is are ally >> > a tiny tiny tiny thin wrapper over posix (or windows or osx) threading - >> > same with locks/semaphores etc. at this level such a complex check isn't >> > really worth it. >> >> there is a single place inside ecore_thread_cancel() that calls this >> function and it knows if t->self is 0 before calling. > > ummm... you're mixing ecore_thread and eina_thread. different things. :) this > here is about eina_thread which has no t->self. t (thread) *IS* pthread_t. > it's > opaque. well it hapens to be pthread_t but we could change it and alloc a > struct in future as long as abi remains the same. > > so how do we check if t (Eina_Thread) has been created. basically we'd need to > > if (eina_list_find(all_eina_threads, t)) > return pthread_cancel((pthread_t)t) == 0; > return EINA_FALSE; > > that means a list walk every time to go find the handle. every > eina_thread_create() has to: > > all_eina_threads = eina_list_append(all_eina_threads, t); > > We could use a hash. an array. point is we don't track all threads. we'd have > to start tracking them and to do a check would be a lookup like above. we're talking about different things for different reasons :-D I've added eina_thread_cancel() just to not expose pthread_cancel(). Most of users should never ever call that directly as they will do mistakes with the threads. pthread_cancel() should return ESRCH if the thread couldn't be found... not SEGV. And it's doing that for other stuff, like pthread_join()... which we simply call without doing any check on given Eina_Thread (thus would crash as well). Users should use Ecore_Thread or something we may put on top (like some Eo object). Ecore_Thread always provided ecore_thread_cancel(), that only queues a request so users may ecore_thread_check() and stop working. With my change, ecore_thread_cancel() will call eina_thread_cancel(), usually that's innocuous as thread cancellation is disabled. If the user choose to enable thread cancellation, that is going to cancel the thread preemptively at some well known points (man:pthreads(7)). THUS, ecore_thread_cancel() does know if it create the thread, if the thread was already joined, etc. It can easily check and do not call eina_thread_cancel(). Alternatively we may EINA_SAFETY_CHECK all entry point of eina_thread.h, but I don't think we should do that given how low level it is. -- Gustavo Sverzut Barbieri -- Mobile: +55 (16) 99354-9890 -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Mon, 19 Sep 2016 09:04:15 -0300 Gustavo Sverzut Barbierisaid: > On Sun, Sep 18, 2016 at 2:03 PM, Carsten Haitzler > wrote: > > On Thu, 15 Sep 2016 08:00:46 -0300 Gustavo Sverzut Barbieri > > said: > > > >> isn't it better to check in ecore_thread_cancel() if the thread was > >> already created? > > > > that'd require keeping track of every thread we create, looking up in that > > list/table ever time etc. ... like eoid does. eina_thread stuff is are ally > > a tiny tiny tiny thin wrapper over posix (or windows or osx) threading - > > same with locks/semaphores etc. at this level such a complex check isn't > > really worth it. > > there is a single place inside ecore_thread_cancel() that calls this > function and it knows if t->self is 0 before calling. ummm... you're mixing ecore_thread and eina_thread. different things. :) this here is about eina_thread which has no t->self. t (thread) *IS* pthread_t. it's opaque. well it hapens to be pthread_t but we could change it and alloc a struct in future as long as abi remains the same. so how do we check if t (Eina_Thread) has been created. basically we'd need to if (eina_list_find(all_eina_threads, t)) return pthread_cancel((pthread_t)t) == 0; return EINA_FALSE; that means a list walk every time to go find the handle. every eina_thread_create() has to: all_eina_threads = eina_list_append(all_eina_threads, t); We could use a hash. an array. point is we don't track all threads. we'd have to start tracking them and to do a check would be a lookup like above. -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Sun, Sep 18, 2016 at 2:03 PM, Carsten Haitzlerwrote: > On Thu, 15 Sep 2016 08:00:46 -0300 Gustavo Sverzut Barbieri > said: > >> isn't it better to check in ecore_thread_cancel() if the thread was >> already created? > > that'd require keeping track of every thread we create, looking up in that > list/table ever time etc. ... like eoid does. eina_thread stuff is are ally a > tiny tiny tiny thin wrapper over posix (or windows or osx) threading - same > with locks/semaphores etc. at this level such a complex check isn't really > worth > it. there is a single place inside ecore_thread_cancel() that calls this function and it knows if t->self is 0 before calling. -- Gustavo Sverzut Barbieri -- Mobile: +55 (16) 99354-9890 -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Thu, 15 Sep 2016 08:00:46 -0300 Gustavo Sverzut Barbierisaid: > isn't it better to check in ecore_thread_cancel() if the thread was > already created? that'd require keeping track of every thread we create, looking up in that list/table ever time etc. ... like eoid does. eina_thread stuff is are ally a tiny tiny tiny thin wrapper over posix (or windows or osx) threading - same with locks/semaphores etc. at this level such a complex check isn't really worth it. > On Wed, Sep 14, 2016 at 8:52 PM, Cedric BAIL wrote: > > cedric pushed a commit to branch master. > > > > http://git.enlightenment.org/core/efl.git/commit/?id=4d69f472fe31a9006436a05282a8376c7a712d41 > > > > commit 4d69f472fe31a9006436a05282a8376c7a712d41 > > Author: Cedric Bail > > Date: Wed Sep 14 16:50:05 2016 -0700 > > > > eina: allow graceful failure when calling eina_thread_cancel with NULL. > > --- > > src/lib/eina/eina_thread.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c > > index d40073a..5002a42 100644 > > --- a/src/lib/eina/eina_thread.c > > +++ b/src/lib/eina/eina_thread.c > > @@ -230,6 +230,7 @@ eina_thread_name_set(Eina_Thread t, const char *name) > > EAPI Eina_Bool > > eina_thread_cancel(Eina_Thread t) > > { > > + if (!t) return EINA_FALSE; > > return pthread_cancel((pthread_t)t) == 0; > > } > > > > > > -- > > > > > > > > -- > Gustavo Sverzut Barbieri > -- > Mobile: +55 (16) 99354-9890 > > -- > ___ > enlightenment-devel mailing list > enlightenment-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel > -- - Codito, ergo sum - "I code, therefore I am" -- The Rasterman (Carsten Haitzler)ras...@rasterman.com -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Thu, 15 Sep 2016 11:31:01 -0700 Cedric BAILsaid: > On Thu, Sep 15, 2016 at 4:00 AM, Gustavo Sverzut Barbieri > wrote: > > isn't it better to check in ecore_thread_cancel() if the thread was > > already created? > > I was wondering also, but settled for this as it will protect any > caller and the code is costly anyway, so no performance impact. actually i'd like to nip this in the bud here. it is not zero performance impact. that if and all the code inside the if's {} section are a cost. cost to code size. a cost to l1 cache for the INSTRUCTION cash (and cacheline prefetch). in fact i recently doubled the speed of eoid lookups JUST by removing if's and mostly their CONTENT because the content of "rare" error handling was more than just a return ... i moved the error handling to the function end with goto's and got a 2x speedup. in fact i want to do a general writeup on this... but this is very important. all out "if's" handling error input, printing some log etc. when such errors are the rare case, not common... we're losing a LOT of perf to l1 cache misses where l1 cachelines prefetched code we won't run. EINA_LIKELY/UNLIKELY doesn't help at all. this actually hasn't helped since 486 days. we really need to change our style. no longer: void func(void *p, int x, int y) { int z; if (!p) { ERR("some log is NULL"); return; } if (x < 1) { ERR("doing %p, x < 1 blah\n", p); return; } if (y < 1) { ERR("doing %p, y < 1 blah\n", p); return; } // actual code here z = x + y; ... } literally the above has a TONNE of cache misses and it HURTS... i'll repeat... EOID LOOKUP was 2 TIIMES FASTER. in fact it wen fro ~5-7% CPU down to STEADY 2.5% CPU. all to do with l1 *INSTRUCTION* cache hits vs misses... i'm doing an informal call here - all code like the above should change to something like: void func(void *p, int x, int y) { int z; if (!p) goto err_badp; if (x < 1) goto err_badx; if (y < 1) goto err_bady; // actual code here z = x + y; ... return; // "rare case" error handling here err_badp: ERR("some log is NULL"); return; err_badx: ERR("doing %p, x < 1 blah\n", p); return; err_bady: ERR("doing %p, y < 1 blah\n", p); return; } yes. you could merge goto's with if ((!p) || (x < 1) || (y < 1)) etc. BUT move the error handling code out of the way of the linear read-ahead by the l1 cache. remember it's reading a cacheline at a time so pre-fetching future instructions. the compiler IS putting the code inside the if {} right there in the assembly where it is in c. it doesn't re-order it. yes. i stumbled upon what is possibly a major compiler optimization opportunity. buty until such a magical day comes... we need to re-do our code so we move "rarely used code paths" out of the "linear codepath" where the cpu is fetching another cacheline then the next etc. but then skipping what it fetched only to get a cache miss and thus has to stop and wait. it was utterly amazing just how much this helps on hot code paths and frankly it doesn't make the code really any worse. it's nicer to read as the error handling is out of the way of scanning the code ahead (or rarely executed code is). (ok ok we could re-order code too to have success case inside if {}'s but that would be far harder in many cases to do than a goto). GOTO IS AWESOME. 'nuff said. it's a really MEASURABLE difference in speed. consistent. more than a double speedup. between 2 to 3 TIMES faster for UNCACHED code (and that is most of our code except inside inner loops, though even with inner loops it would help moving rare cases out of the inner loop code so we can fit more code in l1 cache). seriously consider this. these if's are NOT FREE. yes - this one is just a "return" so it'd be the same as a goto ... but if you just added a printf or an eina log etc. it'd blow out in cost FAST. in fact a lot of these static inline funcs in eina are polluting l1 cache badly by littering our code with the error handling code. we need to revise this. it's costly. it's not free. > > On Wed, Sep 14, 2016 at 8:52 PM, Cedric BAIL wrote: > >> cedric pushed a commit to branch master. > >> > >> http://git.enlightenment.org/core/efl.git/commit/?id=4d69f472fe31a9006436a05282a8376c7a712d41 > >> > >> commit 4d69f472fe31a9006436a05282a8376c7a712d41 > >> Author: Cedric Bail > >> Date: Wed Sep 14 16:50:05 2016 -0700 > >> > >> eina: allow graceful failure when calling eina_thread_cancel with NULL. > >> --- > >> src/lib/eina/eina_thread.c | 1 + > >> 1 file changed, 1 insertion(+) > >> > >> diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c > >> index d40073a..5002a42 100644 > >> --- a/src/lib/eina/eina_thread.c > >> +++ b/src/lib/eina/eina_thread.c > >> @@ -230,6 +230,7 @@ eina_thread_name_set(Eina_Thread t, const char *name) > >> EAPI Eina_Bool > >> eina_thread_cancel(Eina_Thread t) > >>
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
On Thu, Sep 15, 2016 at 4:00 AM, Gustavo Sverzut Barbieriwrote: > isn't it better to check in ecore_thread_cancel() if the thread was > already created? I was wondering also, but settled for this as it will protect any caller and the code is costly anyway, so no performance impact. > On Wed, Sep 14, 2016 at 8:52 PM, Cedric BAIL wrote: >> cedric pushed a commit to branch master. >> >> http://git.enlightenment.org/core/efl.git/commit/?id=4d69f472fe31a9006436a05282a8376c7a712d41 >> >> commit 4d69f472fe31a9006436a05282a8376c7a712d41 >> Author: Cedric Bail >> Date: Wed Sep 14 16:50:05 2016 -0700 >> >> eina: allow graceful failure when calling eina_thread_cancel with NULL. >> --- >> src/lib/eina/eina_thread.c | 1 + >> 1 file changed, 1 insertion(+) >> >> diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c >> index d40073a..5002a42 100644 >> --- a/src/lib/eina/eina_thread.c >> +++ b/src/lib/eina/eina_thread.c >> @@ -230,6 +230,7 @@ eina_thread_name_set(Eina_Thread t, const char *name) >> EAPI Eina_Bool >> eina_thread_cancel(Eina_Thread t) >> { >> + if (!t) return EINA_FALSE; >> return pthread_cancel((pthread_t)t) == 0; >> } >> >> >> -- >> >> > > > > -- > Gustavo Sverzut Barbieri > -- > Mobile: +55 (16) 99354-9890 > > -- > ___ > enlightenment-devel mailing list > enlightenment-devel@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel -- Cedric BAIL -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
Re: [E-devel] [EGIT] [core/efl] master 01/02: eina: allow graceful failure when calling eina_thread_cancel with NULL.
isn't it better to check in ecore_thread_cancel() if the thread was already created? On Wed, Sep 14, 2016 at 8:52 PM, Cedric BAILwrote: > cedric pushed a commit to branch master. > > http://git.enlightenment.org/core/efl.git/commit/?id=4d69f472fe31a9006436a05282a8376c7a712d41 > > commit 4d69f472fe31a9006436a05282a8376c7a712d41 > Author: Cedric Bail > Date: Wed Sep 14 16:50:05 2016 -0700 > > eina: allow graceful failure when calling eina_thread_cancel with NULL. > --- > src/lib/eina/eina_thread.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c > index d40073a..5002a42 100644 > --- a/src/lib/eina/eina_thread.c > +++ b/src/lib/eina/eina_thread.c > @@ -230,6 +230,7 @@ eina_thread_name_set(Eina_Thread t, const char *name) > EAPI Eina_Bool > eina_thread_cancel(Eina_Thread t) > { > + if (!t) return EINA_FALSE; > return pthread_cancel((pthread_t)t) == 0; > } > > > -- > > -- Gustavo Sverzut Barbieri -- Mobile: +55 (16) 99354-9890 -- ___ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel