Commit Graph

29614 Commits

Author SHA1 Message Date
Jordan Petridis
9c65e9ba2d gio: tests: Use slightly more explicit assert functions
Found by using teyit [1] on the code

https://github.com/isidentical/teyit
2024-02-02 16:15:35 +02:00
Philip Withnall
b65657f068 Merge branch 'th/optimize-weak-ref-list' into 'main'
[th/optimize-weak-ref-list] rework GObject's `WeakRefData` to track references in an array instead of GSList

See merge request GNOME/glib!3869
2024-02-02 14:01:10 +00:00
Thomas Haller
d8e4f39aa8 gobject: track GWeakRef in object's WeakRefData with an array
GSList doesn't seem the best choice here. It's benefits are that it's
relatively convenient to use (albeit not very efficient) and that an
empty list requires only the pointer to the list's head.

But for non-empty list, we need to allocate GSList elements. We can do
better, by writing more code.

I think it's worth optimizing GObject, at the expense of a bit(?) more
complicated code. The complicated code is still entirely self-contained,
so unless you review WeakRefData usage, it doesn't need to bother you.
Note that this can be easily measure to be a bit faster. But I think the
more important part is to safe some allocations. Often objects are
long-lived, and the GWeakRef will be tracked for a long time. It is
interesting, to optimize the memory usage of that.

- if the list only contains one weak reference, it's interned/embedded in
  WeakRefData.list.one. Otherwise, an array is allocated and tracked
  at WeakRefData.list.many.

- when the buffer grows, we double the size. When the buffer shrinks,
  we reallocate to 50% when 75% are empty. When the buffer shrinks to
  length 1, we free it (so that "list.one" is always used with a length
  of 1).
  That means, at worst case we waste 75% of the allocated buffer,
  which is a choice in the hope that future weak references will be
  registered, and that this is a suitable strategy.

- on architectures like x86_68, does this not increase the size of
  WeakRefData.

Also, the number of weak-refs is now limited to 65535, and now an
assertion fails when you try to register more than that. But note that
the internal tracking just uses a linear search, so you really don't
want to register thousands of weak references on an object. If you do
that, the current implementation is not suitable anyway and you must
rethink your approach. Nor does it make sense to optimize the
implementation for such a use case. Instead, the implementation is
optimized for a few (one!) weak reference per object.
2024-02-02 14:49:09 +01:00
Thomas Haller
637c2a08ce gobject: combine ref_count/lock_field in WeakRefData
We can safely combine this, and use bit 30 of the ref-count for locking.

This leaves still 2^30-1 for the ref-count, which is more than enough,
because these references are only taken for a short time in
g_weak_ref_get() and g_weak_ref_set(). Note that one thread can at most
take one reference at a time, so the ref-count will always a smaller
number.

Also note, that obviously we will only take a bit lock while also
holding a reference. That means, when weak_ref_data_unref() decreases
the ref-count to zero, the bit will be unlocked as well.

The reason to do this is to free up some space in WeakRefData. Note that
(on x86_64) this doesn't actually make the struct smaller.  It's
probably not reasonably possible to make WeakRefData smaller than it
already is (on x86_64). However, by combining the fields we have some
space for reuse without increasing the struct size. That space will be
used next.
2024-02-02 14:49:09 +01:00
Thomas Haller
824c4da44b gobject/tests: add test that creates a large number of weak references
The implementation of GWeakRef tracks weak references in a way, that
requires linear search. That is probably best, for an expected low
number of entries (e.g. compared to the overhead of having a hash
table). However, it means, if you create thousands of weak references,
performance start to degrade.

Add a test that creates 64k weak references. Just to see how it goes.
2024-02-02 14:49:09 +01:00
Philip Withnall
1c6db4c8b4 Merge branch 'alatiera/docs-fix' into 'main'
docs: Fix include path for the build

See merge request GNOME/glib!3871
2024-02-02 11:52:51 +00:00
Jordan Petridis
e0b7ab81cf docs: Fix include path for the build
f75221c7ea moved the introspection
folder around, but we also need to adjust the relative path so
the documentation will keep building
2024-02-02 12:54:07 +02:00
Philip Withnall
53ded42fbb Merge branch 'revert-untested-codegen-changes' into 'main'
Revert "Don't skip dbus-codegen tests on Win32"

See merge request GNOME/glib!3870
2024-02-02 10:22:02 +00:00
Philip Withnall
5744f55c11 Revert "Don't skip dbus-codegen tests on Win32"
This reverts commit fbdc9a2d03.

