[PATCH v7 09/23] aarch64: Try to free the GCS of makecontext
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu Jan 9 18:53:14 GMT 2025
On 09/01/25 11:39, Yury Khrustalev wrote:
> On Tue, Jan 07, 2025 at 01:36:39PM -0300, Adhemerval Zanella Netto wrote:
>>
>>
>>> +/* From libc.so, arch specific. */
>>> +extern void ARCH_THREAD_FREERES (void) attribute_hidden;
>>>
>>
>> This seems strange if ARCH_THREAD_FREERES is not defined, although I am
>> not sure if this is a problem.
>
> I've been waiting for feedback from Carlos on this change. There is probably
> a better way to do this without #ifdef but it's not obvious to me.
>
>>> +/* Define empty function if no arch-specific clean-up
>>> + function has been defined. */
>>> +#ifndef ARCH_THREAD_FREERES
>>> +void __always_inline
>>> +__libc_arch_thread_freeres (void) {}
>>> +#define ARCH_THREAD_FREERES __libc_arch_thread_freeres
>>> +#endif
>>> +
>>
>> Do we need the __always_inline to force compiler to optimize it away?
>
> Yes
>
>>> @@ -58,6 +101,9 @@ alloc_makecontext_gcs (size_t stack_size)
>>> if (base == (void *) -1)
>>> /* ENOSYS, bad size or OOM. */
>>> abort ();
>>> +
>>> + record_gcs (base, size);
>>> +
>>
>> I think this will make makecontext non async-signal-safe when GCS is used,
>> when we explict document it as AS-Safe and AC-Safe. I think using
>> internal_signal_block_all/internal_signal_restore_set would be suffice,
>> but it is also a performance regression.
>
> Do you refer to the call to malloc() in record_gcs()?
>
> We need to keep track of shadow stacks allocated via map_shadow_stack()
> when a new context is created with makecontext() so that we can munmap
> it when it is no longer required.
>
> I think this is not on a performance critical path, so we can add the
> internal_signal_block_all / internal_signal_restore_set pair. Could you
> recommend where it would be best to use it?
Yes, glibc malloc is not async-signal-safe and thus calling on makecontext
make it async-signal-unsafe (similar for setcontext, which ends up calling
free).
I am not sure if you can really use malloc here, since a makecontext call
potentially interrupt malloc itself. We had the same issue on the getrandom
vDSO call; where we ended up using mmap directly instead.
You will still need to block/unblock signal to avoid reentrant signal
handlers; and there is the consideration of extra the mmap overhead per thread.
Another possibility, which I think would be simpler, is to add a TCB buffer
of N entries and use instead of a linked-list. It would add an small
memory overhead on each thread, and it would limit the number of in-flight
makecontext a thread can make; but at least makecontext can to return
ENOMEM if it can not create a new context, and it way simpler than adding
the mmap-allocator.
More information about the Libc-alpha
mailing list