C11 Re: [PATCH 3/6] termios: Use C11 mutex for input/output

Chris Johns chrisj at rtems.org
Thu Dec 15 22:34:14 UTC 2016


On 15/12/2016 18:02, Sebastian Huber wrote:
> On 14/12/16 22:15, Chris Johns wrote:
>> On 15/12/2016 00:39, Sebastian Huber wrote:
>>> Use C11 mutexes instead of Classic semaphores as a performance
>>> optimization and to simplify the application configuration.
>>
>> The use of C11 mutexes has not been agreed too and we need to discuss
>> this in more detail before we allow use within RTEMS. I would like to
>> see positive agreement from all core maintainers before this and
>> similar patches can be merged.
>
> A patch is a good thing to start such a discussion.
>

Great.

>>
>> RTEMS has required the use of the Classic API because:
>>
>>  1. Available on all architectures, BSPs and tool sets.
>>  2. Always present in a build.
>>  3. Was considered faster than POSIX.
>
> 3. is not the case. From an API point of view the POSIX operations could
> be faster than the Classic API since the parameter evaluation is simpler.
>

Yes, things have moved on and those crusty old developers like me have a 
soft spot for the classic API and I suspect these days it is little 
distorted view. :)

>>
>> The Classic API provides a base level of required functionality
>> because it is always available in supported tool sets and leads to the
>> smallest footprint because we do not need to link in more than one API.
>
> Compared to self-contained objects (like the C11 mutexes for example)
> the overhead of the Classic objects is huge in terms of run-time, memory
> footprint, code size (object administration) and complexity (object
> administration, use of a heap, unlimited objects, configuration).

I agree. The self contained is very attractive and a really big feature.

>
>>
>> I understand things change and move on so it is great to see this
>> change being proposed and our existing base line being challenged.
>>
>> I see from your performance figures C11 mutexes are better and the
>> resources are allocated as needed and used which is a better model
>> than the Classic API's configuration table. This is nice.
>>
>> Do all architectures and BSPs have working C11 support?
>
> Yes, all architectures and BSPs support the C11 <threads.h> mutexes,
> condition variables, thread-specific storage (mapped to POSIX keys),
> once support (mapped to POSIX once) in all configurations. The C11
> threads are mapped to POSIX threads (for simplicity, not a hard
> requirement).

Thank you and well done for all your efforts in this area. This is a 
really excellent place to be.

>
>>
>> Is there tests in the RTEMS testsuite for C11 threading services?
>
> https://git.rtems.org/rtems/tree/testsuites/sptests/spstdthreads01/init.c
>

Nice.

>>
>> What target resources are used to support this API, ie code and RAM
>> usage?
>
> On a 32-bit target:
>
> (gdb) p sizeof(Semaphore_Control)
> $1 = 72
> (gdb) p sizeof(mtx_t)
> $2 = 20
>
> With Thumb-2 instruction set:
>
> size ./arm-rtems4.12/c/atsamv/cpukit/score/src/libscore_a-mutex.o
> ./arm-rtems4.12/c/atsamv/cpukit/score/src/libscore_a-condition.o
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-*.o
>     text    data     bss     dec     hex filename
>      704       0       0     704     2c0
> ./arm-rtems4.12/c/atsamv/cpukit/score/src/libscore_a-mutex.o
>      536       0       0     536     218
> ./arm-rtems4.12/c/atsamv/cpukit/score/src/libscore_a-condition.o
>        4       0       0       4       4
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-call_once.o
>      100       0       0     100      64
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-cnd.o
>      104       0       0     104      68
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-mtx.o
>      156       0       0     156      9c
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-thrd.o
>       40       0       0      40      28
> ./arm-rtems4.12/c/atsamv/cpukit/libstdthreads/libstdthreads_a-tss.o
>
> size ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-sem*
>     text    data     bss     dec     hex filename
>      496       0       0     496     1f0
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semcreate.o
>      152       0       0     152      98
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semdelete.o
>       68       0       0      68      44
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semflush.o
>       28       0       0      28      1c
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semident.o
>       48       0       0      48      30
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-sem.o
>      428       0       0     428     1ac
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semobtain.o
>      464       0       0     464     1d0
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semrelease.o
>      312       0       0     312     138
> ./arm-rtems4.12/c/atsamv/cpukit/rtems/src/librtems_a-semsetpriority.o
>

Nice.