It was not submitted through a merge request and broke CI. Reverting it
immediately to unbreak CI and hence the rest of the development
pipeline. The changes can be re-submitted as a merge request so they’re
properly tested in CI before being merged.

See https://gitlab.gnome.org/GNOME/glib/-/merge_requests/3857#note_1994336
2024-02-02 10:01:24 +00:00
John Ralls
fbdc9a2d03 Don't skip dbus-codegen tests on Win32
And coincidentally on Darwin either.
2024-02-01 15:17:26 -08:00
Philip Withnall
8afefe963d Merge branch '3238-hurd-configure-warnings' into 'main'
ci: Temporarily disable --fatal-meson-warnings on Hurd CI

Closes #3238

See merge request GNOME/glib!3863
2024-02-01 10:53:37 +00:00
Philip Withnall
c6ae56a9d6 Merge branch '3217-gir-stack' into 'main'
girepository: Expose GITypeInfo and GIArgInfo as stack allocatable

Closes #3217

See merge request GNOME/glib!3867
2024-02-01 10:52:13 +00:00
Philip Withnall
bcfb896fed Merge branch 'mcatanzaro/main-context-tutorial' into 'main'
Link to the main context tutorial from the main loop docs

See merge request GNOME/glib!3868
2024-02-01 10:51:30 +00:00
Michael Catanzaro
8f34e90bc3 Link to the main context tutorial from the main loop docs
This might help increase visibility of Philip's useful GMainContext
tutorial. Although the GMainContext documentation is fairly good, it's
also pretty intimidating. The tutorial is very useful and provides
guidance that we can't fit directly into the documentation, so reference
it.
2024-01-31 11:56:56 -06:00
Philip Withnall
2638f97b3e Merge branch 'th/weak-ref-lock-2' into 'main'
[th/weak-ref-lock-2] gobject: use per-object bit-lock instead of global RWLock for GWeakRef

Closes #743

See merge request GNOME/glib!3834
2024-01-31 16:51:50 +00:00
Thomas Haller
7382cc4383 gobject: use per-object bit-lock instead of global RWLock for GWeakRef
Replace the global RWLock with per-object locking. Note that there are
three places where we needed to take the globlal lock. g_weak_ref_get(),
g_weak_ref_set() and in _object_unref_clear_weak_locations(), during
g_object_unref(). The calls during g_object_unref() seem the most
relevant here, where we would want to avoid a global lock. Luckily, that
global lock only had to be taken if the object ever had a GWeakRef
registered, so most objects wouldn't care. The global lock only affects
objects, that are ever set via g_weak_ref_set(). Still, try to avoid that
global lock.

Related to GWeakRef, there are various moments when we don't hold a
strong reference to the object. So the per-object lock cannot be on the
object itself, because when we want to unlock we no longer have access
to the object. And we cannot take a strong reference on the GObject
either, because that triggers toggle notifications. And worse, when one
thread holds the last strong reference of an object and decides to
destroy it, then a `g_weak_ref_set(weak_ref, NULL)` on another thread
could acquire a temporary reference, and steal the destruction of the
object from the other thread.

Instead, we already had a "quark_weak_locations" GData and an allocated
structure for tracking the GSList with GWeakRef. Extend that to be
ref-counted and have a separate lifetime from the object. This
WeakRefData now contains the per-object mutex for locking. We can
request the WeakRefData from an object, take a reference to keep it
alive, and use it to hold the lock without having the object alive.

We also need a bitlock on GWeakRef itself. So to set or get a
GWeakRef we must take the per-object lock on the WeakRefData and the
lock on the GWeakRef (in this order). During g_weak_ref_set() there may
be of course two objects (and two WeakRefData) involved, the previous
and the new object.

Note that now once an object gets a WeakRefData allocated, it can no
longer be freed. It must stick until the object gets destroyed. This
allocation happens, once an object is set via g_weak_ref_set(). In
other words, objects involved with GWeakRef will have extra data
allocated.

It may be possible to also release the WeakRefData once it's no longer
needed. However, that would be quite complicated, and require additional
atomic operations, so it's not clear to be worth it. So it's not done.
Instead, the WeakRefData sticks on the object once it's set.
2024-01-31 17:30:28 +01:00
Thomas Haller
092be080c5 gobject: avoid global GRWLock for weak locations in g_object_unref() in some cases
_object_unref_clear_weak_locations() is called twice during
g_object_unref(). In both cases, it is when we expect that the reference
count is 1 and we are either about to call dispose() or finalize().

At this point, we must check for GWeakRef to avoid a race that the ref
count gets increased just at that point.

However, we can do something better than to always take the global lock.

