Question on __retarget_lock function
sam.edge.newlib@gmx.com
sam.edge.newlib@gmx.com
Sat Dec 7 11:03:56 GMT 2024
On 07/12/2024 08:58, Kedar Karandikar wrote:
> Hi
> I am trying to override the __retarget_lock* dummy functions that are
> provided by NewLib lock.c in my baremetal environment.
>
> I was trying not to touch the newlib source code, but rather implement
> those functions in my framework.
>
> However, the functions defined in lock.c do not have a “weak” attribute
> next to the functions and this causes linker error when I try to define
> them in my framework.
>
> Any reason why they are not defined as weak? Is the expectation that I
> update the functions directly in newlib lock.c and compile the newlib
> after that?
>
> Thanks for the help!
>
> -Kedar K Karandikar
I had the same problem with the version of Newlib provided with the GCC
toolchain with STM's STM32CubeIDE. (And the OpenSTM32 Workbench one as
well.)
The problem is that 'struct _lock' and _LOCK_T (struct _lock *) are
supposed to be defined by the target platform implementer. Because of
this, the functions cannot be defined as weak so as to be overridable by
the end user.
Newlib's lock.c is simply an example dummy implementation but STM in
their stupidity chose to simply compile in this code which defines
struct _lock as being a single byte structure.
That makes reimplementing for, say, FreeRTOS tricky. What I did was use
GCC's symbol wrapper to reimplement all the __retarget_lock_xxxx()
functions and overlay them in the linker. (See the GCC LD --wrap option.)
The functions can simply cast the _LOCK_T arguments to pointers to the
real mutex objects (e.g. cast to SemaphoreHandle_t which is itself a
pointer to an opaque mutex object) and do similar for the _LOCK_T
pointer output parameters in the init functions after obtaining a mutex
pointer from the threading library.
However all the wrapper functions check their _LOCK_T arguments against
a static lookup table mapping from pointers to the predefined library
lock objects (e.g. &__lock___sinit_recursive_mutex) to actual mutex
objects/object pointers values.
Before starting the main() and switching into multithreaded mode, I call
an internal function that creates/initialized recursive or non-recursive
mutexes as appropriate for all the NULL SemaphoreHandle_t values in the
lookup table.
It's messy but it works.
Unfortunately, that's just the start of your problem if your vendor has
compiled in the dummy lock.c. If they've compiled GCC single-threaded,
the C++ STL, C & C++ atomics either aren't implemented or aren't thread
safe either which has knock-on effects for everything else in the C++
libraries when using a pre-emptive threading library
A better approach to take if you have the time is to bite the bullet and
create your own GCC & newlib toolchain, provide the required stubs for
all newlib's locking and for POSIX threads using your threading library
and compile GCC as POSIX-thread aware. That way all the C/C++ atomics
and Newlib APIs are fully reentrant. But it's a much bigger job of course.
--
Sam Edge
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_0xE6200DE0C92CEC06_and_old_rev.asc
Type: application/pgp-keys
Size: 1140 bytes
Desc: OpenPGP public key
URL: <https://sourceware.org/pipermail/newlib/attachments/20241207/a9213cc1/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 236 bytes
Desc: OpenPGP digital signature
URL: <https://sourceware.org/pipermail/newlib/attachments/20241207/a9213cc1/attachment.sig>
More information about the Newlib
mailing list