> The libscore_a-mutex.o contains more than one function. For example we
> have (Cortex-M7 target):
>
> 7000c5f0 <_Mutex_recursive_Acquire>:
> 7000c5f0:       2380            movs    r3, #128        ; 0x80
> 7000c5f2:       f3ef 8111       mrs     r1, BASEPRI
> 7000c5f6:       f383 8812       msr     BASEPRI_MAX, r3
> 7000c5fa:       4a12            ldr     r2, [pc, #72]   ; (7000c644
> <_Mutex_recursive_Acquire+0x54>)
> 7000c5fc:       68c3            ldr     r3, [r0, #12]
> 7000c5fe:       6912            ldr     r2, [r2, #16]
> 7000c600:       b91b            cbnz    r3, 7000c60a
> <_Mutex_recursive_Acquire+0x1a>
> 7000c602:       60c2            str     r2, [r0, #12]
> 7000c604:       f381 8811       msr     BASEPRI, r1
> 7000c608:       4770            bx      lr
>
> Only the above 10 instructions need to be executed in case the mutex is
> available. Below is the part that is executed in case the thread needs
> to block.
>
> 7000c60a:       4293            cmp     r3, r2
> 7000c60c:       d014            beq.n   7000c638
> <_Mutex_recursive_Acquire+0x48>
> 7000c60e:       3008            adds    r0, #8
> 7000c610:       b5f0            push    {r4, r5, r6, r7, lr}
> 7000c612:       b08d            sub     sp, #52 ; 0x34
> 7000c614:       2700            movs    r7, #0
> 7000c616:       f04f 7600       mov.w   r6, #33554432   ; 0x2000000
> 7000c61a:       4d0b            ldr     r5, [pc, #44]   ; (7000c648
> <_Mutex_recursive_Acquire+0x58>)
> 7000c61c:       ab0c            add     r3, sp, #48     ; 0x30
> 7000c61e:       4c0b            ldr     r4, [pc, #44]   ; (7000c64c
> <_Mutex_recursive_Acquire+0x5c>)
> 7000c620:       f88d 700c       strb.w  r7, [sp, #12]
> 7000c624:       f843 1d30       str.w   r1, [r3, #-48]!
> 7000c628:       4909            ldr     r1, [pc, #36]   ; (7000c650
> <_Mutex_recursive_Acquire+0x60>)
> 7000c62a:       9601            str     r6, [sp, #4]
> 7000c62c:       9502            str     r5, [sp, #8]
> 7000c62e:       940a            str     r4, [sp, #40]   ; 0x28
> 7000c630:       f7fd fb8e       bl      70009d50 <_Thread_queue_Enqueue>
> 7000c634:       b00d            add     sp, #52 ; 0x34
> 7000c636:       bdf0            pop     {r4, r5, r6, r7, pc}
> 7000c638:       6903            ldr     r3, [r0, #16]
> 7000c63a:       3301            adds    r3, #1
> 7000c63c:       6103            str     r3, [r0, #16]
> 7000c63e:       f381 8811       msr     BASEPRI, r1
> 7000c642:       4770            bx      lr
> 7000c644:       70016980        .word   0x70016980
> 7000c648:       70009d3d        .word   0x70009d3d
> 7000c64c:       70009d49        .word   0x70009d49
> 7000c650:       70013c24        .word   0x70013c24
>

Nice.

>>
>> Would the "tiny" footprint be smaller if all internal services
>> including compiler thread support are made C11? Could this actually be
>> done? Parts of POSIX has been creeping in over time so the position is
>> a little confused at the moment. I am not sure about a bits and pieces
>> approach, maybe a full switch is made.
>
> Yes, the footprint would be smaller. If we provide self-contained
> threads, then the footprint would be much smaller, e.g. no object
> administration, no heap.

Great. This is a powerful reason to look at moving in this direction and 
removing the remaining POSIX usage in libstdthreads.

A brief audit of rtems.git shows the change is possible with less than 
30 Classic task creates and a similar number of semaphore creates so a 
full change look reachable which is nice.

Should we look at moving all internal services to C11 and standardise 
it? I think there is value in doing this. It can be a post 4.12 branch 
activity.

>
>>
>> Does C11 work on LLVM (I hear support is close)?
>>
>> Where is the C11 API implemented? Is the threading code outside the
>> RTEMS source tree and what effect does that have on those looking to
>> certify RTEMS?
>
>
> The C11 support is not a compiler issue. The <threads.h> is a part of
> the C standard library and for RTEMS this header file is provided by
> Newlib:
>
> https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;a=blob;f=newlib/libc/include/threads.h;h=9fb08b03d1eb20024c0d680a7924336ec7ea57bb;hb=HEAD
>
>
> This header file is compatible to C89 (with the next Newlib release,
> currently C99 due to use of inline in <sys/lock.h>). I imported several
> parts of the FreeBSD <sys/cdefs.h> for this purpose.
>
> The C11 <threads.h> provided functions are implemented in RTEMS:
>
> https://git.rtems.org/rtems/tree/cpukit/libstdthreads
>

Thanks.

>>
>> Does a change like this require a coding standard update?
>
> Currently
>
> https://devel.rtems.org/wiki/Developer/Coding/Conventions
>
> gives no advice to use specific API X or Y.
>

Yes, I knew the answer to this one. :)

Thank you for the detailed and excellent review and analysis of the C11 
support. I have no problem with the change and C11 being used internally.

Chris


More information about the devel mailing list