On the object, whenever an object is set to a GWeakRef, set a flag
OPTIONAL_FLAG_EVER_HAD_WEAK_REF. Most objects are not involved with weak
references and won't have this flag set.

If we reach _object_unref_clear_weak_locations() we just (atomically)
checked that the ref count is one. If the object at this point never had
a GWeakRef registered, we know that nobody else could have raced against
obtaining another reference. In this case, we can skip taking the lock
and checking for weak locations.

As most object don't ever have a GWeakRef registered, this significantly
avoids unnecessary work during _object_unref_clear_weak_locations().

This even fixes a hard to hit race in the do_unref=FALSE case.
Previously, if do_unref=FALSE there were code paths where we avoided
taking the global lock. We do so, when quark_weak_locations is unset.
However, that is not race free. If we enter
_object_unref_clear_weak_locations() with a ref-count of 1 and one
GWeakRef registered, another thread can take a strong reference and
unset the GWeakRef. Then quark_weak_locations will be unset, and
_object_unref_clear_weak_locations() misses the fact that the ref count
is now bumped to two. That is now fixed, because once
OPTIONAL_FLAG_EVER_HAD_WEAK_REF is set, it will stick.

Previously, there was an optimization to first take a read lock to check
whether there are weak locations to clear. It's not clear that this is
worth it, because we now already have a hint that there might be a weak
location. Unfortunately, GRWLock does not support an upgradable lock, so
we cannot take an (upgradable) read lock, and when necessary upgrade
that to a write lock.
2024-01-31 17:30:28 +01:00
Thomas Haller
0c06a4b7a0 glib: add internal g_datalist_id_update_atomic() function
GDataSet is mainly used by GObject. Usually, when we access the private
data there, we already hold another lock around the GObject.

For example, before accessing quark_toggle_refs, we take a
OPTIONAL_BIT_LOCK_TOGGLE_REFS lock. That makes sense, because we anyway
need to protect access to the ToggleRefStack. By holding such an
external mutex around several GData operations, we achieve atomic
updates.

However, there is a (performance) use case to update the qdata
atomically, without such additional lock. The GData already holds a lock
while updating the data. Add a new g_datalist_id_update_atomic()
function, that can invoke a callback while holding that lock.

This will be used by GObject. The benefit is that we can access the
GData atomically, without requiring another mutex around it.

For example, a common pattern is to request some GData entry, and if
it's not yet allocated, to allocate it. This requires to take the GData
bitlock twice. With this API, the callback can allocate the data if no
entry exists yet.
2024-01-31 17:30:28 +01:00
Philip Withnall
2a99d4b168 girepository: Expose GITypeInfo and GIArgInfo as stack allocatable
There are a handful of APIs in libgirepository which are used on
performance-sensitive code paths in language bindings (such as looking
at arguments when doing function calls). Historically libgirepository
has provided a stack-allocated variant for them, which avoids returning
a newly allocated `GIBaseInfo`. Since moving to glib.git and porting to
`GTypeInstance`, that stack allocated version has been broken.

This commit fixes it, by exposing obfuscated stack allocatable versions
of `GITypeInfo` and `GIArgInfo`, which are the two `GIBaseInfo`
subtypes which can be returned by the stack allocation functions.

The commit includes unit tests for them.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Fixes: #3217
2024-01-31 15:49:38 +00:00
Philip Withnall
5f12851312 Merge branch 'wip/oholy/libmnt_monitor' into 'main'
gunixmounts: Use libmnt_monitor API for monitoring

See merge request GNOME/glib!3845
2024-01-31 14:30:09 +00:00
Philip Withnall
7b5bcf62b8 Merge branch 'th/gobject-carray-comment' into 'main'
[th/gobject-carray-comment] gobject: remove obsolete code comment about CArray

See merge request GNOME/glib!3866
2024-01-31 14:09:04 +00:00
Ondrej Holy
c7254fb3ad gunixmounts: Use mnt_monitor_veil_kernel option
The previous commit enabled the `/run/mount/utab` monitoring. The problem
is that the `mount-changed` signal can be emitted twice for one mount. One
for the `/proc/mounts` file change and another one for the `/run/media/utab`
file change. This is still not ideal because e.g. the `GMount` objects for
mounts with the `x-gvfs-hide` option are added and immediately removed.
Let's enable the `mnt_monitor_veil_kernel` option to avoid this.

