Discussion:
What are the __retarget_lock functions?
Freddie Chopin
2018-08-24 22:25:44 UTC
Permalink
Do I need to implement them (how?)
Do you need to implement them - no, but using any of the functions
which needs them will be allowed only from single thread (maybe with
exception of malloc/free if you provide __malloc_lock/unlock()).

I think that implementations from my RTOS will answer your "how"
question:

https://github.com/DISTORTEC/distortos/blob/master/source/newlib/locking.cpp
Why are they needed and what do they do?
They are not needed (; They implement all the locking for newlib. The
most frequent use-case is stdio - each file has its own lock and
there's also a global lock for accessing the list of free FILE
structures (when using fopen() and similar). Without these locks using
anything from stdio is basically allowed from one thread only.

In typical usage of libc - where it is really a part of the operating
system - the locks are implemented "natively", because newlib has a
"port" for that OS (this is a case with Linux, RTEMS, quite likely with
Cygwin). But in bare-metal this approach is not practical - neither
newlib wants to have "ports" for hundreds of RTOSes, nor will anyone
maintain hundreds of newlib forks with such ports. And you would need a
special toolchain for each RTOS + target combination... That's why
there are these "retargetable" locks, which you can implement as
callbacks directly in your project.

Regards,
FCh
Freddie Chopin
2018-09-10 08:53:22 UTC
Permalink
1. Each lock takes about 80 bytes
This is easily solvable (; Just stop using FreeRTOS (;

OK, but seriously. This is a consequence of FreeRTOS design, where
"everything is a queue". Your mutex is in fact a queue with length
zero, so it has dozens of useless member variables, which finally add
up to ~80 bytes. In my opinion (which is of course biased and
subjective), this design decision is extremely stupid.

In other RTOSes (including distortos - the one I'm writing), the mutex
is usually ~20-24 bytes long, so it's ~3-4x smaller, while having a lot
more features (like selectable protocol or selectable type).
3. The way newlib/libc/misc/lock.c is implemented, it's either all-
The linker can garbage collect arc4random(), but not the
arc4random_mutex.
4. It would be better, if arc4random just created it's own lock on
first use.
I suppose that it would be better for the "retargetable locks", but
worse for the normal case, where there is a dedicated port... This may
be a good idea though.
5. Each task creates 3 additional locks with __retarget_lock_init for
stdin/out/err
The solution to this particular problem:

https://github.com/FreddieChopin/bleeding-edge-toolchain/commit/f0b85774eb0fc0ae361897511d96a214a10cceea
6. __retarget_lock_init() looks too complicated with the double
pvPortMalloc/xSemaphoreCreate
That's because the allocation step is useless. FreeRTOS handle is just
`void*`, you don't need to allocate that, just use `_LOCK_T*` directly.
FreeRTOS objects (with the standard API) are all dynamic anyway
(another very stupid decision).
I don't understand why the 3 file locks per thread are needed. There
seems to be
an awful lot of locking going on - every printf("\n") now takes a
lock.
How else do you want to use a shared resource from multiple threads?
Do I need them, if I only use them from the thread they belong to?
No, unless you open/close them with external locking. These operation
access global shared state (list of free FILE structures and
"initialized" flag of whole stdio). I'm pretty sure there may be more
accesses to global shared state, so I suppose that you cannot omit the
locks, unless you use EVERYTHING from one thread only.

Please also note that locking/unlocking is generally considered a very
quick operation (unless locking needs to block [; ). If they are slow
in FreeRTOS then... sorry [; The fact that something is very popular
doesn't really mean that it's better than alternatives (;

Regards,
FCh
Sebastian Huber
2018-09-10 10:17:14 UTC
Permalink
Post by Freddie Chopin
1. Each lock takes about 80 bytes
This is easily solvable (; Just stop using FreeRTOS (;
OK, but seriously. This is a consequence of FreeRTOS design, where
"everything is a queue". Your mutex is in fact a queue with length
zero, so it has dozens of useless member variables, which finally add
up to ~80 bytes. In my opinion (which is of course biased and
subjective), this design decision is extremely stupid.
In other RTOSes (including distortos - the one I'm writing), the mutex
is usually ~20-24 bytes long, so it's ~3-4x smaller, while having a lot
more features (like selectable protocol or selectable type).
The 80 bytes for a mutex object are quite a lot. Even on RTEMS, which
supports SMP systems and complex locking protocols, a recursive mutex
needs just 24 bytes (32-bit target):

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob_plain;f=newlib/libc/sys/rtems/include/sys/lock.h;hb=HEAD

On a uniprocessor RTOS two or three pointers and an integer should be
enough to implement a recursive mutex with support for priority inheritance.
--
Sebastian Huber, embedded brains GmbH

Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone : +49 89 189 47 41-16
Fax : +49 89 189 47 41-09
E-Mail : ***@embedded-brains.de
PGP : Public key available on request.

Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
Loading...