This changes a lot of things all across the EFL. Previously,
methods tagged @const had both their external prototype and
internal impl generated with const on object, while property
getters only had const on the external API. This is now changed
and it all has const everywhere.
Ref T6859.
Summary:
This commit add null check on __efl_auto_unref_set.
In EO_OBJ_POINTER, if obj_id is null, obj can also be null.
Test Plan: N/A
Reviewers: woohyun, kimcinoo, cedric
Subscribers: cedric
Differential Revision: https://phab.enlightenment.org/D5869
Reviewed-by: Cedric BAIL <cedric@osg.samsung.com>
Summary:
This will avoid infinite loops and errors when the parent tries
to orphan an invalidated child.
Fixes T6780
Test Plan: Run `make check`
Reviewers: cedric
Maniphest Tasks: T6780
Differential Revision: https://phab.enlightenment.org/D5839
Reviewed-by: Cedric BAIL <cedric@osg.samsung.com>
This is just a first step. All user of destructor should be updated to
move the code that rely on their efl_parent and on efl_provider_find to
invalidate. Then we will be able to change the way efl_add and efl_del
work to properly refcount things. efl_noref won't be triggered at the
moment until both efl_parent_set(obj, NULL) and the last user ref are
set to NULL. This is not what we want, but due to how user refcount is
accounting parent at the moment, until all the code is move to rely
on invalidate we can not fix this.
so the MAIN loop is actually an efl.app object. which inherits from
efl.loop. the idea is that other loops in threads will not be efl.app
objects. thread on the creator side return an efl.thread object.
inside the thread, like the mainloop, there is now an efl.appthread
object that is for all non-main-loop threads.
every thread (main loop or child) when it spawns a thread is the
parent. there are i/o pipes from parnet to child and back. so parents
are generally expected to, if they want to talk to child thread, so
use the efl.io interfaces on efl.thread, and the main loop's elf.app
class allows you to talk to stdio back to the parent process like the
efl.appthread does the same using the efl.io interfaces to talk to its
parent app or appthread. it's symmetrical
no tests here - sure. i have been holding off on tests until things
settle. that's why i haven't done them yet. those will come back in a
subsequent commit
for really quick examples on using this see:
https://phab.enlightenment.org/F2983118https://phab.enlightenment.org/F2983142
they are just my test code for this.
Please see this design document:
https://phab.enlightenment.org/w/efl-loops-threads/
The cache had a generation count, removing this check breaks eo suite.
EO is designed to tolerate init/shutdown cycles (as long as
dlopen/dlclose isn't involved).
Note: the ugly goto are useless as GCC -O2 understands EINA_(UN)LIKELY
and deals with it as expected (just look at the asm produced).
See 34d9f20706
This makes eo print a WRN message in case a function is called on NULL.
efl_del is an exception to this rule (implemented in a hackish way, I
admit). I don't know any language or object model where using a null
object doesn't result in an exception or crash, except EO. In any case,
calls to null are invalid.
The next commits will resolve most warnings for EFL.
Ref T6326
Summary:
ecore_evas: remove debug
eina: unregister log level when done with
Fixes a constant memory leak.
eina: introduce EINA_HOT and EINA_COLD
These attributes respectivelly expand to __attribute__ ((hot)) and
__attribute__ ((cold)) when available. They allow to mark functions are
being hot/cold (frequently used or not) as well as to qualify labels
within a function (likely/unlikely branches).
eo: speed-up generated calls by removing call cache
The call cache needed to by thread-local, to avoid concurrency issues.
Problem with TLS is that is adds an extra overhead, which appears to be
greater than the optimization the cache provides.
Op is naturally atomic, because it is an unsigned integer. As such, it
cannot be tempered with while another thread is reading it. When
entering the generated function, the first operation done is reading
'op'. If we have concurrency, we will have access sequences returning
either EFL_NOOP or a VALID op, because 'op' is not set until the very
end of the function, when everything has been computed. As such, we now
use the 'op' atomic integer to instore a lock-free/wait-free mechanism,
which allows to drop the TLS nature of the cache, speeding up the access
to the cache, and therefore making functions execute faster.
We don't test anymore the generation count. This can be put as a
limitation. If means that if you call efl_object_shutdown() and
re-initialize it later with different data, opcodes will be invalid.
I am not sure there is any usecase for this to ever happen.
We could move all the caches in a dedicated section, that can be
overwritten after a call to efl_object_shutdown(), but I am not sure it
will be very portable.
Benchmark: mean over 3 executions of
ELM_TEST_AUTOBOUNCE=100 time elementary_test -to genlist
```
BEFORE AFTER
------------------------------------------------------------
time (ns) 11114111647.0 9147676220.0
frames 2872.3333333333335 2904.6666666666665
time per frame (ns) 3869364.6666666665 3149535.3333333335
user time (s) 11.096666666666666 9.22
cpu (%) 22.666666666666668 18.333333333333332
```
Ref T6580
Reviewers: raster, cedric
Subscribers: cedric, jpeg
Maniphest Tasks: T6580
Differential Revision: https://phab.enlightenment.org/D5738
we can't sensibly use things like massif to track memory if we bypass
itr with mmaping -1 fd anonymous memory... so if built with valgrind
support and running under valgrind, use malloc/calloc and free so
these tools actually do something useful for these bits of memory.
Triggered after (almost) complete destruction of the object.
Not called "deleted" because the other event is already "del".
I don't like "destruct" much but this follows the terminology of
"constructor" / "destructor".
@feature
This reverts commit f910ba248e.
The scheduler is meant to be used only in C, not by bindings so there isn't really
a use for it in the loop class. Now this patch was triggered due to complexity in
using future/promise, so will do a follow up patch to improve that.
Efl.Future is an EO object which means even cancelling Efl.Future
objects requires EO. So this should be done before shutting down EO,
otherwise everything fails badly.
I believe Efl.Future is going to disappear soon, but the problem will
remain: if any promise/future uses EO or anything else outside of Eina
(so, basically anything) then it needs to be canceled before shutting
down the above layers. This is the same situation as with ecore events,
for which we've introduced ecore_event_type_flush.
Ping @cedric
in some cases construction can fail badly and this causes a crash...
eoid is NULL going in and this causes a cascade of failure. survive
and be more robust.
This API is meant to be used by parts only, and by bindings dealing with
part objects. This patch fixes make check which got broken in the after
the previous one (cxx).
luajit wants to check the upper 17 bits of pointers and assume they
are all 0 if on a 64bit architecture. it will panic and barf if they
are used. we have been using them in our eoid's for a long time.
my take on this is that this is unportable. assuming how many bits are
or are not valid in an opaque pointer (void *) that is simply passed
to you and you cannot dereference or use (no size information even for
what amount of data it points to etc.), is just wrong. it's not
portable and it's trying to be too smart and creating such issues. my
take is that luajit needs a fix for this in the longer term. but for
now let's have a 47 bit mode and go with that. it does mean i have to
drop our generation counter to 10 bits on 64bit (from 27 bits) which
increases likelihood of eoid re-use being falsely detected as valid
(before on 64bit it was 1 in 130 million or so chance, with this 47
bit change it's 1 in 1000. but to be fair on 32bit it's 7 bits for gen
count so 1 in 127 ... so still more than 10x "safer" than on 32bit...
but still...). the relevant check in luajit is:
(((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
it ONLY does this on 64bit. on 32bit pointers are not checked for
validity at all.
as an aside, armv8.2 seemingly will bring 52bit addresses so luajit is
going to fall over flat on a newer rev of armv8. it may be x86 also
uses more bits. last i knew it was 48bits so the 47 bit check luajit
does i think is even wrong for x86-64. to be detailed i read:
amd64 arch == 48 bits (so luajit is wrong). even better In addition,
the AMD specification requires that the most significant 16 bits of
any virtual address, bits 48 through 63, must be copies of bit 47 (in
a manner akin to sign extension). so if the upper bit of 48 is set
THEN all the 16 upper bits must be 1... breaking luajit, even if it
were 47bit and this rule applied. I read the architecture allows for
up to 52bits of actual addresses so architecture-wise this is even
wrong...
So I smell a core bug here in luajit. Certainly in the number of bits
it insists must be 0 (the upper 17 bits where on amd64/x86-64 it
should be the upper 16 bits... and even then these may NOT be 0 if bit
47 (the upper bit of the lower 48 is 1).... so the whole check is
invalid... :(
at least the above is at a theoretical level. i believe that the
addresses divide the 48 bits into 2 chunks (thus 47)... but at the
PHYSICAL level with no mmu and virtual memory. arm64 has this:
https://www.kernel.org/doc/Documentation/arm64/memory.txt
note in all cases the 2nd chunk of memory has at leats some upper bits
of physical addresses beign 1 ... which makes luajit invalid tyo use
without virtual memory remapping these away from high bits.
@fix
It would be pretty stupid to create an object that dies before it even
gets created. Auto-unref is for parts and should probably not be used
anywhere else :)