Related: https://github.com/util-linux/util-linux/pull/2725
2024-01-31 14:53:42 +01:00
Ondrej Holy
1abbbd761e gunixmounts: Use libmnt_monitor API for monitoring
The `GUnixMountMonitor` object implements monitoring on its own currently.
Only the `/proc/mounts` file changes are monitored. It is not aware of the
`/run/mount/utab` file changes. This file contains the userspace mount
options (e.g. `x-gvfs-notrash`, `x-gvfs-hide`) among others. There is a
problem when `/sbin/mount.<type>` (e.g. `mount.nfs`) helper programs are
used. In that case, the `/run/mount/utab` file is updated later than the
`/proc/mounts` file and thus the `GUnixMountMonitor` clients (e.g.
`gvfs-udisks2-volume-monitor`, `gvfsd-trash`) don't see the userspace
options until the next `mount-changed` signal. Let's use the `libmnt_monitor`
API for monitoring instead and emit the `mount-changed` signal also when the
`/run/mount/utab` file is changed.

Related: https://issues.redhat.com/browse/RHEL-14607
Related: https://github.com/util-linux/util-linux/pull/2607
2024-01-31 14:53:42 +01:00
Philip Withnall
5f855022a6 Merge branch 'th/test-weak-notify' into 'main'
[th/test-weak-notify] gobject/tests: add test checking that GWeakRef is cleared in GWeakNotify

See merge request GNOME/glib!3865
2024-01-31 12:35:52 +00:00
Thomas Haller
81107da210 gobject: remove obsolete code comment about CArray
It's not clear what this code comment tries to tell us. Yes, when we
make changes, we must take care that the changes are correct and update
the relevant places.

It seems long obsolete. Drop it.

This partly reverts commit d7dd9aefd8 ('placed a comment about not
changing CArray until we have').
2024-01-31 13:34:37 +01:00
Philip Withnall
47b2fd8168 Merge branch 'repository-mfile-leak' into 'main'
girepository: Fix a memory leak of a mapped file

See merge request GNOME/glib!3861
2024-01-31 12:31:36 +00:00
Thomas Haller
970325b92d gobject/tests: add test checking that GWeakRef is cleared in GWeakNotify
g_object_weak_ref() documentation refers to GWeakRef as thread-safe
replacement.  However, it's not clear to me, how GWeakRef is a
replacement for a callback. I think, it means, that you combine
g_object_weak_ref() with GWeakRef, to both hold a (thread-safe) weak
reference and get a notification on destruction.

Add a test, that GWeakRef is already cleared inside the GWeakNotify
callback.
2024-01-31 12:42:02 +01:00
Philip Withnall
180e4867c8 Merge branch 'ewlsh/gir-compiler' into 'main'
girepository: Update gir-compiler and use it to compile GIRs

See merge request GNOME/glib!3853
2024-01-31 11:37:35 +00:00
Evan Welsh
3bd7635516 girepository: Cleanup compiler.c formatting 2024-01-31 11:13:16 +00:00
Evan Welsh
5d997cad03 girepository: Update gi-compile-repository and use it to compile GIRs
Adapt gi-compile-repository sources to compile against the updated
libgirepository that is included with GLib.

This also renames "g-ir-compiler" to "gi-compile-repository" to avoid
overwriting the existing binary and to simplify the binary name going
forward.
2024-01-31 11:13:16 +00:00
Philip Withnall
b862fe077a Merge branch 'ewlsh/refactor-gir-generation' into 'main'
Refactor GIRepository GIR generation to avoid cyclical dependency

See merge request GNOME/glib!3797
2024-01-31 11:05:32 +00:00
Michael Catanzaro
936bb9ecfb Merge branch 'memory-monitor-portal-fix' into 'main'
tests: Fix typo in memory-monitor-portal.py.in

See merge request GNOME/glib!3860
2024-01-30 16:39:09 +00:00
Philip Withnall
3b7df5e25d Merge branch '3236-resolver-error-leak' into 'main'
gthreadedresolver: Fix leak on error path

Closes #3236

See merge request GNOME/glib!3862
2024-01-30 14:31:32 +00:00
Philip Withnall
ecc5275be9 ci: Temporarily disable --fatal-meson-warnings on Hurd CI
For the same reasons as in commit 71061fdcb3, but in this
case we can’t downgrade the version of Meson on the CI runner, so just
tell it to shut up instead.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Fixes: #3238
2024-01-30 14:30:42 +00:00
Philip Withnall
8da4fc17b9 gthreadedresolver: Fix leak on error path
Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Fixes: #3236
2024-01-30 09:53:00 +00:00
Philip Withnall
d5954664f2 girepository: Fix a memory leak of a mapped file
This was introduced by me in commit
1eec66c898, as the ownership transfer
semantics of `gi_typelib_new_from_mapped_file()` were not blatant.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3237
2024-01-30 07:45:11 +00:00
Philip Withnall
b2144afe28 tests: Fix typo in memory-monitor-portal.py.in
This was my mistake in commit 67a9fbf1fa.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3237
2024-01-30 07:38:13 +00:00
Evan Welsh
f75221c7ea girepository: Move GIR generation into girepository and prior to tests
To enable tests which depend on libgirepository's GIR and typelib,
we need to refactor the order we're currently building these items.

We can also move everything under girepository/ to cleanup the
top-level.
2024-01-30 00:50:40 -06:00
Philip Withnall
5f345a2653 Merge branch 'th/glib-private-const' into 'main'
[th/glib-private-const] glib: return const pointer from glib__private__()

See merge request GNOME/glib!3859
2024-01-29 15:39:39 +00:00
Thomas Haller
0adb1c24d7 glib: return const pointer from glib__private__()
also, make the global variable "static const". That may allow the linker
to place the variable into read-only memory, so we are a bit more confident
that it cannot be modified.
2024-01-29 16:05:29 +01:00
Philip Withnall
494f8d4d87 Merge branch 'gi-repository-no-singleton' into 'main'
girepository: Drop gi_repository_get_default()

See merge request GNOME/glib!3856
2024-01-26 13:04:40 +00:00
Philip Withnall
b24b54af5b girepository: Drop gi_repository_get_default()
We now only support creating `GIRepository` instances as normal
GObjects, not as a global singleton. This makes the semantics of the
class a bit more standard and, in particular, makes it easier to ensure
that everything is freed when we’re done with libgirepository. This is
particularly useful for unit testing, but should also be useful when
unloading modules from bindings.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3155
2024-01-26 12:08:17 +00:00
Philip Withnall
9ab84bc14a girwriter: Stop using the singleton GIRepository
It’s soon going to disappear.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3155
2024-01-26 12:08:17 +00:00
Philip Withnall
80f9153a7f girepository: Move search and library paths into GIRepository
Rather than them being set and stored globally, make them members of
`GIRepository`. This helps us move away from the concept of a global
singleton `GIRepository`.

This is slightly complicated by the fact that the library paths are
needed within the module loading code in `GITypelib`, but at that point
the `GITypelib` doesn’t have access to its parent `GIRepository` to call
`gi_repository_get_library_path()`, so we have to cache them in
`typelib->library_paths`.

It also means that it’s no longer possible to retrieve the ‘unset’ paths
from the globals, so the test for that is removed from
`repository-search-paths.c`.

This commit makes some API breaks, but that’s OK because libgirepository
has not been in a stable release yet.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3155
2024-01-26 12:08:17 +00:00
Philip Withnall
5ef1c7e110 girepository: Move library path functions over from gitypelib.c
This means they’re implemented in the same file as the typelib search
path, so it’s easier to refactor the code.

This adds `gi_repository_get_library_path()` to expose the library path,
both publicly and to internal users in `gitypelib.c`. And unit tests.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-01-26 12:01:01 +00:00
Philip Withnall
846abed197 girepository: Move a helper method
This introduces no functional changes, but simplifies an upcoming
commit.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-01-26 10:53:21 +00:00
Philip Withnall
b4063e1fa8 Merge branch 'typelib-bytes' into 'main'
gitypelib: Replace multiple constructors with gi_typelib_new_from_bytes()

See merge request GNOME/glib!3855
2024-01-26 10:15:49 +00:00
Philip Withnall
b613c3ef46 Merge branch 'girnode-cleanup' into 'main'
girnode: Document ownership and element types of internal structs

See merge request GNOME/glib!3854
2024-01-26 09:59:50 +00:00
Philip Withnall
1eec66c898 gitypelib: Replace multiple constructors with gi_typelib_new_from_bytes()
`GBytes` provides a way of handling const memory blobs, stolen memory
blobs, and mapped files. Rather than having `GITypelib` implement all of
those itself, just take a `GBytes` as input.

This is an API break, but libgirepository hasn’t been in a stable
release yet.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3155
2024-01-26 09:51:13 +00:00
Philip Withnall
0909b2e3ac girnode: Improve int types in GIIrNodeUnion
`GIIrNodeUnion` is built dynamically at runtime (rather than being
mmapped from disk), so its types can accurately reflect their runtime
semantics, rather than an on-disk format.

As part of this, switch from `atoi()` to `g_ascii_string_to_unsigned()`
for parsing the relevant fields from a GIR XML file. This means we now
get error handling for invalid integers.

Signed-off-by: Philip Withnall <pwithnall@gnome.org>

Helps: #3155

Signed-off-by: Philip Withnall <pwithnall@gnome.org>
2024-01-26 09:29:30 +00:00