Changeset 3d5701e for libcfa


Ignore:
Timestamp:
Feb 25, 2020, 1:17:33 PM (6 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
7dc2e015
Parents:
9fb8f01 (diff), dd9e1ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

resolve conflict

Location:
libcfa
Files:
1 added
63 edited

Legend:

Unmodified
Added
Removed
  • libcfa/Makefile.in

    r9fb8f01 r3d5701e  
    231231CFACC = @CFACC@
    232232CFACPP = @CFACPP@
     233CFADIR_HASH = @CFADIR_HASH@
    233234CFA_BINDIR = @CFA_BINDIR@
    234235CFA_INCDIR = @CFA_INCDIR@
     
    274275LIPO = @LIPO@
    275276LN_S = @LN_S@
     277LOCAL_CC1 = @LOCAL_CC1@
     278LOCAL_CFACC = @LOCAL_CFACC@
    276279LTLIBOBJS = @LTLIBOBJS@
    277280LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
  • libcfa/automake/missing

    • Property mode changed from 120000 to 100644
    r9fb8f01 r3d5701e  
    1 /usr/share/automake-1.15/missing
     1#! /bin/sh
     2# Tdelisle : having the Makefiles.in automatically regenerated causes problems
     3#            when using multiple versions of automake, even if only on end user machines
     4#            therefore I am disabling that feature by commenting this script
     5exit 0
  • libcfa/configure

    r9fb8f01 r3d5701e  
    707707CONFIG_CFLAGS
    708708ARCH_FLAGS
     709CFADIR_HASH
     710LOCAL_CC1
     711LOCAL_CFACC
    709712CFACPP
    710713CFACC
     714ENABLE_DISTCC_FALSE
     715ENABLE_DISTCC_TRUE
    711716CFA_VERSION
    712717DRIVER_DIR
     
    783788enable_option_checking
    784789enable_silent_rules
     790enable_distcc
    785791with_cfa_name
    786792enable_shared
     
    14451451  --enable-silent-rules   less verbose build output (undo: "make V=1")
    14461452  --disable-silent-rules  verbose build output (undo: "make V=0")
     1453  --enable-distcc     whether or not to enable distributed compilation
    14471454  --enable-shared[=PKGS]  build shared libraries [default=yes]
    14481455  --enable-static[=PKGS]  build static libraries [default=yes]
     
    29412948
    29422949
    2943 CFACC=${DRIVER_DIR}cfa
     2950# Check whether --enable-distcc was given.
     2951if test "${enable_distcc+set}" = set; then :
     2952  enableval=$enable_distcc; enable_distcc=$enableval
     2953else
     2954  enable_distcc=no
     2955fi
     2956
     2957
     2958echo -n "checking for distributated build... "
     2959if test x$enable_distcc = xno; then
     2960        CFACC=${DRIVER_DIR}cfa
     2961        echo "no"
     2962else
     2963        tools="$(readlink -m $ac_confdir/)/../tools/build"
     2964        config=$(basename $(readlink -f .))
     2965        echo "$tools/distcc_hash $config"
     2966        CFADIR_HASH=$($tools/distcc_hash $config)
     2967        CFACC="distcc ~/.cfadistcc/${CFADIR_HASH}/cfa"
     2968        echo "yes (hash=${CFADIR_HASH})"
     2969fi
    29442970CFACPP=${DRIVER_DIR}cfa-cpp
     2971LOCAL_CFACC=${DRIVER_DIR}cfa
     2972LOCAL_CC1=${DRIVER_DIR}cc1
     2973
     2974 if test x$enable_distcc = xyes; then
     2975  ENABLE_DISTCC_TRUE=
     2976  ENABLE_DISTCC_FALSE='#'
     2977else
     2978  ENABLE_DISTCC_TRUE='#'
     2979  ENABLE_DISTCC_FALSE=
     2980fi
     2981
     2982
     2983
     2984
     2985
    29452986
    29462987
     
    29593000case $CONFIGURATION in
    29603001        "debug"   )
    2961                 CONFIG_CFLAGS="-Og -g"
     3002                CONFIG_CFLAGS="-O0 -g"
    29623003                CONFIG_CFAFLAGS="-debug"
    29633004                CONFIG_BUILDLIB="yes"
     
    1698217023fi
    1698317024
     17025if test -z "${ENABLE_DISTCC_TRUE}" && test -z "${ENABLE_DISTCC_FALSE}"; then
     17026  as_fn_error $? "conditional \"ENABLE_DISTCC\" was never defined.
     17027Usually this means the macro was only invoked conditionally." "$LINENO" 5
     17028fi
    1698417029if test -z "${BUILDLIB_TRUE}" && test -z "${BUILDLIB_FALSE}"; then
    1698517030  as_fn_error $? "conditional \"BUILDLIB\" was never defined.
  • libcfa/configure.ac

    r9fb8f01 r3d5701e  
    2727AC_ARG_VAR(CFA_VERSION, [The long version of cfa])
    2828
    29 CFACC=${DRIVER_DIR}cfa
     29AC_ARG_ENABLE(distcc,
     30        [  --enable-distcc     whether or not to enable distributed compilation],
     31        enable_distcc=$enableval, enable_distcc=no)
     32
     33echo -n "checking for distributated build... "
     34if test x$enable_distcc = xno; then
     35        CFACC=${DRIVER_DIR}cfa
     36        echo "no"
     37else
     38        tools="$(readlink -m $ac_confdir/)/../tools/build"
     39        config=$(basename $(readlink -f .))
     40        echo "$tools/distcc_hash $config"
     41        CFADIR_HASH=$($tools/distcc_hash $config)
     42        CFACC="distcc ~/.cfadistcc/${CFADIR_HASH}/cfa"
     43        echo "yes (hash=${CFADIR_HASH})"
     44fi
    3045CFACPP=${DRIVER_DIR}cfa-cpp
     46LOCAL_CFACC=${DRIVER_DIR}cfa
     47LOCAL_CC1=${DRIVER_DIR}cc1
     48
     49AM_CONDITIONAL([ENABLE_DISTCC], [test x$enable_distcc = xyes])
     50
    3151AC_SUBST(CFACC)
    3252AC_SUBST(CFACPP)
     53AC_SUBST(LOCAL_CFACC)
     54AC_SUBST(LOCAL_CC1)
     55AC_SUBST(CFADIR_HASH)
    3356AC_SUBST(CFA_VERSION)
    3457
     
    4568case $CONFIGURATION in
    4669        "debug"   )
    47                 CONFIG_CFLAGS="-Og -g"
     70                CONFIG_CFLAGS="-O0 -g"
    4871                CONFIG_CFAFLAGS="-debug"
    4972                CONFIG_BUILDLIB="yes"
  • libcfa/prelude/Makefile.am

    r9fb8f01 r3d5701e  
    1111## Created On       : Sun May 31 08:54:01 2015
    1212## Last Modified By : Peter A. Buhr
    13 ## Last Modified On : Wed Dec 14 15:00:35 2016
    14 ## Update Count     : 205
     13## Last Modified On : Mon Feb  3 21:27:18 2020
     14## Update Count     : 208
    1515###############################################################################
    1616
     
    2323cfalib_DATA = gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c
    2424
    25 CC = @CFACC@
     25CC = @LOCAL_CFACC@
    2626AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC @ARCH_FLAGS@ @CONFIG_CFLAGS@
    2727AM_CFAFLAGS = @CONFIG_CFAFLAGS@
     
    3636extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c
    3737        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx > extras.cf
     38        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> extras.cf
    3839
    3940# create forward declarations for gcc builtins
     
    5455
    5556# create forward declarations for cfa builtins
    56 builtins.cf : builtins.c ${CC}
     57builtins.cf : builtins.c @LOCAL_CFACC@
    5758        ${AM_V_GEN}gcc ${AM_CFLAGS} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
    5859        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
     
    6869MOSTLYCLEANFILES = bootloader.c builtins.cf extras.cf gcc-builtins.c gcc-builtins.cf prelude.cfa
    6970MAINTAINERCLEANFILES = ${addprefix ${libdir}/,${cfalib_DATA}} ${addprefix ${libdir}/,${lib_LIBRARIES}}
     71
     72if ENABLE_DISTCC
     73distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     74        ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@
     75        @echo "Dummy file to track distribution to remote hosts" > ${@}
     76
     77all: all-am distribution
     78endif ENABLE_DISTCC
  • libcfa/prelude/Makefile.in

    r9fb8f01 r3d5701e  
    1 # Makefile.in generated by automake 1.15 from Makefile.am.
     1# Makefile.in generated by automake 1.16.1 from Makefile.am.
    22# @configure_input@
    33
    4 # Copyright (C) 1994-2014 Free Software Foundation, Inc.
     4# Copyright (C) 1994-2018 Free Software Foundation, Inc.
    55
    66# This Makefile.in is free software; the Free Software Foundation
     
    167167AUTOMAKE = @AUTOMAKE@
    168168AWK = @AWK@
    169 CC = @CFACC@
     169CC = @LOCAL_CFACC@
    170170CCAS = @CCAS@
    171171CCASDEPMODE = @CCASDEPMODE@
     
    174174CFACC = @CFACC@
    175175CFACPP = @CFACPP@
     176CFADIR_HASH = @CFADIR_HASH@
    176177CFA_BINDIR = @CFA_BINDIR@
    177178CFA_INCDIR = @CFA_INCDIR@
     
    217218LIPO = @LIPO@
    218219LN_S = @LN_S@
     220LOCAL_CC1 = @LOCAL_CC1@
     221LOCAL_CFACC = @LOCAL_CFACC@
    219222LTLIBOBJS = @LTLIBOBJS@
    220223LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     
    328331            cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
    329332          *) \
    330             echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
    331             cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
     333            echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
     334            cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
    332335        esac;
    333336
     
    374377
    375378
    376 distdir: $(DISTFILES)
     379distdir: $(BUILT_SOURCES)
     380        $(MAKE) $(AM_MAKEFLAGS) distdir-am
     381
     382distdir-am: $(DISTFILES)
    377383        @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
    378384        topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
     
    537543extras.cf : ${srcdir}/extras.regx ${srcdir}/extras.c
    538544        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -f ${srcdir}/extras.regx > extras.cf
     545        ${AM_V_GEN}gcc ${AM_CFLAGS} -E ${srcdir}/extras.c | grep -zo -f ${srcdir}/extras.regx2 | tr '\0' '\n' >> extras.cf
    539546
    540547# create forward declarations for gcc builtins
     
    555562
    556563# create forward declarations for cfa builtins
    557 builtins.cf : builtins.c ${CC}
     564builtins.cf : builtins.c @LOCAL_CFACC@
    558565        ${AM_V_GEN}gcc ${AM_CFLAGS} -E -P ${<} -o ${@} -MD -MP -MF $(DEPDIR)/builtins.Po -D__cforall
    559566        ${AM_V_at}sed -i 's/builtins.o/builtins.cf/g' $(DEPDIR)/builtins.Po
     
    566573maintainer-clean-local :
    567574        rm -rf $(DEPDIR)
     575
     576@ENABLE_DISTCC_TRUE@distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ gcc-builtins.cf builtins.cf extras.cf prelude.cfa bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     577@ENABLE_DISTCC_TRUE@    ${AM_V_GEN}$(srcdir)/../../tools/build/push2dist.sh @CFADIR_HASH@
     578@ENABLE_DISTCC_TRUE@    @echo "Dummy file to track distribution to remote hosts" > ${@}
     579
     580@ENABLE_DISTCC_TRUE@all: all-am distribution
    568581
    569582# Tell versions [3.59,3.63) of GNU make to not export all variables.
  • libcfa/prelude/builtins.c

    r9fb8f01 r3d5701e  
    1010// Created On       : Fri Jul 21 16:21:03 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun 25 18:06:52 2019
    13 // Update Count     : 97
     12// Last Modified On : Thu Nov 21 16:31:39 2019
     13// Update Count     : 101
    1414//
    1515
     
    6969
    7070// universal typed pointer constant
    71 // Compiler issue: there is a problem with anonymous types that do not have a size.
    72 static inline forall( dtype DT | sized(DT) ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
     71static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
    7372
    7473// exponentiation operator implementation
  • libcfa/prelude/extras.regx

    r9fb8f01 r3d5701e  
    1919typedef.* uint32_t;
    2020typedef.* uint64_t;
     21typedef.* __uint_least16_t;
     22typedef.* __uint_least32_t;
    2123typedef.* char16_t;
    2224typedef.* char32_t;
    2325typedef.* wchar_t;
    24 extern.*\*malloc\(.*\).*
    25 extern.* free\(.*\).*
    26 extern.* exit\(.*\).*
    27 extern.* atexit\(.*\).*
    28 extern.* abort\(.*\).*
    29 extern.* printf\(.*\).*
  • libcfa/prelude/prototypes.awk

    r9fb8f01 r3d5701e  
    1010# Created On       : Sat May 16 07:57:37 2015
    1111# Last Modified By : Peter A. Buhr
    12 # Last Modified On : Thu Jun  6 20:46:28 2019
    13 # Update Count     : 34
     12# Last Modified On : Sat Feb  8 09:46:58 2020
     13# Update Count     : 36
    1414#
    1515
     
    1717
    1818BEGIN {
    19   FS = "[( )]"
     19        FS = "[( )]"
    2020        # order so string search is longest string
    2121        i=-1
     
    8484
    8585/BT_FN/ {
    86         for (i = 1; i <= NF; i++) {
    87           if( match($i, "BT_FN") != 0 ) {
    88                 prototypes[$i] = $i
    89           }
     86        for (i = 1; i <= NF; i += 1 ) {
     87                if ( match($i, "BT_FN") != 0 ) {
     88                        prototypes[$i] = $i
     89                }
    9090        }
    91   }
     91}
    9292
    9393END {
     
    103103
    104104        for ( prototype in prototypes ) {
    105           # printf( "//\"%s\"\n", prototype )
    106           if ( index( "BT_LAST", prototype ) == 1 ) {
    107                 continue
    108           } # if
     105                # printf( "//\"%s\"\n", prototype )
     106                if ( index( "BT_LAST", prototype ) == 1 ) {
     107                        continue
     108                } # if
    109109
    110           printf( "#define %s(NAME) FUNC_SIMPLE(", prototype )
     110                printf( "#define %s(NAME) FUNC_SIMPLE(", prototype )
    111111
    112           if ( sub( "BT_FN_", "", prototype ) == 0 ) {
    113                 printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype )
    114                 exit 0
    115           } # if
     112                if ( sub( "BT_FN_", "", prototype ) == 0 ) {
     113                        printf( "\n********** BAD MACRO NAME \"%s\" **********\n", prototype )
     114                        exit 0
     115                } # if
    116116
    117           # generate function return type as macro
    118           for ( t = 0; t < N; t += 1 ) {                                        # find longest match
    119                 type = types[t];
    120                 if ( index( prototype, type ) == 1 ) {          # found match
    121                   printf( "BT_%s, NAME", type )
    122                   sub( type, "", prototype )
    123                   break;
     117                # generate function return type as macro
     118                for ( t = 0; t < N; t += 1 ) {                                  # find longest match
     119                        type = types[t];
     120                        if ( index( prototype, type ) == 1 ) {          # found match
     121                                printf( "BT_%s, NAME", type )
     122                                sub( type, "", prototype )
     123                                break;
     124                        } # if
     125                } # for
     126
     127                # generate function parameter types as macro
     128                if ( index( prototype, "VAR" ) != 2 ) {                 # C-style empty parameters ?
     129                        for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed
     130                                sub( "_", "", prototype)                                # remove "_"
     131                                printf( ", ", type )
     132                                temp = prototype
     133                                for ( t = 0; t < N; t += 1 ) {                  # find longest match
     134                                        type = types[t];
     135                                        if ( index( prototype, type ) == 1 ) { # found match
     136                                                printf( "BT_%s", type )
     137                                                sub( type, "", prototype )
     138                                                break;
     139                                        } # if
     140                                } # for
     141                                if ( temp == prototype ) {                              # no match found for parameter in macro table
     142                                        printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype )
     143                                        exit 0
     144                                } # if
     145                        } # for
    124146                } # if
    125           } # for
    126 
    127           # generate function parameter types as macro
    128           if ( index( prototype, "VAR" ) != 2 ) {                       # C-style empty parameters ?
    129                 for ( p = 0; length( prototype ) > 0; p += 1 ) { # until all parameters types are removed
    130                   sub( "_", "", prototype)                              # remove "_"
    131                   printf( ", ", type )
    132                   temp = prototype
    133                   for ( t = 0; t < N; t += 1 ) {                        # find longest match
    134                         type = types[t];
    135                         if ( index( prototype, type ) == 1 ) { # found match
    136                           printf( "BT_%s", type )
    137                           sub( type, "", prototype )
    138                           break;
    139                         } # if
    140                   } # for
    141                   if ( temp == prototype ) {                            # no match found for parameter in macro table
    142                         printf( "\n********** MISSING TYPE \"%s\" **********\n", prototype )
    143                         exit 0
    144                   } # if
    145                 } # for
    146           } # if
    147           printf( ")\n" )
     147                printf( ")\n" )
    148148        } # for
    149149
  • libcfa/prelude/sync-builtins.cf

    r9fb8f01 r3d5701e  
    11char __sync_fetch_and_add(volatile char *, char,...);
    2 char __sync_fetch_and_add_1(volatile char *, char,...);
    32signed char __sync_fetch_and_add(volatile signed char *, signed char,...);
    4 signed char __sync_fetch_and_add_1(volatile signed char *, signed char,...);
    53unsigned char __sync_fetch_and_add(volatile unsigned char *, unsigned char,...);
    6 unsigned char __sync_fetch_and_add_1(volatile unsigned char *, unsigned char,...);
    74signed short __sync_fetch_and_add(volatile signed short *, signed short,...);
    8 signed short __sync_fetch_and_add_2(volatile signed short *, signed short,...);
    95unsigned short __sync_fetch_and_add(volatile unsigned short *, unsigned short,...);
    10 unsigned short __sync_fetch_and_add_2(volatile unsigned short *, unsigned short,...);
    116signed int __sync_fetch_and_add(volatile signed int *, signed int,...);
    12 signed int __sync_fetch_and_add_4(volatile signed int *, signed int,...);
    137unsigned int __sync_fetch_and_add(volatile unsigned int *, unsigned int,...);
    14 unsigned int __sync_fetch_and_add_4(volatile unsigned int *, unsigned int,...);
     8signed long int __sync_fetch_and_add(volatile signed long int *, signed long int,...);
     9unsigned long int __sync_fetch_and_add(volatile unsigned long int *, unsigned long int,...);
    1510signed long long int __sync_fetch_and_add(volatile signed long long int *, signed long long int,...);
    16 signed long long int __sync_fetch_and_add_8(volatile signed long long int *, signed long long int,...);
    1711unsigned long long int __sync_fetch_and_add(volatile unsigned long long int *, unsigned long long int,...);
    18 unsigned long long int __sync_fetch_and_add_8(volatile unsigned long long int *, unsigned long long int,...);
    1912#if defined(__SIZEOF_INT128__)
    2013signed __int128 __sync_fetch_and_add(volatile signed __int128 *, signed __int128,...);
    21 signed __int128 __sync_fetch_and_add_16(volatile signed __int128 *, signed __int128,...);
    2214unsigned __int128 __sync_fetch_and_add(volatile unsigned __int128 *, unsigned __int128,...);
    23 unsigned __int128 __sync_fetch_and_add_16(volatile unsigned __int128 *, unsigned __int128,...);
    2415#endif
    2516
    2617char __sync_fetch_and_sub(volatile char *, char,...);
    27 char __sync_fetch_and_sub_1(volatile char *, char,...);
    2818signed char __sync_fetch_and_sub(volatile signed char *, signed char,...);
    29 signed char __sync_fetch_and_sub_1(volatile signed char *, signed char,...);
    3019unsigned char __sync_fetch_and_sub(volatile unsigned char *, unsigned char,...);
    31 unsigned char __sync_fetch_and_sub_1(volatile unsigned char *, unsigned char,...);
    3220signed short __sync_fetch_and_sub(volatile signed short *, signed short,...);
    33 signed short __sync_fetch_and_sub_2(volatile signed short *, signed short,...);
    3421unsigned short __sync_fetch_and_sub(volatile unsigned short *, unsigned short,...);
    35 unsigned short __sync_fetch_and_sub_2(volatile unsigned short *, unsigned short,...);
    3622signed int __sync_fetch_and_sub(volatile signed int *, signed int,...);
    37 signed int __sync_fetch_and_sub_4(volatile signed int *, signed int,...);
    3823unsigned int __sync_fetch_and_sub(volatile unsigned int *, unsigned int,...);
    39 unsigned int __sync_fetch_and_sub_4(volatile unsigned int *, unsigned int,...);
     24signed long int __sync_fetch_and_sub(volatile signed long int *, signed long int,...);
     25unsigned long int __sync_fetch_and_sub(volatile unsigned long int *, unsigned long int,...);
    4026signed long long int __sync_fetch_and_sub(volatile signed long long int *, signed long long int,...);
    41 signed long long int __sync_fetch_and_sub_8(volatile signed long long int *, signed long long int,...);
    4227unsigned long long int __sync_fetch_and_sub(volatile unsigned long long int *, unsigned long long int,...);
    43 unsigned long long int __sync_fetch_and_sub_8(volatile unsigned long long int *, unsigned long long int,...);
    4428#if defined(__SIZEOF_INT128__)
    4529signed __int128 __sync_fetch_and_sub(volatile signed __int128 *, signed __int128,...);
    46 signed __int128 __sync_fetch_and_sub_16(volatile signed __int128 *, signed __int128,...);
    4730unsigned __int128 __sync_fetch_and_sub(volatile unsigned __int128 *, unsigned __int128,...);
    48 unsigned __int128 __sync_fetch_and_sub_16(volatile unsigned __int128 *, unsigned __int128,...);
    4931#endif
    5032
    5133char __sync_fetch_and_or(volatile char *, char,...);
    52 char __sync_fetch_and_or_1(volatile char *, char,...);
    5334signed char __sync_fetch_and_or(volatile signed char *, signed char,...);
    54 signed char __sync_fetch_and_or_1(volatile signed char *, signed char,...);
    5535unsigned char __sync_fetch_and_or(volatile unsigned char *, unsigned char,...);
    56 unsigned char __sync_fetch_and_or_1(volatile unsigned char *, unsigned char,...);
    5736signed short __sync_fetch_and_or(volatile signed short *, signed short,...);
    58 signed short __sync_fetch_and_or_2(volatile signed short *, signed short,...);
    5937unsigned short __sync_fetch_and_or(volatile unsigned short *, unsigned short,...);
    60 unsigned short __sync_fetch_and_or_2(volatile unsigned short *, unsigned short,...);
    6138signed int __sync_fetch_and_or(volatile signed int *, signed int,...);
    62 signed int __sync_fetch_and_or_4(volatile signed int *, signed int,...);
    6339unsigned int __sync_fetch_and_or(volatile unsigned int *, unsigned int,...);
    64 unsigned int __sync_fetch_and_or_4(volatile unsigned int *, unsigned int,...);
     40signed long int __sync_fetch_and_or(volatile signed long int *, signed long int,...);
     41unsigned long int __sync_fetch_and_or(volatile unsigned long int *, unsigned long int,...);
    6542signed long long int __sync_fetch_and_or(volatile signed long long int *, signed long long int,...);
    66 signed long long int __sync_fetch_and_or_8(volatile signed long long int *, signed long long int,...);
    6743unsigned long long int __sync_fetch_and_or(volatile unsigned long long int *, unsigned long long int,...);
    68 unsigned long long int __sync_fetch_and_or_8(volatile unsigned long long int *, unsigned long long int,...);
    6944#if defined(__SIZEOF_INT128__)
    7045signed __int128 __sync_fetch_and_or(volatile signed __int128 *, signed __int128,...);
    71 signed __int128 __sync_fetch_and_or_16(volatile signed __int128 *, signed __int128,...);
    7246unsigned __int128 __sync_fetch_and_or(volatile unsigned __int128 *, unsigned __int128,...);
    73 unsigned __int128 __sync_fetch_and_or_16(volatile unsigned __int128 *, unsigned __int128,...);
    7447#endif
    7548
    7649char __sync_fetch_and_and(volatile char *, char,...);
    77 char __sync_fetch_and_and_1(volatile char *, char,...);
    7850signed char __sync_fetch_and_and(volatile signed char *, signed char,...);
    79 signed char __sync_fetch_and_and_1(volatile signed char *, signed char,...);
    8051unsigned char __sync_fetch_and_and(volatile unsigned char *, unsigned char,...);
    81 unsigned char __sync_fetch_and_and_1(volatile unsigned char *, unsigned char,...);
    8252signed short __sync_fetch_and_and(volatile signed short *, signed short,...);
    83 signed short __sync_fetch_and_and_2(volatile signed short *, signed short,...);
    8453unsigned short __sync_fetch_and_and(volatile unsigned short *, unsigned short,...);
    85 unsigned short __sync_fetch_and_and_2(volatile unsigned short *, unsigned short,...);
    8654signed int __sync_fetch_and_and(volatile signed int *, signed int,...);
    87 signed int __sync_fetch_and_and_4(volatile signed int *, signed int,...);
    8855unsigned int __sync_fetch_and_and(volatile unsigned int *, unsigned int,...);
    89 unsigned int __sync_fetch_and_and_4(volatile unsigned int *, unsigned int,...);
     56signed long int __sync_fetch_and_and(volatile signed long int *, signed long int,...);
     57unsigned long int __sync_fetch_and_and(volatile unsigned long int *, unsigned long int,...);
    9058signed long long int __sync_fetch_and_and(volatile signed long long int *, signed long long int,...);
    91 signed long long int __sync_fetch_and_and_8(volatile signed long long int *, signed long long int,...);
    9259unsigned long long int __sync_fetch_and_and(volatile unsigned long long int *, unsigned long long int,...);
    93 unsigned long long int __sync_fetch_and_and_8(volatile unsigned long long int *, unsigned long long int,...);
    9460#if defined(__SIZEOF_INT128__)
    9561signed __int128 __sync_fetch_and_and(volatile signed __int128 *, signed __int128,...);
    96 signed __int128 __sync_fetch_and_and_16(volatile signed __int128 *, signed __int128,...);
    9762unsigned __int128 __sync_fetch_and_and(volatile unsigned __int128 *, unsigned __int128,...);
    98 unsigned __int128 __sync_fetch_and_and_16(volatile unsigned __int128 *, unsigned __int128,...);
    9963#endif
    10064
    10165char __sync_fetch_and_xor(volatile char *, char,...);
    102 char __sync_fetch_and_xor_1(volatile char *, char,...);
    10366signed char __sync_fetch_and_xor(volatile signed char *, signed char,...);
    104 signed char __sync_fetch_and_xor_1(volatile signed char *, signed char,...);
    10567unsigned char __sync_fetch_and_xor(volatile unsigned char *, unsigned char,...);
    106 unsigned char __sync_fetch_and_xor_1(volatile unsigned char *, unsigned char,...);
    10768signed short __sync_fetch_and_xor(volatile signed short *, signed short,...);
    108 signed short __sync_fetch_and_xor_2(volatile signed short *, signed short,...);
    10969unsigned short __sync_fetch_and_xor(volatile unsigned short *, unsigned short,...);
    110 unsigned short __sync_fetch_and_xor_2(volatile unsigned short *, unsigned short,...);
    11170signed int __sync_fetch_and_xor(volatile signed int *, signed int,...);
    112 signed int __sync_fetch_and_xor_4(volatile signed int *, signed int,...);
    11371unsigned int __sync_fetch_and_xor(volatile unsigned int *, unsigned int,...);
    114 unsigned int __sync_fetch_and_xor_4(volatile unsigned int *, unsigned int,...);
     72signed long int __sync_fetch_and_xor(volatile signed long int *, signed long int,...);
     73unsigned long int __sync_fetch_and_xor(volatile unsigned long int *, unsigned long int,...);
    11574signed long long int __sync_fetch_and_xor(volatile signed long long int *, signed long long int,...);
    116 signed long long int __sync_fetch_and_xor_8(volatile signed long long int *, signed long long int,...);
    11775unsigned long long int __sync_fetch_and_xor(volatile unsigned long long int *, unsigned long long int,...);
    118 unsigned long long int __sync_fetch_and_xor_8(volatile unsigned long long int *, unsigned long long int,...);
    11976#if defined(__SIZEOF_INT128__)
    12077signed __int128 __sync_fetch_and_xor(volatile signed __int128 *, signed __int128,...);
    121 signed __int128 __sync_fetch_and_xor_16(volatile signed __int128 *, signed __int128,...);
    12278unsigned __int128 __sync_fetch_and_xor(volatile unsigned __int128 *, unsigned __int128,...);
    123 unsigned __int128 __sync_fetch_and_xor_16(volatile unsigned __int128 *, unsigned __int128,...);
    12479#endif
    12580
    12681char __sync_fetch_and_nand(volatile char *, char,...);
    127 char __sync_fetch_and_nand_1(volatile char *, char,...);
    12882signed char __sync_fetch_and_nand(volatile signed char *, signed char,...);
    129 signed char __sync_fetch_and_nand_1(volatile signed char *, signed char,...);
    13083unsigned char __sync_fetch_and_nand(volatile unsigned char *, unsigned char,...);
    131 unsigned char __sync_fetch_and_nand_1(volatile unsigned char *, unsigned char,...);
    13284signed short __sync_fetch_and_nand(volatile signed short *, signed short,...);
    133 signed short __sync_fetch_and_nand_2(volatile signed short *, signed short,...);
    13485unsigned short __sync_fetch_and_nand(volatile unsigned short *, unsigned short,...);
    135 unsigned short __sync_fetch_and_nand_2(volatile unsigned short *, unsigned short,...);
    13686signed int __sync_fetch_and_nand(volatile signed int *, signed int,...);
    137 signed int __sync_fetch_and_nand_4(volatile signed int *, signed int,...);
    13887unsigned int __sync_fetch_and_nand(volatile unsigned int *, unsigned int,...);
    139 unsigned int __sync_fetch_and_nand_4(volatile unsigned int *, unsigned int,...);
     88signed long int __sync_fetch_and_nand(volatile signed long int *, signed long int,...);
     89unsigned long int __sync_fetch_and_nand(volatile unsigned long int *, unsigned long int,...);
    14090signed long long int __sync_fetch_and_nand(volatile signed long long int *, signed long long int,...);
    141 signed long long int __sync_fetch_and_nand_8(volatile signed long long int *, signed long long int,...);
    14291unsigned long long int __sync_fetch_and_nand(volatile unsigned long long int *, unsigned long long int,...);
    143 unsigned long long int __sync_fetch_and_nand_8(volatile unsigned long long int *, unsigned long long int,...);
    14492#if defined(__SIZEOF_INT128__)
    14593signed __int128 __sync_fetch_and_nand(volatile signed __int128 *, signed __int128,...);
    146 signed __int128 __sync_fetch_and_nand_16(volatile signed __int128 *, signed __int128,...);
    14794unsigned __int128 __sync_fetch_and_nand(volatile unsigned __int128 *, unsigned __int128,...);
    148 unsigned __int128 __sync_fetch_and_nand_16(volatile unsigned __int128 *, unsigned __int128,...);
    14995#endif
    15096
    15197char __sync_add_and_fetch(volatile char *, char,...);
    152 char __sync_add_and_fetch_1(volatile char *, char,...);
    15398signed char __sync_add_and_fetch(volatile signed char *, signed char,...);
    154 signed char __sync_add_and_fetch_1(volatile signed char *, signed char,...);
    15599unsigned char __sync_add_and_fetch(volatile unsigned char *, unsigned char,...);
    156 unsigned char __sync_add_and_fetch_1(volatile unsigned char *, unsigned char,...);
    157100signed short __sync_add_and_fetch(volatile signed short *, signed short,...);
    158 signed short __sync_add_and_fetch_2(volatile signed short *, signed short,...);
    159101unsigned short __sync_add_and_fetch(volatile unsigned short *, unsigned short,...);
    160 unsigned short __sync_add_and_fetch_2(volatile unsigned short *, unsigned short,...);
    161102signed int __sync_add_and_fetch(volatile signed int *, signed int,...);
    162 signed int __sync_add_and_fetch_4(volatile signed int *, signed int,...);
    163103signed int __sync_add_and_fetch(volatile signed int *, signed int,...);
    164 signed int __sync_add_and_fetch_4(volatile signed int *, signed int,...);
     104signed long int __sync_add_and_fetch(volatile signed long int *, signed long int,...);
     105unsigned long int __sync_add_and_fetch(volatile unsigned long int *, unsigned long int,...);
    165106signed long long int __sync_add_and_fetch(volatile signed long long int *, signed long long int,...);
    166 signed long long int __sync_add_and_fetch_8(volatile signed long long int *, signed long long int,...);
    167107unsigned long long int __sync_add_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    168 unsigned long long int __sync_add_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    169108#if defined(__SIZEOF_INT128__)
    170109signed __int128 __sync_add_and_fetch(volatile signed __int128 *, signed __int128,...);
    171 signed __int128 __sync_add_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    172110unsigned __int128 __sync_add_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    173 unsigned __int128 __sync_add_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    174111#endif
    175112
    176113char __sync_sub_and_fetch(volatile char *, char,...);
    177 char __sync_sub_and_fetch_1(volatile char *, char,...);
    178114signed char __sync_sub_and_fetch(volatile signed char *, signed char,...);
    179 signed char __sync_sub_and_fetch_1(volatile signed char *, signed char,...);
    180115unsigned char __sync_sub_and_fetch(volatile unsigned char *, unsigned char,...);
    181 unsigned char __sync_sub_and_fetch_1(volatile unsigned char *, unsigned char,...);
    182116signed short __sync_sub_and_fetch(volatile signed short *, signed short,...);
    183 signed short __sync_sub_and_fetch_2(volatile signed short *, signed short,...);
    184117unsigned short __sync_sub_and_fetch(volatile unsigned short *, unsigned short,...);
    185 unsigned short __sync_sub_and_fetch_2(volatile unsigned short *, unsigned short,...);
    186118signed int __sync_sub_and_fetch(volatile signed int *, signed int,...);
    187 signed int __sync_sub_and_fetch_4(volatile signed int *, signed int,...);
    188119unsigned int __sync_sub_and_fetch(volatile unsigned int *, unsigned int,...);
    189 unsigned int __sync_sub_and_fetch_4(volatile unsigned int *, unsigned int,...);
     120signed long int __sync_sub_and_fetch(volatile signed long int *, signed long int,...);
     121unsigned long int __sync_sub_and_fetch(volatile unsigned long int *, unsigned long int,...);
    190122signed long long int __sync_sub_and_fetch(volatile signed long long int *, signed long long int,...);
    191 signed long long int __sync_sub_and_fetch_8(volatile signed long long int *, signed long long int,...);
    192123unsigned long long int __sync_sub_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    193 unsigned long long int __sync_sub_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    194124#if defined(__SIZEOF_INT128__)
    195125signed __int128 __sync_sub_and_fetch(volatile signed __int128 *, signed __int128,...);
    196 signed __int128 __sync_sub_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    197126unsigned __int128 __sync_sub_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    198 unsigned __int128 __sync_sub_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    199127#endif
    200128
    201129char __sync_or_and_fetch(volatile char *, char,...);
    202 char __sync_or_and_fetch_1(volatile char *, char,...);
    203130signed char __sync_or_and_fetch(volatile signed char *, signed char,...);
    204 signed char __sync_or_and_fetch_1(volatile signed char *, signed char,...);
    205131unsigned char __sync_or_and_fetch(volatile unsigned char *, unsigned char,...);
    206 unsigned char __sync_or_and_fetch_1(volatile unsigned char *, unsigned char,...);
    207132signed short __sync_or_and_fetch(volatile signed short *, signed short,...);
    208 signed short __sync_or_and_fetch_2(volatile signed short *, signed short,...);
    209133unsigned short __sync_or_and_fetch(volatile unsigned short *, unsigned short,...);
    210 unsigned short __sync_or_and_fetch_2(volatile unsigned short *, unsigned short,...);
    211134signed int __sync_or_and_fetch(volatile signed int *, signed int,...);
    212 signed int __sync_or_and_fetch_4(volatile signed int *, signed int,...);
    213135unsigned int __sync_or_and_fetch(volatile unsigned int *, unsigned int,...);
    214 unsigned int __sync_or_and_fetch_4(volatile unsigned int *, unsigned int,...);
     136signed long int __sync_or_and_fetch(volatile signed long int *, signed long int,...);
     137unsigned long int __sync_or_and_fetch(volatile unsigned long int *, unsigned long int,...);
    215138signed long long int __sync_or_and_fetch(volatile signed long long int *, signed long long int,...);
    216 signed long long int __sync_or_and_fetch_8(volatile signed long long int *, signed long long int,...);
    217139unsigned long long int __sync_or_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    218 unsigned long long int __sync_or_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    219140#if defined(__SIZEOF_INT128__)
    220141signed __int128 __sync_or_and_fetch(volatile signed __int128 *, signed __int128,...);
    221 signed __int128 __sync_or_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    222142unsigned __int128 __sync_or_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    223 unsigned __int128 __sync_or_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    224143#endif
    225144
    226145char __sync_and_and_fetch(volatile char *, char,...);
    227 char __sync_and_and_fetch_1(volatile char *, char,...);
    228146signed char __sync_and_and_fetch(volatile signed char *, signed char,...);
    229 signed char __sync_and_and_fetch_1(volatile signed char *, signed char,...);
    230147unsigned char __sync_and_and_fetch(volatile unsigned char *, unsigned char,...);
    231 unsigned char __sync_and_and_fetch_1(volatile unsigned char *, unsigned char,...);
    232148signed short __sync_and_and_fetch(volatile signed short *, signed short,...);
    233 signed short __sync_and_and_fetch_2(volatile signed short *, signed short,...);
    234149unsigned short __sync_and_and_fetch(volatile unsigned short *, unsigned short,...);
    235 unsigned short __sync_and_and_fetch_2(volatile unsigned short *, unsigned short,...);
    236150signed int __sync_and_and_fetch(volatile signed int *, signed int,...);
    237 signed int __sync_and_and_fetch_4(volatile signed int *, signed int,...);
    238151unsigned int __sync_and_and_fetch(volatile unsigned int *, unsigned int,...);
    239 unsigned int __sync_and_and_fetch_4(volatile unsigned int *, unsigned int,...);
     152signed long int __sync_and_and_fetch(volatile signed long int *, signed long int,...);
     153unsigned long int __sync_and_and_fetch(volatile unsigned long int *, unsigned long int,...);
    240154signed long long int __sync_and_and_fetch(volatile signed long long int *, signed long long int,...);
    241 signed long long int __sync_and_and_fetch_8(volatile signed long long int *, signed long long int,...);
    242155unsigned long long int __sync_and_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    243 unsigned long long int __sync_and_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    244156#if defined(__SIZEOF_INT128__)
    245157signed __int128 __sync_and_and_fetch(volatile signed __int128 *, signed __int128,...);
    246 signed __int128 __sync_and_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    247158unsigned __int128 __sync_and_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    248 unsigned __int128 __sync_and_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    249159#endif
    250160
    251161char __sync_xor_and_fetch(volatile char *, char,...);
    252 char __sync_xor_and_fetch_1(volatile char *, char,...);
    253162signed char __sync_xor_and_fetch(volatile signed char *, signed char,...);
    254 signed char __sync_xor_and_fetch_1(volatile signed char *, signed char,...);
    255163unsigned char __sync_xor_and_fetch(volatile unsigned char *, unsigned char,...);
    256 unsigned char __sync_xor_and_fetch_1(volatile unsigned char *, unsigned char,...);
    257164signed short __sync_xor_and_fetch(volatile signed short *, signed short,...);
    258 signed short __sync_xor_and_fetch_2(volatile signed short *, signed short,...);
    259165unsigned short __sync_xor_and_fetch(volatile unsigned short *, unsigned short,...);
    260 unsigned short __sync_xor_and_fetch_2(volatile unsigned short *, unsigned short,...);
    261166signed int __sync_xor_and_fetch(volatile signed int *, signed int,...);
    262 signed int __sync_xor_and_fetch_4(volatile signed int *, signed int,...);
    263167unsigned int __sync_xor_and_fetch(volatile unsigned int *, unsigned int,...);
    264 unsigned int __sync_xor_and_fetch_4(volatile unsigned int *, unsigned int,...);
     168signed long int __sync_xor_and_fetch(volatile signed long int *, signed long int,...);
     169unsigned long int __sync_xor_and_fetch(volatile unsigned long int *, unsigned long int,...);
    265170signed long long int __sync_xor_and_fetch(volatile signed long long int *, signed long long int,...);
    266 signed long long int __sync_xor_and_fetch_8(volatile signed long long int *, signed long long int,...);
    267171unsigned long long int __sync_xor_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    268 unsigned long long int __sync_xor_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    269172#if defined(__SIZEOF_INT128__)
    270173signed __int128 __sync_xor_and_fetch(volatile signed __int128 *, signed __int128,...);
    271 signed __int128 __sync_xor_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    272174unsigned __int128 __sync_xor_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    273 unsigned __int128 __sync_xor_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    274175#endif
    275176
    276177char __sync_nand_and_fetch(volatile char *, char,...);
    277 char __sync_nand_and_fetch_1(volatile char *, char,...);
    278178signed char __sync_nand_and_fetch(volatile signed char *, signed char,...);
    279 signed char __sync_nand_and_fetch_1(volatile signed char *, signed char,...);
    280179unsigned char __sync_nand_and_fetch(volatile unsigned char *, unsigned char,...);
    281 unsigned char __sync_nand_and_fetch_1(volatile unsigned char *, unsigned char,...);
    282180signed short __sync_nand_and_fetch(volatile signed short *, signed short,...);
    283 signed short __sync_nand_and_fetch_2(volatile signed short *, signed short,...);
    284181unsigned short __sync_nand_and_fetch(volatile unsigned short *, unsigned short,...);
    285 unsigned short __sync_nand_and_fetch_2(volatile unsigned short *, unsigned short,...);
    286182signed int __sync_nand_and_fetch(volatile signed int *, signed int,...);
    287 signed int __sync_nand_and_fetch_4(volatile signed int *, signed int,...);
    288183unsigned int __sync_nand_and_fetch(volatile unsigned int *, unsigned int,...);
    289 unsigned int __sync_nand_and_fetch_4(volatile unsigned int *, unsigned int,...);
     184signed long int __sync_nand_and_fetch(volatile signed long int *, signed long int,...);
     185unsigned long int __sync_nand_and_fetch(volatile unsigned long int *, unsigned long int,...);
    290186signed long long int __sync_nand_and_fetch(volatile signed long long int *, signed long long int,...);
    291 signed long long int __sync_nand_and_fetch_8(volatile signed long long int *, signed long long int,...);
    292187unsigned long long int __sync_nand_and_fetch(volatile unsigned long long int *, unsigned long long int,...);
    293 unsigned long long int __sync_nand_and_fetch_8(volatile unsigned long long int *, unsigned long long int,...);
    294188#if defined(__SIZEOF_INT128__)
    295189signed __int128 __sync_nand_and_fetch(volatile signed __int128 *, signed __int128,...);
    296 signed __int128 __sync_nand_and_fetch_16(volatile signed __int128 *, signed __int128,...);
    297190unsigned __int128 __sync_nand_and_fetch(volatile unsigned __int128 *, unsigned __int128,...);
    298 unsigned __int128 __sync_nand_and_fetch_16(volatile unsigned __int128 *, unsigned __int128,...);
    299191#endif
    300192
    301193_Bool __sync_bool_compare_and_swap(volatile char *, char, char,...);
    302 _Bool __sync_bool_compare_and_swap_1(volatile char *, char, char,...);
    303194_Bool __sync_bool_compare_and_swap(volatile signed char *, signed char, signed char,...);
    304 _Bool __sync_bool_compare_and_swap_1(volatile signed char *, signed char, signed char,...);
    305195_Bool __sync_bool_compare_and_swap(volatile unsigned char *, unsigned char, unsigned char,...);
    306 _Bool __sync_bool_compare_and_swap_1(volatile unsigned char *, unsigned char, unsigned char,...);
    307196_Bool __sync_bool_compare_and_swap(volatile short *, signed short, signed short,...);
    308 _Bool __sync_bool_compare_and_swap_2(volatile short *, signed short, signed short,...);
    309197_Bool __sync_bool_compare_and_swap(volatile short *, unsigned short, unsigned short,...);
    310 _Bool __sync_bool_compare_and_swap_2(volatile short *, unsigned short, unsigned short,...);
    311198_Bool __sync_bool_compare_and_swap(volatile signed int *, signed int, signed int,...);
    312 _Bool __sync_bool_compare_and_swap_4(volatile signed int *, signed int, signed int,...);
    313199_Bool __sync_bool_compare_and_swap(volatile unsigned int *, unsigned int, unsigned int,...);
    314 _Bool __sync_bool_compare_and_swap_4(volatile unsigned int *, unsigned int, unsigned int,...);
     200_Bool __sync_bool_compare_and_swap(volatile signed long int *, signed long int, signed long int,...);
     201_Bool __sync_bool_compare_and_swap(volatile unsigned long int *, unsigned long int, unsigned long int,...);
    315202_Bool __sync_bool_compare_and_swap(volatile signed long long int *, signed long long int, signed long long int,...);
    316 _Bool __sync_bool_compare_and_swap_8(volatile signed long long int *, signed long long int, signed long long int,...);
    317203_Bool __sync_bool_compare_and_swap(volatile unsigned long long int *, unsigned long long int, unsigned long long int,...);
    318 _Bool __sync_bool_compare_and_swap_8(volatile unsigned long long int *, unsigned long long int, unsigned long long int,...);
    319204#if defined(__SIZEOF_INT128__)
    320205_Bool __sync_bool_compare_and_swap(volatile signed __int128 *, signed __int128, signed __int128,...);
    321 _Bool __sync_bool_compare_and_swap_16(volatile signed __int128 *, signed __int128, signed __int128,...);
    322206_Bool __sync_bool_compare_and_swap(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    323 _Bool __sync_bool_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    324207#endif
    325208forall(dtype T) _Bool __sync_bool_compare_and_swap(T * volatile *, T *, T*, ...);
    326209
    327210char __sync_val_compare_and_swap(volatile char *, char, char,...);
    328 char __sync_val_compare_and_swap_1(volatile char *, char, char,...);
    329211signed char __sync_val_compare_and_swap(volatile signed char *, signed char, signed char,...);
    330 signed char __sync_val_compare_and_swap_1(volatile signed char *, signed char, signed char,...);
    331212unsigned char __sync_val_compare_and_swap(volatile unsigned char *, unsigned char, unsigned char,...);
    332 unsigned char __sync_val_compare_and_swap_1(volatile unsigned char *, unsigned char, unsigned char,...);
    333213signed short __sync_val_compare_and_swap(volatile signed short *, signed short, signed short,...);
    334 signed short __sync_val_compare_and_swap_2(volatile signed short *, signed short, signed short,...);
    335214unsigned short __sync_val_compare_and_swap(volatile unsigned short *, unsigned short, unsigned short,...);
    336 unsigned short __sync_val_compare_and_swap_2(volatile unsigned short *, unsigned short, unsigned short,...);
    337215signed int __sync_val_compare_and_swap(volatile signed int *, signed int, signed int,...);
    338 signed int __sync_val_compare_and_swap_4(volatile signed int *, signed int, signed int,...);
    339216unsigned int __sync_val_compare_and_swap(volatile unsigned int *, unsigned int, unsigned int,...);
    340 unsigned int __sync_val_compare_and_swap_4(volatile unsigned int *, unsigned int, unsigned int,...);
     217signed long int __sync_val_compare_and_swap(volatile signed long int *, signed long int, signed long int,...);
     218unsigned long int __sync_val_compare_and_swap(volatile unsigned long int *, unsigned long int, unsigned long int,...);
    341219signed long long int __sync_val_compare_and_swap(volatile signed long long int *, signed long long int, signed long long int,...);
    342 signed long long int __sync_val_compare_and_swap_8(volatile signed long long int *, signed long long int, signed long long int,...);
    343220unsigned long long int __sync_val_compare_and_swap(volatile unsigned long long int *, unsigned long long int, unsigned long long int,...);
    344 unsigned long long int __sync_val_compare_and_swap_8(volatile unsigned long long int *, unsigned long long int, unsigned long long int,...);
    345221#if defined(__SIZEOF_INT128__)
    346222signed __int128 __sync_val_compare_and_swap(volatile signed __int128 *, signed __int128, signed __int128,...);
    347 signed __int128 __sync_val_compare_and_swap_16(volatile signed __int128 *, signed __int128, signed __int128,...);
    348223unsigned __int128 __sync_val_compare_and_swap(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    349 unsigned __int128 __sync_val_compare_and_swap_16(volatile unsigned __int128 *, unsigned __int128, unsigned __int128,...);
    350224#endif
    351225forall(dtype T) T * __sync_val_compare_and_swap(T * volatile *, T *, T*,...);
    352226
    353227char __sync_lock_test_and_set(volatile char *, char,...);
    354 char __sync_lock_test_and_set_1(volatile char *, char,...);
    355228signed char __sync_lock_test_and_set(volatile signed char *, signed char,...);
    356 signed char __sync_lock_test_and_set_1(volatile signed char *, signed char,...);
    357229unsigned char __sync_lock_test_and_set(volatile unsigned char *, unsigned char,...);
    358 unsigned char __sync_lock_test_and_set_1(volatile unsigned char *, unsigned char,...);
    359230signed short __sync_lock_test_and_set(volatile signed short *, signed short,...);
    360 signed short __sync_lock_test_and_set_2(volatile signed short *, signed short,...);
    361231unsigned short __sync_lock_test_and_set(volatile unsigned short *, unsigned short,...);
    362 unsigned short __sync_lock_test_and_set_2(volatile unsigned short *, unsigned short,...);
    363232signed int __sync_lock_test_and_set(volatile signed int *, signed int,...);
    364 signed int __sync_lock_test_and_set_4(volatile signed int *, signed int,...);
    365233unsigned int __sync_lock_test_and_set(volatile unsigned int *, unsigned int,...);
    366 unsigned int __sync_lock_test_and_set_4(volatile unsigned int *, unsigned int,...);
     234signed long int __sync_lock_test_and_set(volatile signed long int *, signed long int,...);
     235unsigned long int __sync_lock_test_and_set(volatile unsigned long int *, unsigned long int,...);
    367236signed long long int __sync_lock_test_and_set(volatile signed long long int *, signed long long int,...);
    368 signed long long int __sync_lock_test_and_set_8(volatile signed long long int *, signed long long int,...);
    369237unsigned long long int __sync_lock_test_and_set(volatile unsigned long long int *, unsigned long long int,...);
    370 unsigned long long int __sync_lock_test_and_set_8(volatile unsigned long long int *, unsigned long long int,...);
    371238#if defined(__SIZEOF_INT128__)
    372239signed __int128 __sync_lock_test_and_set(volatile signed __int128 *, signed __int128,...);
    373 signed __int128 __sync_lock_test_and_set_16(volatile signed __int128 *, signed __int128,...);
    374240unsigned __int128 __sync_lock_test_and_set(volatile unsigned __int128 *, unsigned __int128,...);
    375 unsigned __int128 __sync_lock_test_and_set_16(volatile unsigned __int128 *, unsigned __int128,...);
    376241#endif
    377242
    378243void __sync_lock_release(volatile char *,...);
    379 void __sync_lock_release_1(volatile char *,...);
    380244void __sync_lock_release(volatile signed char *,...);
    381 void __sync_lock_release_1(volatile signed char *,...);
    382245void __sync_lock_release(volatile unsigned char *,...);
    383 void __sync_lock_release_1(volatile unsigned char *,...);
    384246void __sync_lock_release(volatile signed short *,...);
    385 void __sync_lock_release_2(volatile signed short *,...);
    386247void __sync_lock_release(volatile unsigned short *,...);
    387 void __sync_lock_release_2(volatile unsigned short *,...);
    388248void __sync_lock_release(volatile signed int *,...);
    389 void __sync_lock_release_4(volatile signed int *,...);
    390249void __sync_lock_release(volatile unsigned int *,...);
    391 void __sync_lock_release_4(volatile unsigned int *,...);
     250void __sync_lock_release(volatile signed long int *,...);
     251void __sync_lock_release(volatile unsigned long int *,...);
    392252void __sync_lock_release(volatile signed long long int *,...);
    393 void __sync_lock_release_8(volatile signed long long int *,...);
    394253void __sync_lock_release(volatile unsigned long long int *,...);
    395 void __sync_lock_release_8(volatile unsigned long long int *,...);
    396254#if defined(__SIZEOF_INT128__)
    397255void __sync_lock_release(volatile signed __int128 *,...);
    398 void __sync_lock_release_16(volatile signed __int128 *,...);
    399256void __sync_lock_release(volatile unsigned __int128 *,...);
    400 void __sync_lock_release_16(volatile unsigned __int128 *,...);
    401257#endif
    402258
     
    414270_Bool __atomic_test_and_set(volatile signed int *, int);
    415271_Bool __atomic_test_and_set(volatile unsigned int *, int);
     272_Bool __atomic_test_and_set(volatile signed long int *, int);
     273_Bool __atomic_test_and_set(volatile unsigned long int *, int);
    416274_Bool __atomic_test_and_set(volatile signed long long int *, int);
    417275_Bool __atomic_test_and_set(volatile unsigned long long int *, int);
     
    429287void __atomic_clear(volatile signed int *, int);
    430288void __atomic_clear(volatile unsigned int *, int);
     289void __atomic_clear(volatile signed long int *, int);
     290void __atomic_clear(volatile unsigned long int *, int);
    431291void __atomic_clear(volatile signed long long int *, int);
    432292void __atomic_clear(volatile unsigned long long int *, int);
     
    436296#endif
    437297
     298_Bool __atomic_exchange_n(volatile _Bool *, _Bool, int);
     299void __atomic_exchange(volatile _Bool *, volatile _Bool *, volatile _Bool *, int);
    438300char __atomic_exchange_n(volatile char *, char, int);
    439 char __atomic_exchange_1(volatile char *, char, int);
    440301void __atomic_exchange(volatile char *, volatile char *, volatile char *, int);
    441302signed char __atomic_exchange_n(volatile signed char *, signed char, int);
    442 signed char __atomic_exchange_1(volatile signed char *, signed char, int);
    443303void __atomic_exchange(volatile signed char *, volatile signed char *, volatile signed char *, int);
    444304unsigned char __atomic_exchange_n(volatile unsigned char *, unsigned char, int);
    445 unsigned char __atomic_exchange_1(volatile unsigned char *, unsigned char, int);
    446305void __atomic_exchange(volatile unsigned char *, volatile unsigned char *, volatile unsigned char *, int);
    447306signed short __atomic_exchange_n(volatile signed short *, signed short, int);
    448 signed short __atomic_exchange_2(volatile signed short *, signed short, int);
    449307void __atomic_exchange(volatile signed short *, volatile signed short *, volatile signed short *, int);
    450308unsigned short __atomic_exchange_n(volatile unsigned short *, unsigned short, int);
    451 unsigned short __atomic_exchange_2(volatile unsigned short *, unsigned short, int);
    452309void __atomic_exchange(volatile unsigned short *, volatile unsigned short *, volatile unsigned short *, int);
    453310signed int __atomic_exchange_n(volatile signed int *, signed int, int);
    454 signed int __atomic_exchange_4(volatile signed int *, signed int, int);
    455311void __atomic_exchange(volatile signed int *, volatile signed int *, volatile signed int *, int);
    456312unsigned int __atomic_exchange_n(volatile unsigned int *, unsigned int, int);
    457 unsigned int __atomic_exchange_4(volatile unsigned int *, unsigned int, int);
    458313void __atomic_exchange(volatile unsigned int *, volatile unsigned int *, volatile unsigned int *, int);
     314signed long int __atomic_exchange_n(volatile signed long int *, signed long int, int);
     315void __atomic_exchange(volatile signed long int *, volatile signed long int *, volatile signed long int *, int);
     316unsigned long int __atomic_exchange_n(volatile unsigned long int *, unsigned long int, int);
     317void __atomic_exchange(volatile unsigned long int *, volatile unsigned long int *, volatile unsigned long int *, int);
    459318signed long long int __atomic_exchange_n(volatile signed long long int *, signed long long int, int);
    460 signed long long int __atomic_exchange_8(volatile signed long long int *, signed long long int, int);
    461319void __atomic_exchange(volatile signed long long int *, volatile signed long long int *, volatile signed long long int *, int);
    462320unsigned long long int __atomic_exchange_n(volatile unsigned long long int *, unsigned long long int, int);
    463 unsigned long long int __atomic_exchange_8(volatile unsigned long long int *, unsigned long long int, int);
    464321void __atomic_exchange(volatile unsigned long long int *, volatile unsigned long long int *, volatile unsigned long long int *, int);
    465322#if defined(__SIZEOF_INT128__)
    466323signed __int128 __atomic_exchange_n(volatile signed __int128 *, signed __int128, int);
    467 signed __int128 __atomic_exchange_16(volatile signed __int128 *, signed __int128, int);
    468324void __atomic_exchange(volatile signed __int128 *, volatile signed __int128 *, volatile signed __int128 *, int);
    469325unsigned __int128 __atomic_exchange_n(volatile unsigned __int128 *, unsigned __int128, int);
    470 unsigned __int128 __atomic_exchange_16(volatile unsigned __int128 *, unsigned __int128, int);
    471326void __atomic_exchange(volatile unsigned __int128 *, volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    472327#endif
     
    477332void __atomic_load(const volatile _Bool *, volatile _Bool *, int);
    478333char __atomic_load_n(const volatile char *, int);
    479 char __atomic_load_1(const volatile char *, int);
    480334void __atomic_load(const volatile char *, volatile char *, int);
    481335signed char __atomic_load_n(const volatile signed char *, int);
    482 signed char __atomic_load_1(const volatile signed char *, int);
    483336void __atomic_load(const volatile signed char *, volatile signed char *, int);
    484337unsigned char __atomic_load_n(const volatile unsigned char *, int);
    485 unsigned char __atomic_load_1(const volatile unsigned char *, int);
    486338void __atomic_load(const volatile unsigned char *, volatile unsigned char *, int);
    487339signed short __atomic_load_n(const volatile signed short *, int);
    488 signed short __atomic_load_2(const volatile signed short *, int);
    489340void __atomic_load(const volatile signed short *, volatile signed short *, int);
    490341unsigned short __atomic_load_n(const volatile unsigned short *, int);
    491 unsigned short __atomic_load_2(const volatile unsigned short *, int);
    492342void __atomic_load(const volatile unsigned short *, volatile unsigned short *, int);
    493343signed int __atomic_load_n(const volatile signed int *, int);
    494 signed int __atomic_load_4(const volatile signed int *, int);
    495344void __atomic_load(const volatile signed int *, volatile signed int *, int);
    496345unsigned int __atomic_load_n(const volatile unsigned int *, int);
    497 unsigned int __atomic_load_4(const volatile unsigned int *, int);
    498346void __atomic_load(const volatile unsigned int *, volatile unsigned int *, int);
     347signed long int __atomic_load_n(const volatile signed long int *, int);
     348void __atomic_load(const volatile signed long int *, volatile signed long int *, int);
     349unsigned long int __atomic_load_n(const volatile unsigned long int *, int);
     350void __atomic_load(const volatile unsigned long int *, volatile unsigned long int *, int);
    499351signed long long int __atomic_load_n(const volatile signed long long int *, int);
    500 signed long long int __atomic_load_8(const volatile signed long long int *, int);
    501352void __atomic_load(const volatile signed long long int *, volatile signed long long int *, int);
    502353unsigned long long int __atomic_load_n(const volatile unsigned long long int *, int);
    503 unsigned long long int __atomic_load_8(const volatile unsigned long long int *, int);
    504354void __atomic_load(const volatile unsigned long long int *, volatile unsigned long long int *, int);
    505355#if defined(__SIZEOF_INT128__)
    506356signed __int128 __atomic_load_n(const volatile signed __int128 *, int);
    507 signed __int128 __atomic_load_16(const volatile signed __int128 *, int);
    508357void __atomic_load(const volatile signed __int128 *, volatile signed __int128 *, int);
    509358unsigned __int128 __atomic_load_n(const volatile unsigned __int128 *, int);
    510 unsigned __int128 __atomic_load_16(const volatile unsigned __int128 *, int);
    511359void __atomic_load(const volatile unsigned __int128 *, volatile unsigned __int128 *, int);
    512360#endif
     
    515363
    516364_Bool __atomic_compare_exchange_n(volatile char *, char *, char, _Bool, int, int);
    517 _Bool __atomic_compare_exchange_1(volatile char *, char *, char, _Bool, int, int);
    518365_Bool __atomic_compare_exchange  (volatile char *, char *, char *, _Bool, int, int);
    519366_Bool __atomic_compare_exchange_n(volatile signed char *, signed char *, signed char, _Bool, int, int);
    520 _Bool __atomic_compare_exchange_1(volatile signed char *, signed char *, signed char, _Bool, int, int);
    521367_Bool __atomic_compare_exchange  (volatile signed char *, signed char *, signed char *, _Bool, int, int);
    522368_Bool __atomic_compare_exchange_n(volatile unsigned char *, unsigned char *, unsigned char, _Bool, int, int);
    523 _Bool __atomic_compare_exchange_1(volatile unsigned char *, unsigned char *, unsigned char, _Bool, int, int);
    524369_Bool __atomic_compare_exchange  (volatile unsigned char *, unsigned char *, unsigned char *, _Bool, int, int);
    525370_Bool __atomic_compare_exchange_n(volatile signed short *, signed short *, signed short, _Bool, int, int);
    526 _Bool __atomic_compare_exchange_2(volatile signed short *, signed short *, signed short, _Bool, int, int);
    527371_Bool __atomic_compare_exchange  (volatile signed short *, signed short *, signed short *, _Bool, int, int);
    528372_Bool __atomic_compare_exchange_n(volatile unsigned short *, unsigned short *, unsigned short, _Bool, int, int);
    529 _Bool __atomic_compare_exchange_2(volatile unsigned short *, unsigned short *, unsigned short, _Bool, int, int);
    530373_Bool __atomic_compare_exchange  (volatile unsigned short *, unsigned short *, unsigned short *, _Bool, int, int);
    531374_Bool __atomic_compare_exchange_n(volatile signed int *, signed int *, signed int, _Bool, int, int);
    532 _Bool __atomic_compare_exchange_4(volatile signed int *, signed int *, signed int, _Bool, int, int);
    533375_Bool __atomic_compare_exchange  (volatile signed int *, signed int *, signed int *, _Bool, int, int);
    534376_Bool __atomic_compare_exchange_n(volatile unsigned int *, unsigned int *, unsigned int, _Bool, int, int);
    535 _Bool __atomic_compare_exchange_4(volatile unsigned int *, unsigned int *, unsigned int, _Bool, int, int);
    536377_Bool __atomic_compare_exchange  (volatile unsigned int *, unsigned int *, unsigned int *, _Bool, int, int);
     378_Bool __atomic_compare_exchange_n(volatile signed long int *, signed long int *, signed long int, _Bool, int, int);
     379_Bool __atomic_compare_exchange  (volatile signed long int *, signed long int *, signed long int *, _Bool, int, int);
     380_Bool __atomic_compare_exchange_n(volatile unsigned long int *, unsigned long int *, unsigned long int, _Bool, int, int);
     381_Bool __atomic_compare_exchange  (volatile unsigned long int *, unsigned long int *, unsigned long int *, _Bool, int, int);
    537382_Bool __atomic_compare_exchange_n(volatile signed long long int *, signed long long int *, signed long long int, _Bool, int, int);
    538 _Bool __atomic_compare_exchange_8(volatile signed long long int *, signed long long int *, signed long long int, _Bool, int, int);
    539383_Bool __atomic_compare_exchange  (volatile signed long long int *, signed long long int *, signed long long int *, _Bool, int, int);
    540384_Bool __atomic_compare_exchange_n(volatile unsigned long long int *, unsigned long long int *, unsigned long long int, _Bool, int, int);
    541 _Bool __atomic_compare_exchange_8(volatile unsigned long long int *, unsigned long long int *, unsigned long long int, _Bool, int, int);
    542385_Bool __atomic_compare_exchange  (volatile unsigned long long int *, unsigned long long int *, unsigned long long int *, _Bool, int, int);
    543386#if defined(__SIZEOF_INT128__)
    544387_Bool __atomic_compare_exchange_n (volatile signed __int128 *, signed __int128 *, signed __int128, _Bool, int, int);
    545 _Bool __atomic_compare_exchange_16(volatile signed __int128 *, signed __int128 *, signed __int128, _Bool, int, int);
    546388_Bool __atomic_compare_exchange   (volatile signed __int128 *, signed __int128 *, signed __int128 *, _Bool, int, int);
    547389_Bool __atomic_compare_exchange_n (volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128, _Bool, int, int);
    548 _Bool __atomic_compare_exchange_16(volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128, _Bool, int, int);
    549390_Bool __atomic_compare_exchange   (volatile unsigned __int128 *, unsigned __int128 *, unsigned __int128 *, _Bool, int, int);
    550391#endif
     
    555396void __atomic_store(volatile _Bool *, _Bool *, int);
    556397void __atomic_store_n(volatile char *, char, int);
    557 void __atomic_store_1(volatile char *, char, int);
    558398void __atomic_store(volatile char *, char *, int);
    559399void __atomic_store_n(volatile signed char *, signed char, int);
    560 void __atomic_store_1(volatile signed char *, signed char, int);
    561400void __atomic_store(volatile signed char *, signed char *, int);
    562401void __atomic_store_n(volatile unsigned char *, unsigned char, int);
    563 void __atomic_store_1(volatile unsigned char *, unsigned char, int);
    564402void __atomic_store(volatile unsigned char *, unsigned char *, int);
    565403void __atomic_store_n(volatile signed short *, signed short, int);
    566 void __atomic_store_2(volatile signed short *, signed short, int);
    567404void __atomic_store(volatile signed short *, signed short *, int);
    568405void __atomic_store_n(volatile unsigned short *, unsigned short, int);
    569 void __atomic_store_2(volatile unsigned short *, unsigned short, int);
    570406void __atomic_store(volatile unsigned short *, unsigned short *, int);
    571407void __atomic_store_n(volatile signed int *, signed int, int);
    572 void __atomic_store_4(volatile signed int *, signed int, int);
    573408void __atomic_store(volatile signed int *, signed int *, int);
    574409void __atomic_store_n(volatile unsigned int *, unsigned int, int);
    575 void __atomic_store_4(volatile unsigned int *, unsigned int, int);
    576410void __atomic_store(volatile unsigned int *, unsigned int *, int);
     411void __atomic_store_n(volatile signed long int *, signed long int, int);
     412void __atomic_store(volatile signed long int *, signed long int *, int);
     413void __atomic_store_n(volatile unsigned long int *, unsigned long int, int);
     414void __atomic_store(volatile unsigned long int *, unsigned long int *, int);
    577415void __atomic_store_n(volatile signed long long int *, signed long long int, int);
    578 void __atomic_store_8(volatile signed long long int *, signed long long int, int);
    579416void __atomic_store(volatile signed long long int *, signed long long int *, int);
    580417void __atomic_store_n(volatile unsigned long long int *, unsigned long long int, int);
    581 void __atomic_store_8(volatile unsigned long long int *, unsigned long long int, int);
    582418void __atomic_store(volatile unsigned long long int *, unsigned long long int *, int);
    583419#if defined(__SIZEOF_INT128__)
    584420void __atomic_store_n(volatile signed __int128 *, signed __int128, int);
    585 void __atomic_store_16(volatile signed __int128 *, signed __int128, int);
    586421void __atomic_store(volatile signed __int128 *, signed __int128 *, int);
    587422void __atomic_store_n(volatile unsigned __int128 *, unsigned __int128, int);
    588 void __atomic_store_16(volatile unsigned __int128 *, unsigned __int128, int);
    589423void __atomic_store(volatile unsigned __int128 *, unsigned __int128 *, int);
    590424#endif
     
    593427
    594428char __atomic_add_fetch  (volatile char *, char, int);
    595 char __atomic_add_fetch_1(volatile char *, char, int);
    596429signed char __atomic_add_fetch  (volatile signed char *, signed char, int);
    597 signed char __atomic_add_fetch_1(volatile signed char *, signed char, int);
    598430unsigned char __atomic_add_fetch  (volatile unsigned char *, unsigned char, int);
    599 unsigned char __atomic_add_fetch_1(volatile unsigned char *, unsigned char, int);
    600431signed short __atomic_add_fetch  (volatile signed short *, signed short, int);
    601 signed short __atomic_add_fetch_2(volatile signed short *, signed short, int);
    602432unsigned short __atomic_add_fetch  (volatile unsigned short *, unsigned short, int);
    603 unsigned short __atomic_add_fetch_2(volatile unsigned short *, unsigned short, int);
    604433signed int __atomic_add_fetch  (volatile signed int *, signed int, int);
    605 signed int __atomic_add_fetch_4(volatile signed int *, signed int, int);
    606434unsigned int __atomic_add_fetch  (volatile unsigned int *, unsigned int, int);
    607 unsigned int __atomic_add_fetch_4(volatile unsigned int *, unsigned int, int);
     435signed long int __atomic_add_fetch  (volatile signed long int *, signed long int, int);
     436unsigned long int __atomic_add_fetch  (volatile unsigned long int *, unsigned long int, int);
    608437signed long long int __atomic_add_fetch  (volatile signed long long int *, signed long long int, int);
    609 signed long long int __atomic_add_fetch_8(volatile signed long long int *, signed long long int, int);
    610438unsigned long long int __atomic_add_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    611 unsigned long long int __atomic_add_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    612439#if defined(__SIZEOF_INT128__)
    613440signed __int128 __atomic_add_fetch   (volatile signed __int128 *, signed __int128, int);
    614 signed __int128 __atomic_add_fetch_16(volatile signed __int128 *, signed __int128, int);
    615441unsigned __int128 __atomic_add_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    616 unsigned __int128 __atomic_add_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    617442#endif
    618443
    619444char __atomic_sub_fetch  (volatile char *, char, int);
    620 char __atomic_sub_fetch_1(volatile char *, char, int);
    621445signed char __atomic_sub_fetch  (volatile signed char *, signed char, int);
    622 signed char __atomic_sub_fetch_1(volatile signed char *, signed char, int);
    623446unsigned char __atomic_sub_fetch  (volatile unsigned char *, unsigned char, int);
    624 unsigned char __atomic_sub_fetch_1(volatile unsigned char *, unsigned char, int);
    625447signed short __atomic_sub_fetch  (volatile signed short *, signed short, int);
    626 signed short __atomic_sub_fetch_2(volatile signed short *, signed short, int);
    627448unsigned short __atomic_sub_fetch  (volatile unsigned short *, unsigned short, int);
    628 unsigned short __atomic_sub_fetch_2(volatile unsigned short *, unsigned short, int);
    629449signed int __atomic_sub_fetch  (volatile signed int *, signed int, int);
    630 signed int __atomic_sub_fetch_4(volatile signed int *, signed int, int);
    631450unsigned int __atomic_sub_fetch  (volatile unsigned int *, unsigned int, int);
    632 unsigned int __atomic_sub_fetch_4(volatile unsigned int *, unsigned int, int);
     451signed long long int __atomic_sub_fetch  (volatile signed long int *, signed long int, int);
     452unsigned long long int __atomic_sub_fetch  (volatile unsigned long int *, unsigned long int, int);
    633453signed long long int __atomic_sub_fetch  (volatile signed long long int *, signed long long int, int);
    634 signed long long int __atomic_sub_fetch_8(volatile signed long long int *, signed long long int, int);
    635454unsigned long long int __atomic_sub_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    636 unsigned long long int __atomic_sub_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    637455#if defined(__SIZEOF_INT128__)
    638456signed __int128 __atomic_sub_fetch   (volatile signed __int128 *, signed __int128, int);
    639 signed __int128 __atomic_sub_fetch_16(volatile signed __int128 *, signed __int128, int);
    640457unsigned __int128 __atomic_sub_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    641 unsigned __int128 __atomic_sub_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    642458#endif
    643459
    644460char __atomic_and_fetch  (volatile char *, char, int);
    645 char __atomic_and_fetch_1(volatile char *, char, int);
    646461signed char __atomic_and_fetch  (volatile signed char *, signed char, int);
    647 signed char __atomic_and_fetch_1(volatile signed char *, signed char, int);
    648462unsigned char __atomic_and_fetch  (volatile unsigned char *, unsigned char, int);
    649 unsigned char __atomic_and_fetch_1(volatile unsigned char *, unsigned char, int);
    650463signed short __atomic_and_fetch  (volatile signed short *, signed short, int);
    651 signed short __atomic_and_fetch_2(volatile signed short *, signed short, int);
    652464unsigned short __atomic_and_fetch  (volatile unsigned short *, unsigned short, int);
    653 unsigned short __atomic_and_fetch_2(volatile unsigned short *, unsigned short, int);
    654465signed int __atomic_and_fetch  (volatile signed int *, signed int, int);
    655 signed int __atomic_and_fetch_4(volatile signed int *, signed int, int);
    656466unsigned int __atomic_and_fetch  (volatile unsigned int *, unsigned int, int);
    657 unsigned int __atomic_and_fetch_4(volatile unsigned int *, unsigned int, int);
     467signed long int __atomic_and_fetch  (volatile signed long int *, signed long int, int);
     468unsigned long int __atomic_and_fetch  (volatile unsigned long int *, unsigned long int, int);
    658469signed long long int __atomic_and_fetch  (volatile signed long long int *, signed long long int, int);
    659 signed long long int __atomic_and_fetch_8(volatile signed long long int *, signed long long int, int);
    660470unsigned long long int __atomic_and_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    661 unsigned long long int __atomic_and_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    662471#if defined(__SIZEOF_INT128__)
    663472signed __int128 __atomic_and_fetch   (volatile signed __int128 *, signed __int128, int);
    664 signed __int128 __atomic_and_fetch_16(volatile signed __int128 *, signed __int128, int);
    665473unsigned __int128 __atomic_and_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    666 unsigned __int128 __atomic_and_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    667474#endif
    668475
    669476char __atomic_nand_fetch  (volatile char *, char, int);
    670 char __atomic_nand_fetch_1(volatile char *, char, int);
    671477signed char __atomic_nand_fetch  (volatile signed char *, signed char, int);
    672 signed char __atomic_nand_fetch_1(volatile signed char *, signed char, int);
    673478unsigned char __atomic_nand_fetch  (volatile unsigned char *, unsigned char, int);
    674 unsigned char __atomic_nand_fetch_1(volatile unsigned char *, unsigned char, int);
    675479signed short __atomic_nand_fetch  (volatile signed short *, signed short, int);
    676 signed short __atomic_nand_fetch_2(volatile signed short *, signed short, int);
    677480unsigned short __atomic_nand_fetch  (volatile unsigned short *, unsigned short, int);
    678 unsigned short __atomic_nand_fetch_2(volatile unsigned short *, unsigned short, int);
    679481signed int __atomic_nand_fetch  (volatile signed int *, signed int, int);
    680 signed int __atomic_nand_fetch_4(volatile signed int *, signed int, int);
    681482unsigned int __atomic_nand_fetch  (volatile unsigned int *, unsigned int, int);
    682 unsigned int __atomic_nand_fetch_4(volatile unsigned int *, unsigned int, int);
     483signed long int __atomic_nand_fetch  (volatile signed long int *, signed long int, int);
     484unsigned long int __atomic_nand_fetch  (volatile unsigned long int *, unsigned long int, int);
    683485signed long long int __atomic_nand_fetch  (volatile signed long long int *, signed long long int, int);
    684 signed long long int __atomic_nand_fetch_8(volatile signed long long int *, signed long long int, int);
    685486unsigned long long int __atomic_nand_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    686 unsigned long long int __atomic_nand_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    687487#if defined(__SIZEOF_INT128__)
    688488signed __int128 __atomic_nand_fetch   (volatile signed __int128 *, signed __int128, int);
    689 signed __int128 __atomic_nand_fetch_16(volatile signed __int128 *, signed __int128, int);
    690489unsigned __int128 __atomic_nand_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    691 unsigned __int128 __atomic_nand_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    692490#endif
    693491
    694492char __atomic_xor_fetch  (volatile char *, char, int);
    695 char __atomic_xor_fetch_1(volatile char *, char, int);
    696493signed char __atomic_xor_fetch  (volatile signed char *, signed char, int);
    697 signed char __atomic_xor_fetch_1(volatile signed char *, signed char, int);
    698494unsigned char __atomic_xor_fetch  (volatile unsigned char *, unsigned char, int);
    699 unsigned char __atomic_xor_fetch_1(volatile unsigned char *, unsigned char, int);
    700495signed short __atomic_xor_fetch  (volatile signed short *, signed short, int);
    701 signed short __atomic_xor_fetch_2(volatile signed short *, signed short, int);
    702496unsigned short __atomic_xor_fetch  (volatile unsigned short *, unsigned short, int);
    703 unsigned short __atomic_xor_fetch_2(volatile unsigned short *, unsigned short, int);
    704497signed int __atomic_xor_fetch  (volatile signed int *, signed int, int);
    705 signed int __atomic_xor_fetch_4(volatile signed int *, signed int, int);
    706498unsigned int __atomic_xor_fetch  (volatile unsigned int *, unsigned int, int);
    707 unsigned int __atomic_xor_fetch_4(volatile unsigned int *, unsigned int, int);
     499signed long int __atomic_xor_fetch  (volatile signed long int *, signed long int, int);
     500unsigned long int __atomic_xor_fetch  (volatile unsigned long int *, unsigned long int, int);
    708501signed long long int __atomic_xor_fetch  (volatile signed long long int *, signed long long int, int);
    709 signed long long int __atomic_xor_fetch_8(volatile signed long long int *, signed long long int, int);
    710502unsigned long long int __atomic_xor_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    711 unsigned long long int __atomic_xor_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    712503#if defined(__SIZEOF_INT128__)
    713504signed __int128 __atomic_xor_fetch   (volatile signed __int128 *, signed __int128, int);
    714 signed __int128 __atomic_xor_fetch_16(volatile signed __int128 *, signed __int128, int);
    715505unsigned __int128 __atomic_xor_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    716 unsigned __int128 __atomic_xor_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    717506#endif
    718507
    719508char __atomic_or_fetch  (volatile char *, char, int);
    720 char __atomic_or_fetch_1(volatile char *, char, int);
    721509signed char __atomic_or_fetch  (volatile signed char *, signed char, int);
    722 signed char __atomic_or_fetch_1(volatile signed char *, signed char, int);
    723510unsigned char __atomic_or_fetch  (volatile unsigned char *, unsigned char, int);
    724 unsigned char __atomic_or_fetch_1(volatile unsigned char *, unsigned char, int);
    725511signed short __atomic_or_fetch  (volatile signed short *, signed short, int);
    726 signed short __atomic_or_fetch_2(volatile signed short *, signed short, int);
    727512unsigned short __atomic_or_fetch  (volatile unsigned short *, unsigned short, int);
    728 unsigned short __atomic_or_fetch_2(volatile unsigned short *, unsigned short, int);
    729513signed int __atomic_or_fetch  (volatile signed int *, signed int, int);
    730 signed int __atomic_or_fetch_4(volatile signed int *, signed int, int);
    731514unsigned int __atomic_or_fetch  (volatile unsigned int *, unsigned int, int);
    732 unsigned int __atomic_or_fetch_4(volatile unsigned int *, unsigned int, int);
     515signed long int __atomic_or_fetch  (volatile signed long int *, signed long int, int);
     516unsigned long int __atomic_or_fetch  (volatile unsigned long int *, unsigned long int, int);
    733517signed long long int __atomic_or_fetch  (volatile signed long long int *, signed long long int, int);
    734 signed long long int __atomic_or_fetch_8(volatile signed long long int *, signed long long int, int);
    735518unsigned long long int __atomic_or_fetch  (volatile unsigned long long int *, unsigned long long int, int);
    736 unsigned long long int __atomic_or_fetch_8(volatile unsigned long long int *, unsigned long long int, int);
    737519#if defined(__SIZEOF_INT128__)
    738520signed __int128 __atomic_or_fetch   (volatile signed __int128 *, signed __int128, int);
    739 signed __int128 __atomic_or_fetch_16(volatile signed __int128 *, signed __int128, int);
    740521unsigned __int128 __atomic_or_fetch   (volatile unsigned __int128 *, unsigned __int128, int);
    741 unsigned __int128 __atomic_or_fetch_16(volatile unsigned __int128 *, unsigned __int128, int);
    742522#endif
    743523
    744524char __atomic_fetch_add  (volatile char *, char, int);
    745 char __atomic_fetch_add_1(volatile char *, char, int);
    746525signed char __atomic_fetch_add  (volatile signed char *, signed char, int);
    747 signed char __atomic_fetch_add_1(volatile signed char *, signed char, int);
    748526unsigned char __atomic_fetch_add  (volatile unsigned char *, unsigned char, int);
    749 unsigned char __atomic_fetch_add_1(volatile unsigned char *, unsigned char, int);
    750527signed short __atomic_fetch_add  (volatile signed short *, signed short, int);
    751 signed short __atomic_fetch_add_2(volatile signed short *, signed short, int);
    752528unsigned short __atomic_fetch_add  (volatile unsigned short *, unsigned short, int);
    753 unsigned short __atomic_fetch_add_2(volatile unsigned short *, unsigned short, int);
    754529signed int __atomic_fetch_add  (volatile signed int *, signed int, int);
    755 signed int __atomic_fetch_add_4(volatile signed int *, signed int, int);
    756530unsigned int __atomic_fetch_add  (volatile unsigned int *, unsigned int, int);
    757 unsigned int __atomic_fetch_add_4(volatile unsigned int *, unsigned int, int);
     531signed long int __atomic_fetch_add  (volatile signed long int *, signed long int, int);
     532unsigned long int __atomic_fetch_add  (volatile unsigned long int *, unsigned long int, int);
    758533signed long long int __atomic_fetch_add  (volatile signed long long int *, signed long long int, int);
    759 signed long long int __atomic_fetch_add_8(volatile signed long long int *, signed long long int, int);
    760534unsigned long long int __atomic_fetch_add  (volatile unsigned long long int *, unsigned long long int, int);
    761 unsigned long long int __atomic_fetch_add_8(volatile unsigned long long int *, unsigned long long int, int);
    762535#if defined(__SIZEOF_INT128__)
    763536signed __int128 __atomic_fetch_add   (volatile signed __int128 *, signed __int128, int);
    764 signed __int128 __atomic_fetch_add_16(volatile signed __int128 *, signed __int128, int);
    765537unsigned __int128 __atomic_fetch_add   (volatile unsigned __int128 *, unsigned __int128, int);
    766 unsigned __int128 __atomic_fetch_add_16(volatile unsigned __int128 *, unsigned __int128, int);
    767538#endif
    768539
    769540char __atomic_fetch_sub  (volatile char *, char, int);
    770 char __atomic_fetch_sub_1(volatile char *, char, int);
    771541signed char __atomic_fetch_sub  (volatile signed char *, signed char, int);
    772 signed char __atomic_fetch_sub_1(volatile signed char *, signed char, int);
    773542unsigned char __atomic_fetch_sub  (volatile unsigned char *, unsigned char, int);
    774 unsigned char __atomic_fetch_sub_1(volatile unsigned char *, unsigned char, int);
    775543signed short __atomic_fetch_sub  (volatile signed short *, signed short, int);
    776 signed short __atomic_fetch_sub_2(volatile signed short *, signed short, int);
    777544unsigned short __atomic_fetch_sub  (volatile unsigned short *, unsigned short, int);
    778 unsigned short __atomic_fetch_sub_2(volatile unsigned short *, unsigned short, int);
    779545signed int __atomic_fetch_sub  (volatile signed int *, signed int, int);
    780 signed int __atomic_fetch_sub_4(volatile signed int *, signed int, int);
    781546unsigned int __atomic_fetch_sub  (volatile unsigned int *, unsigned int, int);
    782 unsigned int __atomic_fetch_sub_4(volatile unsigned int *, unsigned int, int);
     547signed long int __atomic_fetch_sub  (volatile signed long int *, signed long int, int);
     548unsigned long int __atomic_fetch_sub  (volatile unsigned long int *, unsigned long int, int);
    783549signed long long int __atomic_fetch_sub  (volatile signed long long int *, signed long long int, int);
    784 signed long long int __atomic_fetch_sub_8(volatile signed long long int *, signed long long int, int);
    785550unsigned long long int __atomic_fetch_sub  (volatile unsigned long long int *, unsigned long long int, int);
    786 unsigned long long int __atomic_fetch_sub_8(volatile unsigned long long int *, unsigned long long int, int);
    787551#if defined(__SIZEOF_INT128__)
    788552signed __int128 __atomic_fetch_sub   (volatile signed  __int128 *, signed __int128, int);
    789 signed __int128 __atomic_fetch_sub_16(volatile signed  __int128 *, signed __int128, int);
    790553unsigned __int128 __atomic_fetch_sub   (volatile unsigned  __int128 *, unsigned __int128, int);
    791 unsigned __int128 __atomic_fetch_sub_16(volatile unsigned  __int128 *, unsigned __int128, int);
    792554#endif
    793555
    794556char __atomic_fetch_and  (volatile char *, char, int);
    795 char __atomic_fetch_and_1(volatile char *, char, int);
    796557signed char __atomic_fetch_and  (volatile signed char *, signed char, int);
    797 signed char __atomic_fetch_and_1(volatile signed char *, signed char, int);
    798558unsigned char __atomic_fetch_and  (volatile unsigned char *, unsigned char, int);
    799 unsigned char __atomic_fetch_and_1(volatile unsigned char *, unsigned char, int);
    800559signed short __atomic_fetch_and  (volatile signed short *, signed short, int);
    801 signed short __atomic_fetch_and_2(volatile signed short *, signed short, int);
    802560unsigned short __atomic_fetch_and  (volatile unsigned short *, unsigned short, int);
    803 unsigned short __atomic_fetch_and_2(volatile unsigned short *, unsigned short, int);
    804561signed int __atomic_fetch_and  (volatile signed int *, signed int, int);
    805 signed int __atomic_fetch_and_4(volatile signed int *, signed int, int);
    806562unsigned int __atomic_fetch_and  (volatile unsigned int *, unsigned int, int);
    807 unsigned int __atomic_fetch_and_4(volatile unsigned int *, unsigned int, int);
     563signed long int __atomic_fetch_and  (volatile signed long int *, signed long int, int);
     564unsigned long int __atomic_fetch_and  (volatile unsigned long int *, unsigned long int, int);
    808565signed long long int __atomic_fetch_and  (volatile signed long long int *, signed long long int, int);
    809 signed long long int __atomic_fetch_and_8(volatile signed long long int *, signed long long int, int);
    810566unsigned long long int __atomic_fetch_and  (volatile unsigned long long int *, unsigned long long int, int);
    811 unsigned long long int __atomic_fetch_and_8(volatile unsigned long long int *, unsigned long long int, int);
    812567#if defined(__SIZEOF_INT128__)
    813568signed __int128 __atomic_fetch_and   (volatile signed __int128 *, signed __int128, int);
    814 signed __int128 __atomic_fetch_and_16(volatile signed __int128 *, signed __int128, int);
    815569unsigned __int128 __atomic_fetch_and   (volatile unsigned __int128 *, unsigned __int128, int);
    816 unsigned __int128 __atomic_fetch_and_16(volatile unsigned __int128 *, unsigned __int128, int);
    817570#endif
    818571
    819572char __atomic_fetch_nand  (volatile char *, char, int);
    820 char __atomic_fetch_nand_1(volatile char *, char, int);
    821573signed char __atomic_fetch_nand  (volatile signed char *, signed char, int);
    822 signed char __atomic_fetch_nand_1(volatile signed char *, signed char, int);
    823574unsigned char __atomic_fetch_nand  (volatile unsigned char *, unsigned char, int);
    824 unsigned char __atomic_fetch_nand_1(volatile unsigned char *, unsigned char, int);
    825575signed short __atomic_fetch_nand  (volatile signed short *, signed short, int);
    826 signed short __atomic_fetch_nand_2(volatile signed short *, signed short, int);
    827576unsigned short __atomic_fetch_nand  (volatile unsigned short *, unsigned short, int);
    828 unsigned short __atomic_fetch_nand_2(volatile unsigned short *, unsigned short, int);
    829577signed int __atomic_fetch_nand  (volatile signed int *, signed int, int);
    830 signed int __atomic_fetch_nand_4(volatile signed int *, signed int, int);
    831578unsigned int __atomic_fetch_nand  (volatile unsigned int *, unsigned int, int);
    832 unsigned int __atomic_fetch_nand_4(volatile unsigned int *, unsigned int, int);
     579signed long int __atomic_fetch_nand  (volatile signed long int *, signed long int, int);
     580unsigned long int __atomic_fetch_nand  (volatile unsigned long int *, unsigned long int, int);
    833581signed long long int __atomic_fetch_nand  (volatile signed long long int *, signed long long int, int);
    834 signed long long int __atomic_fetch_nand_8(volatile signed long long int *, signed long long int, int);
    835582unsigned long long int __atomic_fetch_nand  (volatile unsigned long long int *, unsigned long long int, int);
    836 unsigned long long int __atomic_fetch_nand_8(volatile unsigned long long int *, unsigned long long int, int);
    837583#if defined(__SIZEOF_INT128__)
    838584signed __int128 __atomic_fetch_nand   (volatile signed __int128 *, signed __int128, int);
    839 signed __int128 __atomic_fetch_nand_16(volatile signed __int128 *, signed __int128, int);
    840585unsigned __int128 __atomic_fetch_nand   (volatile unsigned __int128 *, unsigned __int128, int);
    841 unsigned __int128 __atomic_fetch_nand_16(volatile unsigned __int128 *, unsigned __int128, int);
    842586#endif
    843587
    844588char __atomic_fetch_xor  (volatile char *, char, int);
    845 char __atomic_fetch_xor_1(volatile char *, char, int);
    846589signed char __atomic_fetch_xor  (volatile signed char *, signed char, int);
    847 signed char __atomic_fetch_xor_1(volatile signed char *, signed char, int);
    848590unsigned char __atomic_fetch_xor  (volatile unsigned char *, unsigned char, int);
    849 unsigned char __atomic_fetch_xor_1(volatile unsigned char *, unsigned char, int);
    850591signed short __atomic_fetch_xor  (volatile signed short *, signed short, int);
    851 signed short __atomic_fetch_xor_2(volatile signed short *, signed short, int);
    852592unsigned short __atomic_fetch_xor  (volatile unsigned short *, unsigned short, int);
    853 unsigned short __atomic_fetch_xor_2(volatile unsigned short *, unsigned short, int);
    854593signed int __atomic_fetch_xor  (volatile signed int *, signed int, int);
    855 signed int __atomic_fetch_xor_4(volatile signed int *, signed int, int);
    856594unsigned int __atomic_fetch_xor  (volatile unsigned int *, unsigned int, int);
    857 unsigned int __atomic_fetch_xor_4(volatile unsigned int *, unsigned int, int);
     595signed long int __atomic_fetch_xor  (volatile signed long int *, signed long int, int);
     596unsigned long int __atomic_fetch_xor  (volatile unsigned long int *, unsigned long int, int);
    858597signed long long int __atomic_fetch_xor  (volatile signed long long int *, signed long long int, int);
    859 signed long long int __atomic_fetch_xor_8(volatile signed long long int *, signed long long int, int);
    860598unsigned long long int __atomic_fetch_xor  (volatile unsigned long long int *, unsigned long long int, int);
    861 unsigned long long int __atomic_fetch_xor_8(volatile unsigned long long int *, unsigned long long int, int);
    862599#if defined(__SIZEOF_INT128__)
    863600signed __int128 __atomic_fetch_xor   (volatile signed __int128 *, signed __int128, int);
    864 signed __int128 __atomic_fetch_xor_16(volatile signed __int128 *, signed __int128, int);
    865601unsigned __int128 __atomic_fetch_xor   (volatile unsigned __int128 *, unsigned __int128, int);
    866 unsigned __int128 __atomic_fetch_xor_16(volatile unsigned __int128 *, unsigned __int128, int);
    867602#endif
    868603
    869604char __atomic_fetch_or  (volatile char *, char, int);
    870 char __atomic_fetch_or_1(volatile char *, char, int);
    871605signed char __atomic_fetch_or  (volatile signed char *, signed char, int);
    872 signed char __atomic_fetch_or_1(volatile signed char *, signed char, int);
    873606unsigned char __atomic_fetch_or  (volatile unsigned char *, unsigned char, int);
    874 unsigned char __atomic_fetch_or_1(volatile unsigned char *, unsigned char, int);
    875607signed short __atomic_fetch_or  (volatile signed short *, signed short, int);
    876 signed short __atomic_fetch_or_2(volatile signed short *, signed short, int);
    877608unsigned short __atomic_fetch_or  (volatile unsigned short *, unsigned short, int);
    878 unsigned short __atomic_fetch_or_2(volatile unsigned short *, unsigned short, int);
    879609signed int __atomic_fetch_or  (volatile signed int *, signed int, int);
    880 signed int __atomic_fetch_or_4(volatile signed int *, signed int, int);
    881610unsigned int __atomic_fetch_or  (volatile unsigned int *, unsigned int, int);
    882 unsigned int __atomic_fetch_or_4(volatile unsigned int *, unsigned int, int);
     611signed long int __atomic_fetch_or  (volatile signed long int *, signed long int, int);
     612unsigned long int __atomic_fetch_or  (volatile unsigned long int *, unsigned long int, int);
    883613signed long long int __atomic_fetch_or  (volatile signed long long int *, signed long long int, int);
    884 signed long long int __atomic_fetch_or_8(volatile signed long long int *, signed long long int, int);
    885614unsigned long long int __atomic_fetch_or  (volatile unsigned long long int *, unsigned long long int, int);
    886 unsigned long long int __atomic_fetch_or_8(volatile unsigned long long int *, unsigned long long int, int);
    887615#if defined(__SIZEOF_INT128__)
    888616signed __int128 __atomic_fetch_or   (volatile signed __int128 *, signed __int128, int);
    889 signed __int128 __atomic_fetch_or_16(volatile signed __int128 *, signed __int128, int);
    890617unsigned __int128 __atomic_fetch_or   (volatile unsigned __int128 *, unsigned __int128, int);
    891 unsigned __int128 __atomic_fetch_or_16(volatile unsigned __int128 *, unsigned __int128, int);
    892618#endif
    893619
  • libcfa/src/Makefile.am

    r9fb8f01 r3d5701e  
    3232# use -no-include-stdhdr to prevent rebuild cycles
    3333# The built sources must not depend on the installed headers
    34 AM_CFAFLAGS = -quiet -in-tree -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    35 AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC @ARCH_FLAGS@ @CONFIG_CFLAGS@
     34AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
     35AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3636AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
    3737CFACC = @CFACC@
     
    6464# add dependency of cfa files
    6565libobjs = $(addsuffix .lo, $(basename $(filter %.cfa,$(libsrc))))
    66 $(libobjs) : @CFACC@ @CFACPP@ prelude.cfa
     66$(libobjs) : @LOCAL_CFACC@ @CFACPP@ prelude.cfa
    6767
    6868thread_libobjs = $(addsuffix .lo, $(basename $(filter %.cfa,$(thread_libsrc))))
    69 $(thread_libobjs) : @CFACC@ @CFACPP@ prelude.cfa
     69$(thread_libobjs) : @LOCAL_CFACC@ @CFACPP@ prelude.cfa
    7070
    7171
     
    8686
    8787
    88 prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    89         ${AM_V_GEN}$(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
     88if ENABLE_DISTCC
    9089
    91 prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
     90../prelude/distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ ../prelude/gcc-builtins.cf ../prelude/builtins.cf ../prelude/extras.cf ../prelude/prelude.cfa ../prelude/bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     91        @+make -C ../prelude distribution
     92
     93prelude.o prelude.lo $(libobjs) $(thread_libobjs) : ../prelude/distribution
     94
     95endif ENABLE_DISTCC
     96
     97prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
     98        ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}
     99
     100prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
    92101        ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
    93         $(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    94 
     102        $(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}
    95103
    96104#----------------------------------------------------------------------------------------------------------------
  • libcfa/src/Makefile.in

    r9fb8f01 r3d5701e  
    284284CFACC = @CFACC@
    285285CFACPP = @CFACPP@
     286CFADIR_HASH = @CFADIR_HASH@
    286287CFA_BINDIR = @CFA_BINDIR@
    287288CFA_INCDIR = @CFA_INCDIR@
     
    327328LIPO = @LIPO@
    328329LN_S = @LN_S@
     330LOCAL_CC1 = @LOCAL_CC1@
     331LOCAL_CFACC = @LOCAL_CFACC@
    329332LTLIBOBJS = @LTLIBOBJS@
    330333LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
     
    413416LTCFACOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
    414417        $(LIBTOOLFLAGS) --mode=compile $(CFACC) $(DEFS) \
    415         $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(CFAFLAGS) \
    416         $(AM_CFLAGS) $(CFLAGS)
     418        $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CFAFLAGS) $(AM_CFLAGS) $(CFAFLAGS) $(CFLAGS)
    417419
    418420AM_V_CFA = $(am__v_CFA_@AM_V@)
     
    420422am__v_CFA_0 = @echo "  CFA     " $@;
    421423am__v_CFA_1 =
    422 AM_V_JAVAC = $(am__v_JAVAC_@AM_V@)
    423 am__v_JAVAC_ = $(am__v_JAVAC_@AM_DEFAULT_V@)
    424 am__v_JAVAC_0 = @echo "  JAVAC   " $@;
    425 am__v_JAVAC_1 =
    426 AM_V_GOC = $(am__v_GOC_@AM_V@)
    427 am__v_GOC_ = $(am__v_GOC_@AM_DEFAULT_V@)
    428 am__v_GOC_0 = @echo "  GOC     " $@;
    429 am__v_GOC_1 =
    430424UPPCC = u++
    431425UPPCOMPILE = $(UPPCC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_UPPFLAGS) $(UPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_CFLAGS) $(CFLAGS)
     
    434428am__v_UPP_0 = @echo "  UPP     " $@;
    435429am__v_UPP_1 =
     430AM_V_GOC = $(am__v_GOC_@AM_V@)
     431am__v_GOC_ = $(am__v_GOC_@AM_DEFAULT_V@)
     432am__v_GOC_0 = @echo "  GOC     " $@;
     433am__v_GOC_1 =
     434AM_V_RUST = $(am__v_RUST_@AM_V@)
     435am__v_RUST_ = $(am__v_RUST_@AM_DEFAULT_V@)
     436am__v_RUST_0 = @echo "  RUST     " $@;
     437am__v_RUST_1 =
     438AM_V_NODEJS = $(am__v_NODEJS_@AM_V@)
     439am__v_NODEJS_ = $(am__v_NODEJS_@AM_DEFAULT_V@)
     440am__v_NODEJS_0 = @echo "  NODEJS     " $@;
     441am__v_NODEJS_1 =
     442AM_V_JAVAC = $(am__v_JAVAC_@AM_V@)
     443am__v_JAVAC_ = $(am__v_JAVAC_@AM_DEFAULT_V@)
     444am__v_JAVAC_0 = @echo "  JAVAC   " $@;
     445am__v_JAVAC_1 =
    436446lib_LTLIBRARIES = libcfa.la libcfathread.la
    437447gdbwaittarget = ""
     
    441451# use -no-include-stdhdr to prevent rebuild cycles
    442452# The built sources must not depend on the installed headers
    443 AM_CFAFLAGS = -quiet -in-tree -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
    444 AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC @ARCH_FLAGS@ @CONFIG_CFLAGS@
     453AM_CFAFLAGS = -quiet -cfalib -I$(srcdir)/stdhdr $(if $(findstring ${gdbwaittarget}, ${@}), -XCFA --gdb) @CONFIG_CFAFLAGS@
     454AM_CFLAGS = -g -Wall -Wno-unused-function -fPIC -pthread @ARCH_FLAGS@ @CONFIG_CFLAGS@
    445455AM_CCASFLAGS = -g -Wall -Wno-unused-function @ARCH_FLAGS@ @CONFIG_CFLAGS@
    446456@BUILDLIB_FALSE@headers_nosrc =
     
    937947        $(LTCFACOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
    938948        $(am__mv) $$depbase.Tpo $$depbase.Plo
    939 $(libobjs) : @CFACC@ @CFACPP@ prelude.cfa
    940 $(thread_libobjs) : @CFACC@ @CFACPP@ prelude.cfa
     949$(libobjs) : @LOCAL_CFACC@ @CFACPP@ prelude.cfa
     950$(thread_libobjs) : @LOCAL_CFACC@ @CFACPP@ prelude.cfa
    941951
    942952-include $(libdeps)
     
    944954-include $(thread_libdeps)
    945955
    946 prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
    947         ${AM_V_GEN}$(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
    948 
    949 prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @CFACC@ @CFACPP@
     956@ENABLE_DISTCC_TRUE@../prelude/distribution: @LOCAL_CFACC@ @LOCAL_CC1@ @CFACPP@ ../prelude/gcc-builtins.cf ../prelude/builtins.cf ../prelude/extras.cf ../prelude/prelude.cfa ../prelude/bootloader.c $(srcdir)/../../tools/build/push2dist.sh
     957@ENABLE_DISTCC_TRUE@    @+make -C ../prelude distribution
     958
     959@ENABLE_DISTCC_TRUE@prelude.o prelude.lo $(libobjs) $(thread_libobjs) : ../prelude/distribution
     960
     961prelude.o : prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
     962        ${AM_V_GEN}$(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}
     963
     964prelude.lo: prelude.cfa extras.cf gcc-builtins.cf builtins.cf @LOCAL_CFACC@ @CFACPP@
    950965        ${AM_V_GEN}$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile \
    951         $(CFACOMPILE) -quiet -in-tree -XCFA -l ${<} -c -o ${@}
     966        $(CFACOMPILE) -quiet -XCFA -l ${<} -c -o ${@}
    952967
    953968#----------------------------------------------------------------------------------------------------------------
  • libcfa/src/assert.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 20 15:10:26 2017
    13 // Update Count     : 2
     12// Last Modified On : Tue Feb  4 13:00:18 2020
     13// Update Count     : 6
    1414//
    1515
     
    1717#include <stdarg.h>                                                             // varargs
    1818#include <stdio.h>                                                              // fprintf
     19#include <unistd.h>                                                             // STDERR_FILENO
    1920#include "bits/debug.hfa"
    2021
     
    2526
    2627        // called by macro assert in assert.h
    27         void __assert_fail( const char *assertion, const char *file, unsigned int line, const char *function ) {
    28                 __cfaabi_dbg_bits_print_safe( CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
     28        void __assert_fail( const char assertion[], const char file[], unsigned int line, const char function[] ) {
     29                __cfaabi_bits_print_safe( STDERR_FILENO, CFA_ASSERT_FMT ".\n", assertion, __progname, function, line, file );
    2930                abort();
    3031        }
    3132
    3233        // called by macro assertf
    33         void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) {
    34                 __cfaabi_dbg_bits_acquire();
    35                 __cfaabi_dbg_bits_print_nolock( CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
     34        void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) {
     35                __cfaabi_bits_acquire();
     36                __cfaabi_bits_print_nolock( STDERR_FILENO, CFA_ASSERT_FMT ": ", assertion, __progname, function, line, file );
    3637
    3738                va_list args;
    3839                va_start( args, fmt );
    39                 __cfaabi_dbg_bits_print_vararg( fmt, args );
     40                __cfaabi_bits_print_vararg( STDERR_FILENO, fmt, args );
    4041                va_end( args );
    4142
    42                 __cfaabi_dbg_bits_print_nolock( "\n" );
    43                 __cfaabi_dbg_bits_release();
     43                __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
     44                __cfaabi_bits_release();
    4445                abort();
    4546        }
  • libcfa/src/bits/align.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 21 23:05:35 2017
    13 // Update Count     : 2
     12// Last Modified On : Sat Nov 16 18:58:22 2019
     13// Update Count     : 3
    1414//
    1515// This  library is free  software; you  can redistribute  it and/or  modify it
     
    3333
    3434// Minimum size used to align memory boundaries for memory allocations.
    35 #define libAlign() (sizeof(double))
     35//#define libAlign() (sizeof(double))
     36// gcc-7 uses xmms instructions, which require 16 byte alignment.
     37#define libAlign() (16)
    3638
    3739// Check for power of 2
  • libcfa/src/bits/containers.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Oct 31 16:38:50 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 26 08:52:20 2019
    13 // Update Count     : 4
     12// Last Modified On : Wed Jan 15 07:42:35 2020
     13// Update Count     : 28
    1414
    1515#pragma once
     
    4444
    4545        forall(dtype T | sized(T))
    46         static inline T& ?[?]( __small_array(T) & this, __lock_size_t idx) {
     46        static inline T & ?[?]( __small_array(T) & this, __lock_size_t idx ) {
    4747                return ((typeof(this.data))this.data)[idx];
    4848        }
    4949
    5050        forall(dtype T | sized(T))
    51         static inline T& ?[?]( const __small_array(T) & this, __lock_size_t idx) {
     51        static inline T & ?[?]( const __small_array(T) & this, __lock_size_t idx ) {
    5252                return ((typeof(this.data))this.data)[idx];
    5353        }
    5454
     55        forall(dtype T)
     56        static inline T * begin( const __small_array(T) & this ) {
     57                return ((typeof(this.data))this.data);
     58        }
     59
    5560        forall(dtype T | sized(T))
    56         static inline T* begin( const __small_array(T) & this ) {
    57                 return ((typeof(this.data))this.data);
    58         }
    59 
    60         forall(dtype T | sized(T))
    61         static inline T* end( const __small_array(T) & this ) {
     61        static inline T * end( const __small_array(T) & this ) {
    6262                return ((typeof(this.data))this.data) + this.size;
    6363        }
     
    7070#ifdef __cforall
    7171        trait is_node(dtype T) {
    72                 T*& get_next( T& );
     72                T *& get_next( T & );
    7373        };
    7474#endif
     
    9797        forall(dtype T)
    9898        static inline void ?{}( __stack(T) & this ) {
    99                 (this.top){ NULL };
    100         }
    101 
    102         forall(dtype T | is_node(T) | sized(T))
    103         static inline void push( __stack(T) & this, T * val ) {
    104                 verify( !get_next( *val ) );
    105                 get_next( *val ) = this.top;
    106                 this.top = val;
    107         }
    108 
    109         forall(dtype T | is_node(T) | sized(T))
    110         static inline T * pop( __stack(T) & this ) {
    111                 T * top = this.top;
    112                 if( top ) {
    113                         this.top = get_next( *top );
    114                         get_next( *top ) = NULL;
    115                 }
    116                 return top;
    117         }
    118 
    119         forall(dtype T | is_node(T))
    120         static inline int ?!=?( const __stack(T) & this, __attribute__((unused)) zero_t zero ) {
    121                 return this.top != 0;
     99                (this.top){ 0p };
     100        }
     101
     102        static inline forall( dtype T | is_node(T) ) {
     103                void push( __stack(T) & this, T * val ) {
     104                        verify( !get_next( *val ) );
     105                        get_next( *val ) = this.top;
     106                        this.top = val;
     107                }
     108
     109                T * pop( __stack(T) & this ) {
     110                        T * top = this.top;
     111                        if( top ) {
     112                                this.top = get_next( *top );
     113                                get_next( *top ) = 0p;
     114                        }
     115                        return top;
     116                }
     117
     118                int ?!=?( const __stack(T) & this, __attribute__((unused)) zero_t zero ) {
     119                        return this.top != 0;
     120                }
    122121        }
    123122#endif
     
    145144
    146145#ifdef __cforall
    147 
    148         forall(dtype T)
    149         static inline void ?{}( __queue(T) & this ) with( this ) {
    150                 head{ NULL };
    151                 tail{ &head };
    152         }
    153 
    154         forall(dtype T | is_node(T) | sized(T))
    155         static inline void append( __queue(T) & this, T * val ) with( this ) {
    156                 verify(tail != NULL);
    157                 *tail = val;
    158                 tail = &get_next( *val );
    159         }
    160 
    161         forall(dtype T | is_node(T) | sized(T))
    162         static inline T * pop_head( __queue(T) & this ) {
    163                 T * head = this.head;
    164                 if( head ) {
    165                         this.head = get_next( *head );
    166                         if( !get_next( *head ) ) {
    167                                 this.tail = &this.head;
    168                         }
    169                         get_next( *head ) = NULL;
    170                 }
    171                 return head;
    172         }
    173 
    174         forall(dtype T | is_node(T) | sized(T))
    175         static inline T * remove( __queue(T) & this, T ** it ) with( this ) {
    176                 T * val = *it;
    177                 verify( val );
    178 
    179                 (*it) = get_next( *val );
    180 
    181                 if( tail == &get_next( *val ) ) {
    182                         tail = it;
    183                 }
    184 
    185                 get_next( *val ) = NULL;
    186 
    187                 verify( (head == NULL) == (&head == tail) );
    188                 verify( *tail == NULL );
    189                 return val;
    190         }
    191 
    192         forall(dtype T | is_node(T))
    193         static inline int ?!=?( const __queue(T) & this, __attribute__((unused)) zero_t zero ) {
    194                 return this.head != 0;
     146        static inline forall( dtype T | is_node(T) ) {
     147                void ?{}( __queue(T) & this ) with( this ) {
     148                        head{ 1p };
     149                        tail{ &head };
     150                        verify(*tail == 1p);
     151                }
     152
     153                void append( __queue(T) & this, T * val ) with( this ) {
     154                        verify(tail != 0p);
     155                        verify(*tail == 1p);
     156                        *tail = val;
     157                        tail = &get_next( *val );
     158                        *tail = 1p;
     159                }
     160
     161                T * pop_head( __queue(T) & this ) {
     162                        verify(*this.tail == 1p);
     163                        T * head = this.head;
     164                        if( head != 1p ) {
     165                                this.head = get_next( *head );
     166                                if( get_next( *head ) == 1p ) {
     167                                        this.tail = &this.head;
     168                                }
     169                                get_next( *head ) = 0p;
     170                                verify(*this.tail == 1p);
     171                                return head;
     172                        }
     173                        verify(*this.tail == 1p);
     174                        return 0p;
     175                }
     176
     177                T * remove( __queue(T) & this, T ** it ) with( this ) {
     178                        T * val = *it;
     179                        verify( val );
     180
     181                        (*it) = get_next( *val );
     182
     183                        if( tail == &get_next( *val ) ) {
     184                                tail = it;
     185                        }
     186
     187                        get_next( *val ) = 0p;
     188
     189                        verify( (head == 1p) == (&head == tail) );
     190                        verify( *tail == 1p );
     191                        return val;
     192                }
     193
     194                int ?!=?( const __queue(T) & this, __attribute__((unused)) zero_t zero ) {
     195                        return this.head != 0;
     196                }
    195197        }
    196198#endif
     
    223225
    224226#ifdef __cforall
    225 
    226         forall(dtype T | sized(T))
     227        forall(dtype T )
    227228        static inline [void] ?{}( __dllist(T) & this, * [T * & next, T * & prev] ( T & ) __get ) {
    228                 this.head{ NULL };
     229                this.head{ 0p };
    229230                this.__get = __get;
    230231        }
     
    232233        #define next 0
    233234        #define prev 1
    234         forall(dtype T | sized(T))
    235         static inline void push_front( __dllist(T) & this, T & node ) with( this ) {
    236                 verify(__get);
    237                 if ( head ) {
    238                         __get( node ).next = head;
    239                         __get( node ).prev = __get( *head ).prev;
    240                         // inserted node must be consistent before it is seen
     235        static inline forall(dtype T) {
     236                void push_front( __dllist(T) & this, T & node ) with( this ) {
     237                        verify(__get);
     238                        if ( head ) {
     239                                __get( node ).next = head;
     240                                __get( node ).prev = __get( *head ).prev;
     241                                // inserted node must be consistent before it is seen
     242                                // prevent code movement across barrier
     243                                asm( "" : : : "memory" );
     244                                __get( *head ).prev = &node;
     245                                T & _prev = *__get( node ).prev;
     246                                __get( _prev ).next = &node;
     247                        } else {
     248                                __get( node ).next = &node;
     249                                __get( node ).prev = &node;
     250                        }
     251
    241252                        // prevent code movement across barrier
    242253                        asm( "" : : : "memory" );
    243                         __get( *head ).prev = &node;
    244                         T & _prev = *__get( node ).prev;
    245                         __get( _prev ).next = &node;
    246                 }
    247                 else {
    248                         __get( node ).next = &node;
    249                         __get( node ).prev = &node;
    250                 }
    251 
    252                 // prevent code movement across barrier
    253                 asm( "" : : : "memory" );
    254                 head = &node;
    255         }
    256 
    257         forall(dtype T | sized(T))
    258         static inline void remove( __dllist(T) & this, T & node ) with( this ) {
    259                 verify(__get);
    260                 if ( &node == head ) {
    261                         if ( __get( *head ).next == head ) {
    262                                 head = NULL;
    263                         }
    264                         else {
    265                                 head = __get( *head ).next;
    266                         }
    267                 }
    268                 __get( *__get( node ).next ).prev = __get( node ).prev;
    269                 __get( *__get( node ).prev ).next = __get( node ).next;
    270                 __get( node ).next = NULL;
    271                 __get( node ).prev = NULL;
    272         }
    273 
    274         forall(dtype T | sized(T))
    275         static inline int ?!=?( const __dllist(T) & this, __attribute__((unused)) zero_t zero ) {
    276                 return this.head != 0;
     254                        head = &node;
     255                }
     256
     257                void remove( __dllist(T) & this, T & node ) with( this ) {
     258                        verify(__get);
     259                        if ( &node == head ) {
     260                                if ( __get( *head ).next == head ) {
     261                                        head = 0p;
     262                                } else {
     263                                        head = __get( *head ).next;
     264                                }
     265                        }
     266                        __get( *__get( node ).next ).prev = __get( node ).prev;
     267                        __get( *__get( node ).prev ).next = __get( node ).next;
     268                        __get( node ).next = 0p;
     269                        __get( node ).prev = 0p;
     270                }
     271
     272                int ?!=?( const __dllist(T) & this, __attribute__((unused)) zero_t zero ) {
     273                        return this.head != 0;
     274                }
    277275        }
    278276        #undef next
     
    286284
    287285#endif
     286
     287// Local Variables: //
     288// tab-width: 4 //
     289// End: //
  • libcfa/src/bits/debug.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Mar 30 12:30:01 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 22:17:35 2019
    13 // Update Count     : 4
     12// Last Modified On : Tue Feb  4 13:03:16 2020
     13// Update Count     : 11
    1414//
    1515
     
    2727
    2828extern "C" {
    29 
    30         void __cfaabi_dbg_bits_write( const char *in_buffer, int len ) {
     29        void __cfaabi_bits_write( int fd, const char in_buffer[], int len ) {
    3130                // ensure all data is written
    3231                for ( int count = 0, retcode; count < len; count += retcode ) {
     
    3433
    3534                        for ( ;; ) {
    36                                 retcode = write( STDERR_FILENO, in_buffer, len - count );
     35                                retcode = write( fd, in_buffer, len - count );
    3736
    3837                                // not a timer interrupt ?
     
    4443        }
    4544
    46         void __cfaabi_dbg_bits_acquire() __attribute__((__weak__)) {}
    47         void __cfaabi_dbg_bits_release() __attribute__((__weak__)) {}
     45        void __cfaabi_bits_acquire() __attribute__((__weak__)) {}
     46        void __cfaabi_bits_release() __attribute__((__weak__)) {}
    4847
    49         void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     48        void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
    5049                va_list args;
    5150
    5251                va_start( args, fmt );
    53                 __cfaabi_dbg_bits_acquire();
     52                __cfaabi_bits_acquire();
    5453
    5554                int len = vsnprintf( buffer, buffer_size, fmt, args );
    56                 __cfaabi_dbg_bits_write( buffer, len );
     55                __cfaabi_bits_write( fd, buffer, len );
    5756
    58                 __cfaabi_dbg_bits_release();
     57                __cfaabi_bits_release();
    5958                va_end( args );
    6059        }
    6160
    62         void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) )) {
     61        void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) )) {
    6362                va_list args;
    6463
     
    6665
    6766                int len = vsnprintf( buffer, buffer_size, fmt, args );
    68                 __cfaabi_dbg_bits_write( buffer, len );
     67                __cfaabi_bits_write( fd, buffer, len );
    6968
    7069                va_end( args );
    7170        }
    7271
    73         void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list args ) {
     72        void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list args ) {
    7473                int len = vsnprintf( buffer, buffer_size, fmt, args );
    75                 __cfaabi_dbg_bits_write( buffer, len );
     74                __cfaabi_bits_write( fd, buffer, len );
    7675        }
    7776
    78         void __cfaabi_dbg_bits_print_buffer( char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) )) {
     77        void __cfaabi_bits_print_buffer( int fd, char in_buffer[], int in_buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) )) {
    7978                va_list args;
    8079
     
    8281
    8382                int len = vsnprintf( in_buffer, in_buffer_size, fmt, args );
    84                 __cfaabi_dbg_bits_write( in_buffer, len );
     83                __cfaabi_bits_write( fd, in_buffer, len );
    8584
    8685                va_end( args );
  • libcfa/src/bits/debug.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 12:35:19 2018
    13 // Update Count     : 2
     12// Last Modified On : Tue Feb  4 12:29:21 2020
     13// Update Count     : 9
    1414//
    1515
     
    2121        #define __cfaabi_dbg_ctx __PRETTY_FUNCTION__
    2222        #define __cfaabi_dbg_ctx2 , __PRETTY_FUNCTION__
    23         #define __cfaabi_dbg_ctx_param const char * caller
    24         #define __cfaabi_dbg_ctx_param2 , const char * caller
     23        #define __cfaabi_dbg_ctx_param const char caller[]
     24        #define __cfaabi_dbg_ctx_param2 , const char caller[]
    2525#else
    2626        #define __cfaabi_dbg_debug_do(...)
     
    3838        #include <stdio.h>
    3939
    40       extern void __cfaabi_dbg_bits_write( const char *buffer, int len );
    41       extern void __cfaabi_dbg_bits_acquire();
    42       extern void __cfaabi_dbg_bits_release();
    43       extern void __cfaabi_dbg_bits_print_safe  ( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
    44       extern void __cfaabi_dbg_bits_print_nolock( const char fmt[], ... ) __attribute__(( format(printf, 1, 2) ));
    45       extern void __cfaabi_dbg_bits_print_vararg( const char fmt[], va_list arg );
    46       extern void __cfaabi_dbg_bits_print_buffer( char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 3, 4) ));
     40        extern void __cfaabi_bits_write( int fd, const char buffer[], int len );
     41        extern void __cfaabi_bits_acquire();
     42        extern void __cfaabi_bits_release();
     43        extern void __cfaabi_bits_print_safe  ( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
     44        extern void __cfaabi_bits_print_nolock( int fd, const char fmt[], ... ) __attribute__(( format(printf, 2, 3) ));
     45        extern void __cfaabi_bits_print_vararg( int fd, const char fmt[], va_list arg );
     46        extern void __cfaabi_bits_print_buffer( int fd, char buffer[], int buffer_size, const char fmt[], ... ) __attribute__(( format(printf, 4, 5) ));
    4747#ifdef __cforall
    4848}
     
    5050
    5151#ifdef __CFA_DEBUG_PRINT__
    52         #define __cfaabi_dbg_write( buffer, len )         __cfaabi_dbg_bits_write( buffer, len )
    53         #define __cfaabi_dbg_acquire()                    __cfaabi_dbg_bits_acquire()
    54         #define __cfaabi_dbg_release()                    __cfaabi_dbg_bits_release()
    55         #define __cfaabi_dbg_print_safe(...)              __cfaabi_dbg_bits_print_safe   (__VA_ARGS__)
    56         #define __cfaabi_dbg_print_nolock(...)            __cfaabi_dbg_bits_print_nolock (__VA_ARGS__)
    57         #define __cfaabi_dbg_print_buffer(...)            __cfaabi_dbg_bits_print_buffer (__VA_ARGS__)
    58         #define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
    59         #define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_bits_write( __dbg_text, __dbg_len );
     52        #define __cfaabi_dbg_write( buffer, len )         __cfaabi_bits_write( STDERR_FILENO, buffer, len )
     53        #define __cfaabi_dbg_acquire()                    __cfaabi_bits_acquire()
     54        #define __cfaabi_dbg_release()                    __cfaabi_bits_release()
     55        #define __cfaabi_dbg_print_safe(...)              __cfaabi_bits_print_safe   (__VA_ARGS__)
     56        #define __cfaabi_dbg_print_nolock(...)            __cfaabi_bits_print_nolock (__VA_ARGS__)
     57        #define __cfaabi_dbg_print_buffer(...)            __cfaabi_bits_print_buffer (__VA_ARGS__)
     58        #define __cfaabi_dbg_print_buffer_decl(...)       char __dbg_text[256]; int __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_bits_write( __dbg_text, __dbg_len );
     59        #define __cfaabi_dbg_print_buffer_local(...)      __dbg_len = snprintf( __dbg_text, 256, __VA_ARGS__ ); __cfaabi_dbg_write( __dbg_text, __dbg_len );
    6060#else
    6161        #define __cfaabi_dbg_write(...)               ((void)0)
  • libcfa/src/bits/defs.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Nov  9 13:24:10 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 16:22:41 2018
    13 // Update Count     : 8
     12// Last Modified On : Tue Jan 28 22:38:27 2020
     13// Update Count     : 9
    1414//
    1515
     
    3434
    3535#ifdef __cforall
    36 void abort ( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     36void abort( const char fmt[], ... ) __attribute__ (( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     37void abort( bool signalAbort, const char fmt[], ... ) __attribute__ (( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    3738extern "C" {
    3839#endif
     
    4748#define OPTIONAL_THREAD __attribute__((weak))
    4849#endif
     50
     51static inline long long rdtscl(void) {
     52    unsigned int lo, hi;
     53    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
     54    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
     55}
  • libcfa/src/bits/locks.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Oct 31 15:14:38 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Aug 11 15:42:24 2018
    13 // Update Count     : 10
     12// Last Modified On : Tue Feb  4 13:03:19 2020
     13// Update Count     : 11
    1414//
    1515
     
    5454
    5555                #ifdef __CFA_DEBUG__
    56                         void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name);
     56                        void __cfaabi_dbg_record(__spinlock_t & this, const char prev_name[]);
    5757                #else
    5858                        #define __cfaabi_dbg_record(x, y)
    5959                #endif
    6060        }
    61 
    62         extern void yield( unsigned int );
    6361
    6462        static inline void ?{}( __spinlock_t & this ) {
     
    6866        // Lock the spinlock, return false if already acquired
    6967        static inline bool try_lock  ( __spinlock_t & this __cfaabi_dbg_ctx_param2 ) {
     68                disable_interrupts();
    7069                bool result = (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0);
    7170                if( result ) {
    72                         disable_interrupts();
    7371                        __cfaabi_dbg_record( this, caller );
     72                } else {
     73                        enable_interrupts_noPoll();
    7474                }
    7575                return result;
     
    8383                #endif
    8484
     85                disable_interrupts();
    8586                for ( unsigned int i = 1;; i += 1 ) {
    8687                        if ( (this.lock == 0) && (__atomic_test_and_set( &this.lock, __ATOMIC_ACQUIRE ) == 0) ) break;
     
    9899                        #endif
    99100                }
    100                 disable_interrupts();
    101101                __cfaabi_dbg_record( this, caller );
    102102        }
    103103
    104104        static inline void unlock( __spinlock_t & this ) {
     105                __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    105106                enable_interrupts_noPoll();
    106                 __atomic_clear( &this.lock, __ATOMIC_RELEASE );
    107107        }
    108108
  • libcfa/src/bits/signal.hfa

    r9fb8f01 r3d5701e  
    3737
    3838        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     39        sigemptyset( &act.sa_mask );
     40        sigaddset( &act.sa_mask, SIGALRM );             // disabled during signal handler
     41        sigaddset( &act.sa_mask, SIGUSR1 );
     42        sigaddset( &act.sa_mask, SIGSEGV );
     43        sigaddset( &act.sa_mask, SIGBUS );
     44        sigaddset( &act.sa_mask, SIGILL );
     45        sigaddset( &act.sa_mask, SIGFPE );
     46        sigaddset( &act.sa_mask, SIGHUP );              // revert to default on second delivery
     47        sigaddset( &act.sa_mask, SIGTERM );
     48        sigaddset( &act.sa_mask, SIGINT );
    3949        act.sa_flags = flags;
    4050
    41         if ( sigaction( sig, &act, NULL ) == -1 ) {
     51        if ( sigaction( sig, &act, 0p ) == -1 ) {
    4252                __cfaabi_dbg_print_buffer_decl(
    4353                        " __cfaabi_sigaction( sig:%d, handler:%p, flags:%d ), problem installing signal handler, error(%d) %s.\n",
     
    4555                );
    4656                _exit( EXIT_FAILURE );
    47         }
     57        } // if
    4858}
    49 
    50 // Sigaction wrapper : restore default handler
    51 static void __cfaabi_sigdefault( int sig ) {
    52         struct sigaction act;
    53 
    54         act.sa_handler = SIG_DFL;
    55         act.sa_flags = 0;
    56         sigemptyset( &act.sa_mask );
    57 
    58         if ( sigaction( sig, &act, NULL ) == -1 ) {
    59                 __cfaabi_dbg_print_buffer_decl(
    60                         " __cfaabi_sigdefault( sig:%d ), problem reseting signal handler, error(%d) %s.\n",
    61                         sig, errno, strerror( errno )
    62                 );
    63                 _exit( EXIT_FAILURE );
    64         }
    65 }
  • libcfa/src/clock.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Apr 12 14:36:06 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun 13 21:21:13 2019
    13 // Update Count     : 8
     12// Last Modified On : Mon Jan  6 12:49:58 2020
     13// Update Count     : 9
    1414//
    1515
    1616#include <time.hfa>
    17 
    1817
    1918//######################### C time #########################
     
    2625static inline tm * localtime_r( time_t tp, tm * result ) { return localtime_r( &tp, result ); }
    2726
    28 
    2927//######################### Clock #########################
    3028
    3129struct Clock {                                                                                  // private
    3230        Duration offset;                                                                        // for virtual clock: contains offset from real-time
    33         int clocktype;                                                                          // implementation only -1 (virtual), CLOCK_REALTIME
    3431};
    3532
    3633static inline {
    37         void resetClock( Clock & clk ) with( clk ) {
    38                 clocktype = CLOCK_REALTIME_COARSE;
    39         } // Clock::resetClock
    40 
    4134        void resetClock( Clock & clk, Duration adj ) with( clk ) {
    42                 clocktype = -1;
    4335                offset = adj + __timezone`s;                                    // timezone (global) is (UTC - local time) in seconds
    4436        } // resetClock
    4537
    46         void ?{}( Clock & clk ) { resetClock( clk ); }
    4738        void ?{}( Clock & clk, Duration adj ) { resetClock( clk, adj ); }
    4839
     
    8980                return ret;
    9081        } // getTime
     82
     83        Time getCPUTime() {
     84                timespec ts;
     85                clock_gettime( CLOCK_THREAD_CPUTIME_ID, &ts );
     86                return (Time){ ts };
     87    } // getCPUTime
    9188} // distribution
    9289
  • libcfa/src/concurrency/CtxSwitch-arm.S

    r9fb8f01 r3d5701e  
    1313        .text
    1414        .align  2
    15         .global CtxSwitch
    16         .type   CtxSwitch, %function
     15        .global __cfactx_switch
     16        .type   __cfactx_switch, %function
    1717
    18 CtxSwitch:
     18__cfactx_switch:
    1919        @ save callee-saved registers: r4-r8, r10, r11, r13(sp) (plus r9 depending on platform specification)
    2020        @ I've seen reference to 31 registers on 64-bit, if this is the case, more need to be saved
     
    5252        mov r15, r14
    5353        #endif // R9_SPECIAL
    54        
     54
    5555        .text
    5656        .align  2
    57         .global CtxInvokeStub
    58         .type   CtxInvokeStub, %function
     57        .global __cfactx_invoke_stub
     58        .type   __cfactx_invoke_stub, %function
    5959
    60 CtxInvokeStub:
     60__cfactx_invoke_stub:
    6161        ldmfd r13!, {r0-r1}
    6262        mov r15, r1
  • libcfa/src/concurrency/CtxSwitch-i386.S

    r9fb8f01 r3d5701e  
    4343        .text
    4444        .align 2
    45         .globl CtxSwitch
    46         .type  CtxSwitch, @function
    47 CtxSwitch:
     45        .globl __cfactx_switch
     46        .type  __cfactx_switch, @function
     47__cfactx_switch:
    4848
    4949        // Copy the "from" context argument from the stack to register eax
     
    8383
    8484        ret
    85         .size  CtxSwitch, .-CtxSwitch
     85        .size  __cfactx_switch, .-__cfactx_switch
    8686
    8787// Local Variables: //
  • libcfa/src/concurrency/CtxSwitch-x86_64.S

    r9fb8f01 r3d5701e  
    4444        .text
    4545        .align 2
    46         .globl CtxSwitch
    47         .type  CtxSwitch, @function
    48 CtxSwitch:
     46        .globl __cfactx_switch
     47        .type  __cfactx_switch, @function
     48__cfactx_switch:
    4949
    5050        // Save volatile registers on the stack.
     
    7777
    7878        ret
    79         .size  CtxSwitch, .-CtxSwitch
     79        .size  __cfactx_switch, .-__cfactx_switch
    8080
    8181//-----------------------------------------------------------------------------
     
    8383        .text
    8484        .align 2
    85         .globl CtxInvokeStub
    86         .type    CtxInvokeStub, @function
    87 CtxInvokeStub:
     85        .globl __cfactx_invoke_stub
     86        .type    __cfactx_invoke_stub, @function
     87__cfactx_invoke_stub:
    8888        movq %rbx, %rdi
    89         jmp *%r12
    90         .size  CtxInvokeStub, .-CtxInvokeStub
     89        movq %r12, %rsi
     90        jmp *%r13
     91        .size  __cfactx_invoke_stub, .-__cfactx_invoke_stub
    9192
    9293// Local Variables: //
  • libcfa/src/concurrency/alarm.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Fri Jun 2 11:31:25 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri May 25 06:25:47 2018
    13 // Update Count     : 67
     12// Last Modified On : Sun Jan  5 08:41:36 2020
     13// Update Count     : 69
    1414//
    1515
     
    3939
    4040void __kernel_set_timer( Duration alarm ) {
    41         verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (%jins)", alarm.tv);
    42         setitimer( ITIMER_REAL, &(itimerval){ alarm }, NULL );
     41        verifyf(alarm >= 1`us || alarm == 0, "Setting timer to < 1us (%jins)", alarm`ns);
     42        setitimer( ITIMER_REAL, &(itimerval){ alarm }, 0p );
    4343}
    4444
     
    4747//=============================================================================================
    4848
    49 void ?{}( alarm_node_t & this, thread_desc * thrd, Time alarm, Duration period ) with( this ) {
     49void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period ) with( this ) {
    5050        this.thrd = thrd;
    5151        this.alarm = alarm;
     
    113113                        this->tail = &this->head;
    114114                }
    115                 head->next = NULL;
     115                head->next = 0p;
    116116        }
    117117        verify( validate( this ) );
     
    127127                this->tail = it;
    128128        }
    129         n->next = NULL;
     129        n->next = 0p;
    130130
    131131        verify( validate( this ) );
  • libcfa/src/concurrency/alarm.hfa

    r9fb8f01 r3d5701e  
    2323#include "time.hfa"
    2424
    25 struct thread_desc;
     25struct $thread;
    2626struct processor;
    2727
     
    4343
    4444        union {
    45                 thread_desc * thrd;     // thrd who created event
     45                $thread * thrd; // thrd who created event
    4646                processor * proc;               // proc who created event
    4747        };
     
    5353typedef alarm_node_t ** __alarm_it_t;
    5454
    55 void ?{}( alarm_node_t & this, thread_desc * thrd, Time alarm, Duration period );
     55void ?{}( alarm_node_t & this, $thread * thrd, Time alarm, Duration period );
    5656void ?{}( alarm_node_t & this, processor   * proc, Time alarm, Duration period );
    5757void ^?{}( alarm_node_t & this );
  • libcfa/src/concurrency/coroutine.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 17:20:57 2018
    13 // Update Count     : 9
     12// Last Modified On : Tue Feb  4 12:29:25 2020
     13// Update Count     : 16
    1414//
    1515
     
    3737
    3838extern "C" {
    39         void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     39        void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__));
    4040        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) __attribute__ ((__noreturn__));
    4141        static void _CtxCoroutine_UnwindCleanup(_Unwind_Reason_Code, struct _Unwind_Exception *) {
     
    8989}
    9090
    91 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize ) with( this ) {
    92         (this.context){NULL, NULL};
     91void ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize ) with( this ) {
     92        (this.context){0p, 0p};
    9393        (this.stack){storage, storageSize};
    9494        this.name = name;
    9595        state = Start;
    96         starter = NULL;
    97         last = NULL;
    98         cancellation = NULL;
    99 }
    100 
    101 void ^?{}(coroutine_desc& this) {
     96        starter = 0p;
     97        last = 0p;
     98        cancellation = 0p;
     99}
     100
     101void ^?{}($coroutine& this) {
    102102        if(this.state != Halted && this.state != Start && this.state != Primed) {
    103                 coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    104                 coroutine_desc * dst = &this;
     103                $coroutine * src = TL_GET( this_thread )->curr_cor;
     104                $coroutine * dst = &this;
    105105
    106106                struct _Unwind_Exception storage;
     
    115115                }
    116116
    117                 CoroutineCtxSwitch( src, dst );
     117                $ctx_switch( src, dst );
    118118        }
    119119}
     
    123123forall(dtype T | is_coroutine(T))
    124124void prime(T& cor) {
    125         coroutine_desc* this = get_coroutine(cor);
     125        $coroutine* this = get_coroutine(cor);
    126126        assert(this->state == Start);
    127127
     
    131131
    132132[void *, size_t] __stack_alloc( size_t storageSize ) {
    133         static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     133        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    134134        assert(__page_size != 0l);
    135135        size_t size = libCeiling( storageSize, 16 ) + stack_data_size;
     
    157157
    158158void __stack_prepare( __stack_info_t * this, size_t create_size ) {
    159         static const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
     159        const size_t stack_data_size = libCeiling( sizeof(__stack_t), 16 ); // minimum alignment
    160160        bool userStack;
    161161        void * storage;
     
    187187// is not inline (We can't inline Cforall in C)
    188188extern "C" {
    189         void __suspend_internal(void) {
    190                 suspend();
    191         }
    192 
    193         void __leave_coroutine( coroutine_desc * src ) {
    194                 coroutine_desc * starter = src->cancellation != 0 ? src->last : src->starter;
     189        void __cfactx_cor_leave( struct $coroutine * src ) {
     190                $coroutine * starter = src->cancellation != 0 ? src->last : src->starter;
    195191
    196192                src->state = Halted;
     
    205201                        src->name, src, starter->name, starter );
    206202
    207                 CoroutineCtxSwitch( src, starter );
     203                $ctx_switch( src, starter );
     204        }
     205
     206        struct $coroutine * __cfactx_cor_finish(void) {
     207                struct $coroutine * cor = kernelTLS.this_thread->curr_cor;
     208
     209                if(cor->state == Primed) {
     210                        suspend();
     211                }
     212
     213                cor->state = Active;
     214
     215                return cor;
    208216        }
    209217}
  • libcfa/src/concurrency/coroutine.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Nov 28 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 17:49:39 2019
    13 // Update Count     : 9
     12// Last Modified On : Tue Feb  4 12:29:26 2020
     13// Update Count     : 11
    1414//
    1515
     
    2525trait is_coroutine(dtype T) {
    2626      void main(T & this);
    27       coroutine_desc * get_coroutine(T & this);
     27      $coroutine * get_coroutine(T & this);
    2828};
    2929
    30 #define DECL_COROUTINE(X) static inline coroutine_desc* get_coroutine(X& this) { return &this.__cor; } void main(X& this)
     30#define DECL_COROUTINE(X) static inline $coroutine* get_coroutine(X& this) { return &this.__cor; } void main(X& this)
    3131
    3232//-----------------------------------------------------------------------------
     
    3535// void ^?{}( coStack_t & this );
    3636
    37 void ?{}( coroutine_desc & this, const char * name, void * storage, size_t storageSize );
    38 void ^?{}( coroutine_desc & this );
     37void  ?{}( $coroutine & this, const char name[], void * storage, size_t storageSize );
     38void ^?{}( $coroutine & this );
    3939
    40 static inline void ?{}( coroutine_desc & this)                                       { this{ "Anonymous Coroutine", NULL, 0 }; }
    41 static inline void ?{}( coroutine_desc & this, size_t stackSize)                     { this{ "Anonymous Coroutine", NULL, stackSize }; }
    42 static inline void ?{}( coroutine_desc & this, void * storage, size_t storageSize )  { this{ "Anonymous Coroutine", storage, storageSize }; }
    43 static inline void ?{}( coroutine_desc & this, const char * name)                    { this{ name, NULL, 0 }; }
    44 static inline void ?{}( coroutine_desc & this, const char * name, size_t stackSize ) { this{ name, NULL, stackSize }; }
     40static inline void ?{}( $coroutine & this)                                       { this{ "Anonymous Coroutine", 0p, 0 }; }
     41static inline void ?{}( $coroutine & this, size_t stackSize)                     { this{ "Anonymous Coroutine", 0p, stackSize }; }
     42static inline void ?{}( $coroutine & this, void * storage, size_t storageSize )  { this{ "Anonymous Coroutine", storage, storageSize }; }
     43static inline void ?{}( $coroutine & this, const char name[])                    { this{ name, 0p, 0 }; }
     44static inline void ?{}( $coroutine & this, const char name[], size_t stackSize ) { this{ name, 0p, stackSize }; }
    4545
    4646//-----------------------------------------------------------------------------
     
    5454void prime(T & cor);
    5555
    56 static inline struct coroutine_desc * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
     56static inline struct $coroutine * active_coroutine() { return TL_GET( this_thread )->curr_cor; }
    5757
    5858//-----------------------------------------------------------------------------
     
    6161// Start coroutine routines
    6262extern "C" {
    63       forall(dtype T | is_coroutine(T))
    64       void CtxInvokeCoroutine(T * this);
     63        void __cfactx_invoke_coroutine(void (*main)(void *), void * this);
    6564
    66       forall(dtype T | is_coroutine(T))
    67       void CtxStart(T * this, void ( *invoke)(T *));
     65        forall(dtype T)
     66        void __cfactx_start(void (*main)(T &), struct $coroutine * cor, T & this, void (*invoke)(void (*main)(void *), void *));
    6867
    69         extern void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc *) __attribute__ ((__noreturn__));
     68        extern void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine *) __attribute__ ((__noreturn__));
    7069
    71         extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
     70        extern void __cfactx_switch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("__cfactx_switch");
    7271}
    7372
    7473// Private wrappers for context switch and stack creation
    7574// Wrapper for co
    76 static inline void CoroutineCtxSwitch(coroutine_desc* src, coroutine_desc* dst) {
     75static inline void $ctx_switch( $coroutine * src, $coroutine * dst ) __attribute__((nonnull (1, 2))) {
    7776        // set state of current coroutine to inactive
    7877        src->state = src->state == Halted ? Halted : Inactive;
     
    8382        // context switch to specified coroutine
    8483        verify( dst->context.SP );
    85         CtxSwitch( &src->context, &dst->context );
    86         // when CtxSwitch returns we are back in the src coroutine
     84        __cfactx_switch( &src->context, &dst->context );
     85        // when __cfactx_switch returns we are back in the src coroutine
    8786
    8887        // set state of new coroutine to active
    8988        src->state = Active;
    9089
    91         if( unlikely(src->cancellation != NULL) ) {
    92                 _CtxCoroutine_Unwind(src->cancellation, src);
     90        if( unlikely(src->cancellation != 0p) ) {
     91                __cfactx_coroutine_unwind(src->cancellation, src);
    9392        }
    9493}
     
    103102        // will also migrate which means this value will
    104103        // stay in syn with the TLS
    105         coroutine_desc * src = TL_GET( this_thread )->curr_cor;
     104        $coroutine * src = TL_GET( this_thread )->curr_cor;
    106105
    107106        assertf( src->last != 0,
     
    114113                src->name, src, src->last->name, src->last );
    115114
    116         CoroutineCtxSwitch( src, src->last );
     115        $ctx_switch( src, src->last );
    117116}
    118117
     
    125124        // will also migrate which means this value will
    126125        // stay in syn with the TLS
    127         coroutine_desc * src = TL_GET( this_thread )->curr_cor;
    128         coroutine_desc * dst = get_coroutine(cor);
     126        $coroutine * src = TL_GET( this_thread )->curr_cor;
     127        $coroutine * dst = get_coroutine(cor);
    129128
    130         if( unlikely(dst->context.SP == NULL) ) {
     129        if( unlikely(dst->context.SP == 0p) ) {
     130                TL_GET( this_thread )->curr_cor = dst;
    131131                __stack_prepare(&dst->stack, 65000);
    132                 CtxStart(&cor, CtxInvokeCoroutine);
     132                __cfactx_start(main, dst, cor, __cfactx_invoke_coroutine);
     133                TL_GET( this_thread )->curr_cor = src;
    133134        }
    134135
     
    146147
    147148        // always done for performance testing
    148         CoroutineCtxSwitch( src, dst );
     149        $ctx_switch( src, dst );
    149150
    150151        return cor;
    151152}
    152153
    153 static inline void resume(coroutine_desc * dst) {
     154static inline void resume( $coroutine * dst ) __attribute__((nonnull (1))) {
    154155        // optimization : read TLS once and reuse it
    155156        // Safety note: this is preemption safe since if
     
    157158        // will also migrate which means this value will
    158159        // stay in syn with the TLS
    159         coroutine_desc * src = TL_GET( this_thread )->curr_cor;
     160        $coroutine * src = TL_GET( this_thread )->curr_cor;
    160161
    161162        // not resuming self ?
     
    171172
    172173        // always done for performance testing
    173         CoroutineCtxSwitch( src, dst );
     174        $ctx_switch( src, dst );
    174175}
    175176
  • libcfa/src/concurrency/invoke.c

    r9fb8f01 r3d5701e  
    2929// Called from the kernel when starting a coroutine or task so must switch back to user mode.
    3030
    31 extern void __suspend_internal(void);
    32 extern void __leave_coroutine( struct coroutine_desc * );
    33 extern void __finish_creation( struct thread_desc * );
    34 extern void __leave_thread_monitor( struct thread_desc * this );
     31extern struct $coroutine * __cfactx_cor_finish(void);
     32extern void __cfactx_cor_leave ( struct $coroutine * );
     33extern void __cfactx_thrd_leave();
     34
    3535extern void disable_interrupts() OPTIONAL_THREAD;
    3636extern void enable_interrupts( __cfaabi_dbg_ctx_param );
    3737
    38 void CtxInvokeCoroutine(
     38void __cfactx_invoke_coroutine(
    3939        void (*main)(void *),
    40         struct coroutine_desc *(*get_coroutine)(void *),
    4140        void *this
    4241) {
    43         struct coroutine_desc* cor = get_coroutine( this );
     42        // Finish setting up the coroutine by setting its state
     43        struct $coroutine * cor = __cfactx_cor_finish();
    4444
    45         if(cor->state == Primed) {
    46                 __suspend_internal();
    47         }
    48 
    49         cor->state = Active;
    50 
     45        // Call the main of the coroutine
    5146        main( this );
    5247
    5348        //Final suspend, should never return
    54         __leave_coroutine( cor );
     49        __cfactx_cor_leave( cor );
    5550        __cabi_abort( "Resumed dead coroutine" );
    5651}
    5752
    58 static _Unwind_Reason_Code _CtxCoroutine_UnwindStop(
     53static _Unwind_Reason_Code __cfactx_coroutine_unwindstop(
    5954        __attribute((__unused__)) int version,
    6055        _Unwind_Action actions,
     
    6762                // We finished unwinding the coroutine,
    6863                // leave it
    69                 __leave_coroutine( param );
     64                __cfactx_cor_leave( param );
    7065                __cabi_abort( "Resumed dead coroutine" );
    7166        }
     
    7570}
    7671
    77 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) __attribute__ ((__noreturn__));
    78 void _CtxCoroutine_Unwind(struct _Unwind_Exception * storage, struct coroutine_desc * cor) {
    79         _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, _CtxCoroutine_UnwindStop, cor );
     72void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine * cor) __attribute__ ((__noreturn__));
     73void __cfactx_coroutine_unwind(struct _Unwind_Exception * storage, struct $coroutine * cor) {
     74        _Unwind_Reason_Code ret = _Unwind_ForcedUnwind( storage, __cfactx_coroutine_unwindstop, cor );
    8075        printf("UNWIND ERROR %d after force unwind\n", ret);
    8176        abort();
    8277}
    8378
    84 void CtxInvokeThread(
    85         void (*dtor)(void *),
     79void __cfactx_invoke_thread(
    8680        void (*main)(void *),
    87         struct thread_desc *(*get_thread)(void *),
    8881        void *this
    8982) {
    90         // Fetch the thread handle from the user defined thread structure
    91         struct thread_desc* thrd = get_thread( this );
    92 
    93         // First suspend, once the thread arrives here,
    94         // the function pointer to main can be invalidated without risk
    95         __finish_creation( thrd );
    96 
    9783        // Officially start the thread by enabling preemption
    9884        enable_interrupts( __cfaabi_dbg_ctx );
     
    10894        // The order of these 4 operations is very important
    10995        //Final suspend, should never return
    110         __leave_thread_monitor( thrd );
     96        __cfactx_thrd_leave();
    11197        __cabi_abort( "Resumed dead thread" );
    11298}
    11399
    114 
    115 void CtxStart(
     100void __cfactx_start(
    116101        void (*main)(void *),
    117         struct coroutine_desc *(*get_coroutine)(void *),
     102        struct $coroutine * cor,
    118103        void *this,
    119104        void (*invoke)(void *)
    120105) {
    121         struct coroutine_desc * cor = get_coroutine( this );
    122106        struct __stack_t * stack = cor->stack.storage;
    123107
     
    138122
    139123        fs->dummyReturn = NULL;
    140         fs->argument[0] = this;     // argument to invoke
     124        fs->argument[0] = main;     // argument to invoke
     125        fs->argument[1] = this;     // argument to invoke
    141126        fs->rturn = invoke;
    142127
     
    155140
    156141        fs->dummyReturn = NULL;
    157         fs->rturn = CtxInvokeStub;
    158         fs->fixedRegisters[0] = this;
    159         fs->fixedRegisters[1] = invoke;
     142        fs->rturn = __cfactx_invoke_stub;
     143        fs->fixedRegisters[0] = main;
     144        fs->fixedRegisters[1] = this;
     145        fs->fixedRegisters[2] = invoke;
    160146
    161147#elif defined( __ARM_ARCH )
    162 
     148#error ARM needs to be upgrade to use to parameters like X86/X64 (A.K.A. : I broke this and do not know how to fix it)
    163149        struct FakeStack {
    164150                float fpRegs[16];                       // floating point registers
     
    172158        struct FakeStack *fs = (struct FakeStack *)cor->context.SP;
    173159
    174         fs->intRegs[8] = CtxInvokeStub;
     160        fs->intRegs[8] = __cfactx_invoke_stub;
    175161        fs->arg[0] = this;
    176162        fs->arg[1] = invoke;
  • libcfa/src/concurrency/invoke.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jan 17 12:27:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 22 18:19:13 2019
    13 // Update Count     : 40
     12// Last Modified On : Thu Dec  5 16:26:03 2019
     13// Update Count     : 44
    1414//
    1515
     
    4646        #ifdef __cforall
    4747        extern "Cforall" {
    48                 extern thread_local struct KernelThreadData {
    49                         struct thread_desc    * volatile this_thread;
     48                extern __attribute__((aligned(128))) thread_local struct KernelThreadData {
     49                        struct $thread    * volatile this_thread;
    5050                        struct processor      * volatile this_processor;
    5151
     
    5555                                volatile bool in_progress;
    5656                        } preemption_state;
     57
     58                        uint32_t rand_seed;
    5759                } kernelTLS __attribute__ ((tls_model ( "initial-exec" )));
    5860        }
     
    9092        };
    9193
    92         enum coroutine_state { Halted, Start, Inactive, Active, Primed };
    93 
    94         struct coroutine_desc {
    95                 // context that is switch during a CtxSwitch
     94        enum coroutine_state { Halted, Start, Primed, Inactive, Active, Rerun };
     95        enum __Preemption_Reason { __NO_PREEMPTION, __ALARM_PREEMPTION, __POLL_PREEMPTION, __MANUAL_PREEMPTION };
     96
     97        struct $coroutine {
     98                // context that is switch during a __cfactx_switch
    9699                struct __stack_context_t context;
    97100
     
    106109
    107110                // first coroutine to resume this one
    108                 struct coroutine_desc * starter;
     111                struct $coroutine * starter;
    109112
    110113                // last coroutine to resume this one
    111                 struct coroutine_desc * last;
     114                struct $coroutine * last;
    112115
    113116                // If non-null stack must be unwound with this exception
     
    125128        };
    126129
    127         struct monitor_desc {
     130        struct $monitor {
    128131                // spinlock to protect internal data
    129132                struct __spinlock_t lock;
    130133
    131134                // current owner of the monitor
    132                 struct thread_desc * owner;
     135                struct $thread * owner;
    133136
    134137                // queue of threads that are blocked waiting for the monitor
    135                 __queue_t(struct thread_desc) entry_queue;
     138                __queue_t(struct $thread) entry_queue;
    136139
    137140                // stack of conditions to run next once we exit the monitor
     
    150153        struct __monitor_group_t {
    151154                // currently held monitors
    152                 __cfa_anonymous_object( __small_array_t(monitor_desc*) );
     155                __cfa_anonymous_object( __small_array_t($monitor*) );
    153156
    154157                // last function that acquired monitors
     
    156159        };
    157160
    158         struct thread_desc {
     161        struct $thread {
    159162                // Core threading fields
    160                 // context that is switch during a CtxSwitch
     163                // context that is switch during a __cfactx_switch
    161164                struct __stack_context_t context;
    162165
    163166                // current execution status for coroutine
    164                 enum coroutine_state state;
     167                volatile int state;
     168                enum __Preemption_Reason preempted;
    165169
    166170                //SKULLDUGGERY errno is not save in the thread data structure because returnToKernel appears to be the only function to require saving and restoring it
    167171
    168172                // coroutine body used to store context
    169                 struct coroutine_desc  self_cor;
     173                struct $coroutine  self_cor;
    170174
    171175                // current active context
    172                 struct coroutine_desc * curr_cor;
     176                struct $coroutine * curr_cor;
    173177
    174178                // monitor body used for mutual exclusion
    175                 struct monitor_desc    self_mon;
     179                struct $monitor    self_mon;
    176180
    177181                // pointer to monitor with sufficient lifetime for current monitors
    178                 struct monitor_desc *  self_mon_p;
     182                struct $monitor *  self_mon_p;
    179183
    180184                // pointer to the cluster on which the thread is running
     
    186190                // Link lists fields
    187191                // instrusive link field for threads
    188                 struct thread_desc * next;
     192                struct $thread * next;
    189193
    190194                struct {
    191                         struct thread_desc * next;
    192                         struct thread_desc * prev;
     195                        struct $thread * next;
     196                        struct $thread * prev;
    193197                } node;
    194198        };
     
    196200        #ifdef __cforall
    197201        extern "Cforall" {
    198                 static inline thread_desc *& get_next( thread_desc & this ) {
     202                static inline $thread *& get_next( $thread & this ) __attribute__((const)) {
    199203                        return this.next;
    200204                }
    201205
    202                 static inline [thread_desc *&, thread_desc *& ] __get( thread_desc & this ) {
     206                static inline [$thread *&, $thread *& ] __get( $thread & this ) __attribute__((const)) {
    203207                        return this.node.[next, prev];
    204208                }
    205209
    206210                static inline void ?{}(__monitor_group_t & this) {
    207                         (this.data){NULL};
     211                        (this.data){0p};
    208212                        (this.size){0};
    209213                        (this.func){NULL};
    210214                }
    211215
    212                 static inline void ?{}(__monitor_group_t & this, struct monitor_desc ** data, __lock_size_t size, fptr_t func) {
     216                static inline void ?{}(__monitor_group_t & this, struct $monitor ** data, __lock_size_t size, fptr_t func) {
    213217                        (this.data){data};
    214218                        (this.size){size};
     
    216220                }
    217221
    218                 static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) {
     222                static inline bool ?==?( const __monitor_group_t & lhs, const __monitor_group_t & rhs ) __attribute__((const)) {
    219223                        if( (lhs.data != 0) != (rhs.data != 0) ) return false;
    220224                        if( lhs.size != rhs.size ) return false;
     
    250254
    251255        // assembler routines that performs the context switch
    252         extern void CtxInvokeStub( void );
    253         extern void CtxSwitch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("CtxSwitch");
     256        extern void __cfactx_invoke_stub( void );
     257        extern void __cfactx_switch( struct __stack_context_t * from, struct __stack_context_t * to ) asm ("__cfactx_switch");
    254258        // void CtxStore ( void * this ) asm ("CtxStore");
    255259        // void CtxRet   ( void * dst  ) asm ("CtxRet");
  • libcfa/src/concurrency/kernel.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jun 20 17:21:23 2019
    13 // Update Count     : 25
     12// Last Modified On : Tue Feb  4 13:03:15 2020
     13// Update Count     : 58
    1414//
    1515
     
    2626#include <signal.h>
    2727#include <unistd.h>
     28#include <limits.h>                                                                             // PTHREAD_STACK_MIN
     29#include <sys/mman.h>                                                                   // mprotect
    2830}
    2931
     
    4042//-----------------------------------------------------------------------------
    4143// Some assembly required
    42 #if   defined( __i386 )
     44#if defined( __i386 )
    4345        #define CtxGet( ctx )        \
    4446                __asm__ volatile (     \
     
    108110//-----------------------------------------------------------------------------
    109111//Start and stop routine for the kernel, declared first to make sure they run first
    110 static void kernel_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
    111 static void kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
     112static void __kernel_startup (void) __attribute__(( constructor( STARTUP_PRIORITY_KERNEL ) ));
     113static void __kernel_shutdown(void) __attribute__(( destructor ( STARTUP_PRIORITY_KERNEL ) ));
    112114
    113115//-----------------------------------------------------------------------------
     
    115117KERNEL_STORAGE(cluster,         mainCluster);
    116118KERNEL_STORAGE(processor,       mainProcessor);
    117 KERNEL_STORAGE(thread_desc,     mainThread);
     119KERNEL_STORAGE($thread, mainThread);
    118120KERNEL_STORAGE(__stack_t,       mainThreadCtx);
    119121
    120122cluster     * mainCluster;
    121123processor   * mainProcessor;
    122 thread_desc * mainThread;
     124$thread * mainThread;
    123125
    124126extern "C" {
    125 struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
     127        struct { __dllist_t(cluster) list; __spinlock_t lock; } __cfa_dbg_global_clusters;
    126128}
    127129
     
    131133// Global state
    132134thread_local struct KernelThreadData kernelTLS __attribute__ ((tls_model ( "initial-exec" ))) = {
     135        NULL,                                                                                           // cannot use 0p
    133136        NULL,
    134         NULL,
    135         { 1, false, false }
     137        { 1, false, false },
     138        6u //this should be seeded better but due to a bug calling rdtsc doesn't work
    136139};
    137140
     
    139142// Struct to steal stack
    140143struct current_stack_info_t {
    141         __stack_t * storage;            // pointer to stack object
    142         void *base;                             // base of stack
    143         void *limit;                    // stack grows towards stack limit
    144         void *context;                  // address of cfa_context_t
     144        __stack_t * storage;                                                            // pointer to stack object
     145        void * base;                                                                            // base of stack
     146        void * limit;                                                                           // stack grows towards stack limit
     147        void * context;                                                                         // address of cfa_context_t
    145148};
    146149
     
    161164// Main thread construction
    162165
    163 void ?{}( coroutine_desc & this, current_stack_info_t * info) with( this ) {
     166void ?{}( $coroutine & this, current_stack_info_t * info) with( this ) {
    164167        stack.storage = info->storage;
    165168        with(*stack.storage) {
     
    171174        name = "Main Thread";
    172175        state = Start;
    173         starter = NULL;
    174         last = NULL;
    175         cancellation = NULL;
    176 }
    177 
    178 void ?{}( thread_desc & this, current_stack_info_t * info) with( this ) {
     176        starter = 0p;
     177        last = 0p;
     178        cancellation = 0p;
     179}
     180
     181void ?{}( $thread & this, current_stack_info_t * info) with( this ) {
    179182        state = Start;
    180183        self_cor{ info };
     
    184187        self_mon.recursion = 1;
    185188        self_mon_p = &self_mon;
    186         next = NULL;
    187 
    188         node.next = NULL;
    189         node.prev = NULL;
     189        next = 0p;
     190
     191        node.next = 0p;
     192        node.prev = 0p;
    190193        doregister(curr_cluster, this);
    191194
     
    205208}
    206209
    207 static void start(processor * this);
    208 void ?{}(processor & this, const char * name, cluster & cltr) with( this ) {
     210static void * __invoke_processor(void * arg);
     211
     212void ?{}(processor & this, const char name[], cluster & cltr) with( this ) {
    209213        this.name = name;
    210214        this.cltr = &cltr;
    211215        terminated{ 0 };
     216        destroyer = 0p;
    212217        do_terminate = false;
    213         preemption_alarm = NULL;
     218        preemption_alarm = 0p;
    214219        pending_preemption = false;
    215220        runner.proc = &this;
     
    217222        idleLock{};
    218223
    219         start( &this );
     224        __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", &this);
     225
     226        this.stack = __create_pthread( &this.kernel_thread, __invoke_processor, (void *)&this );
     227
     228        __cfaabi_dbg_print_safe("Kernel : core %p started\n", &this);
    220229}
    221230
     
    231240        }
    232241
    233         pthread_join( kernel_thread, NULL );
    234 }
    235 
    236 void ?{}(cluster & this, const char * name, Duration preemption_rate) with( this ) {
     242        pthread_join( kernel_thread, 0p );
     243        free( this.stack );
     244}
     245
     246void ?{}(cluster & this, const char name[], Duration preemption_rate) with( this ) {
    237247        this.name = name;
    238248        this.preemption_rate = preemption_rate;
     
    254264// Kernel Scheduling logic
    255265//=============================================================================================
    256 static void runThread(processor * this, thread_desc * dst);
    257 static void finishRunning(processor * this);
    258 static void halt(processor * this);
     266static $thread * __next_thread(cluster * this);
     267static void __run_thread(processor * this, $thread * dst);
     268static void __halt(processor * this);
    259269
    260270//Main of the processor contexts
    261271void main(processorCtx_t & runner) {
     272        // Because of a bug, we couldn't initialized the seed on construction
     273        // Do it here
     274        kernelTLS.rand_seed ^= rdtscl();
     275
    262276        processor * this = runner.proc;
    263277        verify(this);
     
    273287                __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
    274288
    275                 thread_desc * readyThread = NULL;
    276                 for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ )
    277                 {
    278                         readyThread = nextThread( this->cltr );
    279 
    280                         if(readyThread)
    281                         {
    282                                 verify( ! kernelTLS.preemption_state.enabled );
    283 
    284                                 runThread(this, readyThread);
    285 
    286                                 verify( ! kernelTLS.preemption_state.enabled );
    287 
    288                                 //Some actions need to be taken from the kernel
    289                                 finishRunning(this);
     289                $thread * readyThread = 0p;
     290                for( unsigned int spin_count = 0; ! __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST); spin_count++ ) {
     291                        readyThread = __next_thread( this->cltr );
     292
     293                        if(readyThread) {
     294                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     295                                /* paranoid */ verifyf( readyThread->state == Inactive || readyThread->state == Start || readyThread->preempted != __NO_PREEMPTION, "state : %d, preempted %d\n", readyThread->state, readyThread->preempted);
     296                                /* paranoid */ verifyf( readyThread->next == 0p, "Expected null got %p", readyThread->next );
     297
     298                                __run_thread(this, readyThread);
     299
     300                                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    290301
    291302                                spin_count = 0;
    292                         }
    293                         else
    294                         {
     303                        } else {
    295304                                // spin(this, &spin_count);
    296                                 halt(this);
     305                                __halt(this);
    297306                        }
    298307                }
     
    314323// runThread runs a thread by context switching
    315324// from the processor coroutine to the target thread
    316 static void runThread(processor * this, thread_desc * thrd_dst) {
    317         coroutine_desc * proc_cor = get_coroutine(this->runner);
    318 
    319         // Reset the terminating actions here
    320         this->finish.action_code = No_Action;
     325static void __run_thread(processor * this, $thread * thrd_dst) {
     326        $coroutine * proc_cor = get_coroutine(this->runner);
    321327
    322328        // Update global state
    323329        kernelTLS.this_thread = thrd_dst;
    324330
    325         // set state of processor coroutine to inactive and the thread to active
    326         proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
    327         thrd_dst->state = Active;
    328 
    329         // set context switch to the thread that the processor is executing
    330         verify( thrd_dst->context.SP );
    331         CtxSwitch( &proc_cor->context, &thrd_dst->context );
    332         // when CtxSwitch returns we are back in the processor coroutine
    333 
    334         // set state of processor coroutine to active and the thread to inactive
    335         thrd_dst->state = thrd_dst->state == Halted ? Halted : Inactive;
     331        // set state of processor coroutine to inactive
     332        verify(proc_cor->state == Active);
     333        proc_cor->state = Inactive;
     334
     335        // Actually run the thread
     336        RUNNING:  while(true) {
     337                if(unlikely(thrd_dst->preempted)) {
     338                        thrd_dst->preempted = __NO_PREEMPTION;
     339                        verify(thrd_dst->state == Active || thrd_dst->state == Rerun);
     340                } else {
     341                        verify(thrd_dst->state == Start || thrd_dst->state == Primed || thrd_dst->state == Inactive);
     342                        thrd_dst->state = Active;
     343                }
     344
     345                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     346
     347                // set context switch to the thread that the processor is executing
     348                verify( thrd_dst->context.SP );
     349                __cfactx_switch( &proc_cor->context, &thrd_dst->context );
     350                // when __cfactx_switch returns we are back in the processor coroutine
     351
     352                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     353
     354
     355                // We just finished running a thread, there are a few things that could have happened.
     356                // 1 - Regular case : the thread has blocked and now one has scheduled it yet.
     357                // 2 - Racy case    : the thread has blocked but someone has already tried to schedule it.
     358                // 3 - Polite Racy case : the thread has blocked, someone has already tried to schedule it, but the thread is nice and wants to go through the ready-queue any way
     359                // 4 - Preempted
     360                // In case 1, we may have won a race so we can't write to the state again.
     361                // In case 2, we lost the race so we now own the thread.
     362                // In case 3, we lost the race but can just reschedule the thread.
     363
     364                if(unlikely(thrd_dst->preempted != __NO_PREEMPTION)) {
     365                        // The thread was preempted, reschedule it and reset the flag
     366                        __schedule_thread( thrd_dst );
     367                        break RUNNING;
     368                }
     369
     370                // set state of processor coroutine to active and the thread to inactive
     371                static_assert(sizeof(thrd_dst->state) == sizeof(int));
     372                enum coroutine_state old_state = __atomic_exchange_n(&thrd_dst->state, Inactive, __ATOMIC_SEQ_CST);
     373                switch(old_state) {
     374                        case Halted:
     375                                // The thread has halted, it should never be scheduled/run again, leave it back to Halted and move on
     376                                thrd_dst->state = Halted;
     377
     378                                // We may need to wake someone up here since
     379                                unpark( this->destroyer );
     380                                this->destroyer = 0p;
     381                                break RUNNING;
     382                        case Active:
     383                                // This is case 1, the regular case, nothing more is needed
     384                                break RUNNING;
     385                        case Rerun:
     386                                // This is case 2, the racy case, someone tried to run this thread before it finished blocking
     387                                // In this case, just run it again.
     388                                continue RUNNING;
     389                        default:
     390                                // This makes no sense, something is wrong abort
     391                                abort("Finished running a thread that was Inactive/Start/Primed %d\n", old_state);
     392                }
     393        }
     394
     395        // Just before returning to the processor, set the processor coroutine to active
    336396        proc_cor->state = Active;
    337397}
    338398
    339399// KERNEL_ONLY
    340 static void returnToKernel() {
    341         coroutine_desc * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
    342         thread_desc * thrd_src = kernelTLS.this_thread;
    343 
    344         // set state of current coroutine to inactive
    345         thrd_src->state = thrd_src->state == Halted ? Halted : Inactive;
    346         proc_cor->state = Active;
    347         int local_errno = *__volatile_errno();
    348         #if defined( __i386 ) || defined( __x86_64 )
    349                 __x87_store;
    350         #endif
    351 
    352         // set new coroutine that the processor is executing
    353         // and context switch to it
    354         verify( proc_cor->context.SP );
    355         CtxSwitch( &thrd_src->context, &proc_cor->context );
    356 
    357         // set state of new coroutine to active
    358         proc_cor->state = proc_cor->state == Halted ? Halted : Inactive;
    359         thrd_src->state = Active;
    360 
    361         #if defined( __i386 ) || defined( __x86_64 )
    362                 __x87_load;
    363         #endif
    364         *__volatile_errno() = local_errno;
    365 }
    366 
    367 // KERNEL_ONLY
    368 // Once a thread has finished running, some of
    369 // its final actions must be executed from the kernel
    370 static void finishRunning(processor * this) with( this->finish ) {
    371         verify( ! kernelTLS.preemption_state.enabled );
    372         choose( action_code ) {
    373         case No_Action:
    374                 break;
    375         case Release:
    376                 unlock( *lock );
    377         case Schedule:
    378                 ScheduleThread( thrd );
    379         case Release_Schedule:
    380                 unlock( *lock );
    381                 ScheduleThread( thrd );
    382         case Release_Multi:
    383                 for(int i = 0; i < lock_count; i++) {
    384                         unlock( *locks[i] );
    385                 }
    386         case Release_Multi_Schedule:
    387                 for(int i = 0; i < lock_count; i++) {
    388                         unlock( *locks[i] );
    389                 }
    390                 for(int i = 0; i < thrd_count; i++) {
    391                         ScheduleThread( thrds[i] );
    392                 }
    393         case Callback:
    394                 callback();
    395         default:
    396                 abort("KERNEL ERROR: Unexpected action to run after thread");
    397         }
     400void returnToKernel() {
     401        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     402        $coroutine * proc_cor = get_coroutine(kernelTLS.this_processor->runner);
     403        $thread * thrd_src = kernelTLS.this_thread;
     404
     405        // Run the thread on this processor
     406        {
     407                int local_errno = *__volatile_errno();
     408                #if defined( __i386 ) || defined( __x86_64 )
     409                        __x87_store;
     410                #endif
     411                verify( proc_cor->context.SP );
     412                __cfactx_switch( &thrd_src->context, &proc_cor->context );
     413                #if defined( __i386 ) || defined( __x86_64 )
     414                        __x87_load;
     415                #endif
     416                *__volatile_errno() = local_errno;
     417        }
     418
     419        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    398420}
    399421
     
    402424// This is the entry point for processors (kernel threads)
    403425// It effectively constructs a coroutine by stealing the pthread stack
    404 static void * CtxInvokeProcessor(void * arg) {
     426static void * __invoke_processor(void * arg) {
    405427        processor * proc = (processor *) arg;
    406428        kernelTLS.this_processor = proc;
    407         kernelTLS.this_thread    = NULL;
     429        kernelTLS.this_thread    = 0p;
    408430        kernelTLS.preemption_state.[enabled, disable_count] = [false, 1];
    409431        // SKULLDUGGERY: We want to create a context for the processor coroutine
     
    418440
    419441        //Set global state
    420         kernelTLS.this_thread    = NULL;
     442        kernelTLS.this_thread = 0p;
    421443
    422444        //We now have a proper context from which to schedule threads
     
    434456        __cfaabi_dbg_print_safe("Kernel : core %p main ended (%p)\n", proc, &proc->runner);
    435457
    436         return NULL;
    437 }
    438 
    439 static void start(processor * this) {
    440         __cfaabi_dbg_print_safe("Kernel : Starting core %p\n", this);
    441 
    442         pthread_create( &this->kernel_thread, NULL, CtxInvokeProcessor, (void*)this );
    443 
    444         __cfaabi_dbg_print_safe("Kernel : core %p started\n", this);
     458        return 0p;
     459}
     460
     461static void Abort( int ret, const char func[] ) {
     462        if ( ret ) {                                                                            // pthread routines return errno values
     463                abort( "%s : internal error, error(%d) %s.", func, ret, strerror( ret ) );
     464        } // if
     465} // Abort
     466
     467void * __create_pthread( pthread_t * pthread, void * (*start)(void *), void * arg ) {
     468        pthread_attr_t attr;
     469
     470        Abort( pthread_attr_init( &attr ), "pthread_attr_init" ); // initialize attribute
     471
     472        size_t stacksize;
     473        // default stack size, normally defined by shell limit
     474        Abort( pthread_attr_getstacksize( &attr, &stacksize ), "pthread_attr_getstacksize" );
     475        assert( stacksize >= PTHREAD_STACK_MIN );
     476
     477        void * stack;
     478        __cfaabi_dbg_debug_do(
     479                stack = memalign( __page_size, stacksize + __page_size );
     480                // pthread has no mechanism to create the guard page in user supplied stack.
     481                if ( mprotect( stack, __page_size, PROT_NONE ) == -1 ) {
     482                        abort( "mprotect : internal error, mprotect failure, error(%d) %s.", errno, strerror( errno ) );
     483                } // if
     484        );
     485        __cfaabi_dbg_no_debug_do(
     486                stack = malloc( stacksize );
     487        );
     488
     489        Abort( pthread_attr_setstack( &attr, stack, stacksize ), "pthread_attr_setstack" );
     490
     491        Abort( pthread_create( pthread, &attr, start, arg ), "pthread_create" );
     492        return stack;
    445493}
    446494
    447495// KERNEL_ONLY
    448 void kernel_first_resume( processor * this ) {
    449         thread_desc * src = mainThread;
    450         coroutine_desc * dst = get_coroutine(this->runner);
     496static void __kernel_first_resume( processor * this ) {
     497        $thread * src = mainThread;
     498        $coroutine * dst = get_coroutine(this->runner);
    451499
    452500        verify( ! kernelTLS.preemption_state.enabled );
    453501
     502        kernelTLS.this_thread->curr_cor = dst;
    454503        __stack_prepare( &dst->stack, 65000 );
    455         CtxStart(&this->runner, CtxInvokeCoroutine);
     504        __cfactx_start(main, dst, this->runner, __cfactx_invoke_coroutine);
    456505
    457506        verify( ! kernelTLS.preemption_state.enabled );
     
    465514        // context switch to specified coroutine
    466515        verify( dst->context.SP );
    467         CtxSwitch( &src->context, &dst->context );
    468         // when CtxSwitch returns we are back in the src coroutine
     516        __cfactx_switch( &src->context, &dst->context );
     517        // when __cfactx_switch returns we are back in the src coroutine
     518
     519        mainThread->curr_cor = &mainThread->self_cor;
    469520
    470521        // set state of new coroutine to active
     
    475526
    476527// KERNEL_ONLY
    477 void kernel_last_resume( processor * this ) {
    478         coroutine_desc * src = &mainThread->self_cor;
    479         coroutine_desc * dst = get_coroutine(this->runner);
     528static void __kernel_last_resume( processor * this ) {
     529        $coroutine * src = &mainThread->self_cor;
     530        $coroutine * dst = get_coroutine(this->runner);
    480531
    481532        verify( ! kernelTLS.preemption_state.enabled );
     
    484535
    485536        // context switch to the processor
    486         CtxSwitch( &src->context, &dst->context );
     537        __cfactx_switch( &src->context, &dst->context );
    487538}
    488539
    489540//-----------------------------------------------------------------------------
    490541// Scheduler routines
    491 
    492542// KERNEL ONLY
    493 void ScheduleThread( thread_desc * thrd ) {
    494         verify( thrd );
    495         verify( thrd->state != Halted );
    496 
    497         verify( ! kernelTLS.preemption_state.enabled );
    498 
    499         verifyf( thrd->next == NULL, "Expected null got %p", thrd->next );
    500 
    501         with( *thrd->curr_cluster ) {
    502                 lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
    503                 bool was_empty = !(ready_queue != 0);
    504                 append( ready_queue, thrd );
    505                 unlock( ready_queue_lock );
    506 
    507                 if(was_empty) {
    508                         lock      (proc_list_lock __cfaabi_dbg_ctx2);
    509                         if(idles) {
    510                                 wake_fast(idles.head);
    511                         }
    512                         unlock    (proc_list_lock);
     543void __schedule_thread( $thread * thrd ) with( *thrd->curr_cluster ) {
     544        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     545        /* paranoid */ #if defined( __CFA_WITH_VERIFY__ )
     546        /* paranoid */ if( thrd->state == Inactive || thrd->state == Start ) assertf( thrd->preempted == __NO_PREEMPTION,
     547                          "Error inactive thread marked as preempted, state %d, preemption %d\n", thrd->state, thrd->preempted );
     548        /* paranoid */ if( thrd->preempted != __NO_PREEMPTION ) assertf(thrd->state == Active || thrd->state == Rerun,
     549                          "Error preempted thread marked as not currently running, state %d, preemption %d\n", thrd->state, thrd->preempted );
     550        /* paranoid */ #endif
     551        /* paranoid */ verifyf( thrd->next == 0p, "Expected null got %p", thrd->next );
     552
     553        lock  ( ready_queue_lock __cfaabi_dbg_ctx2 );
     554        bool was_empty = !(ready_queue != 0);
     555        append( ready_queue, thrd );
     556        unlock( ready_queue_lock );
     557
     558        if(was_empty) {
     559                lock      (proc_list_lock __cfaabi_dbg_ctx2);
     560                if(idles) {
     561                        wake_fast(idles.head);
    513562                }
    514                 else if( struct processor * idle = idles.head ) {
    515                         wake_fast(idle);
    516                 }
    517 
    518         }
    519 
    520         verify( ! kernelTLS.preemption_state.enabled );
     563                unlock    (proc_list_lock);
     564        }
     565        else if( struct processor * idle = idles.head ) {
     566                wake_fast(idle);
     567        }
     568
     569        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    521570}
    522571
    523572// KERNEL ONLY
    524 thread_desc * nextThread(cluster * this) with( *this ) {
    525         verify( ! kernelTLS.preemption_state.enabled );
     573static $thread * __next_thread(cluster * this) with( *this ) {
     574        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     575
    526576        lock( ready_queue_lock __cfaabi_dbg_ctx2 );
    527         thread_desc * head = pop_head( ready_queue );
     577        $thread * head = pop_head( ready_queue );
    528578        unlock( ready_queue_lock );
    529         verify( ! kernelTLS.preemption_state.enabled );
     579
     580        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    530581        return head;
    531582}
    532583
    533 void BlockInternal() {
     584void unpark( $thread * thrd ) {
     585        if( !thrd ) return;
     586
    534587        disable_interrupts();
    535         verify( ! kernelTLS.preemption_state.enabled );
     588        static_assert(sizeof(thrd->state) == sizeof(int));
     589        enum coroutine_state old_state = __atomic_exchange_n(&thrd->state, Rerun, __ATOMIC_SEQ_CST);
     590        switch(old_state) {
     591                case Active:
     592                        // Wake won the race, the thread will reschedule/rerun itself
     593                        break;
     594                case Inactive:
     595                        /* paranoid */ verify( ! thrd->preempted != __NO_PREEMPTION );
     596
     597                        // Wake lost the race,
     598                        thrd->state = Inactive;
     599                        __schedule_thread( thrd );
     600                        break;
     601                case Rerun:
     602                        abort("More than one thread attempted to schedule thread %p\n", thrd);
     603                        break;
     604                case Halted:
     605                case Start:
     606                case Primed:
     607                default:
     608                        // This makes no sense, something is wrong abort
     609                        abort();
     610        }
     611        enable_interrupts( __cfaabi_dbg_ctx );
     612}
     613
     614void park( void ) {
     615        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
     616        disable_interrupts();
     617        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     618        /* paranoid */ verify( kernelTLS.this_thread->preempted == __NO_PREEMPTION );
     619
    536620        returnToKernel();
    537         verify( ! kernelTLS.preemption_state.enabled );
     621
     622        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    538623        enable_interrupts( __cfaabi_dbg_ctx );
    539 }
    540 
    541 void BlockInternal( __spinlock_t * lock ) {
     624        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
     625
     626}
     627
     628// KERNEL ONLY
     629void __leave_thread() {
     630        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     631        returnToKernel();
     632        abort();
     633}
     634
     635// KERNEL ONLY
     636bool force_yield( __Preemption_Reason reason ) {
     637        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
    542638        disable_interrupts();
    543         with( *kernelTLS.this_processor ) {
    544                 finish.action_code = Release;
    545                 finish.lock        = lock;
    546         }
    547 
    548         verify( ! kernelTLS.preemption_state.enabled );
    549         returnToKernel();
    550         verify( ! kernelTLS.preemption_state.enabled );
    551 
    552         enable_interrupts( __cfaabi_dbg_ctx );
    553 }
    554 
    555 void BlockInternal( thread_desc * thrd ) {
    556         disable_interrupts();
    557         with( * kernelTLS.this_processor ) {
    558                 finish.action_code = Schedule;
    559                 finish.thrd        = thrd;
    560         }
    561 
    562         verify( ! kernelTLS.preemption_state.enabled );
    563         returnToKernel();
    564         verify( ! kernelTLS.preemption_state.enabled );
    565 
    566         enable_interrupts( __cfaabi_dbg_ctx );
    567 }
    568 
    569 void BlockInternal( __spinlock_t * lock, thread_desc * thrd ) {
    570         assert(thrd);
    571         disable_interrupts();
    572         with( * kernelTLS.this_processor ) {
    573                 finish.action_code = Release_Schedule;
    574                 finish.lock        = lock;
    575                 finish.thrd        = thrd;
    576         }
    577 
    578         verify( ! kernelTLS.preemption_state.enabled );
    579         returnToKernel();
    580         verify( ! kernelTLS.preemption_state.enabled );
    581 
    582         enable_interrupts( __cfaabi_dbg_ctx );
    583 }
    584 
    585 void BlockInternal(__spinlock_t * locks [], unsigned short count) {
    586         disable_interrupts();
    587         with( * kernelTLS.this_processor ) {
    588                 finish.action_code = Release_Multi;
    589                 finish.locks       = locks;
    590                 finish.lock_count  = count;
    591         }
    592 
    593         verify( ! kernelTLS.preemption_state.enabled );
    594         returnToKernel();
    595         verify( ! kernelTLS.preemption_state.enabled );
    596 
    597         enable_interrupts( __cfaabi_dbg_ctx );
    598 }
    599 
    600 void BlockInternal(__spinlock_t * locks [], unsigned short lock_count, thread_desc * thrds [], unsigned short thrd_count) {
    601         disable_interrupts();
    602         with( *kernelTLS.this_processor ) {
    603                 finish.action_code = Release_Multi_Schedule;
    604                 finish.locks       = locks;
    605                 finish.lock_count  = lock_count;
    606                 finish.thrds       = thrds;
    607                 finish.thrd_count  = thrd_count;
    608         }
    609 
    610         verify( ! kernelTLS.preemption_state.enabled );
    611         returnToKernel();
    612         verify( ! kernelTLS.preemption_state.enabled );
    613 
    614         enable_interrupts( __cfaabi_dbg_ctx );
    615 }
    616 
    617 void BlockInternal(__finish_callback_fptr_t callback) {
    618         disable_interrupts();
    619         with( *kernelTLS.this_processor ) {
    620                 finish.action_code = Callback;
    621                 finish.callback    = callback;
    622         }
    623 
    624         verify( ! kernelTLS.preemption_state.enabled );
    625         returnToKernel();
    626         verify( ! kernelTLS.preemption_state.enabled );
    627 
    628         enable_interrupts( __cfaabi_dbg_ctx );
    629 }
    630 
    631 // KERNEL ONLY
    632 void LeaveThread(__spinlock_t * lock, thread_desc * thrd) {
    633         verify( ! kernelTLS.preemption_state.enabled );
    634         with( * kernelTLS.this_processor ) {
    635                 finish.action_code = thrd ? Release_Schedule : Release;
    636                 finish.lock        = lock;
    637                 finish.thrd        = thrd;
    638         }
    639 
    640         returnToKernel();
     639        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     640
     641        $thread * thrd = kernelTLS.this_thread;
     642        /* paranoid */ verify(thrd->state == Active || thrd->state == Rerun);
     643
     644        // SKULLDUGGERY: It is possible that we are preempting this thread just before
     645        // it was going to park itself. If that is the case and it is already using the
     646        // intrusive fields then we can't use them to preempt the thread
     647        // If that is the case, abandon the preemption.
     648        bool preempted = false;
     649        if(thrd->next == 0p) {
     650                preempted = true;
     651                thrd->preempted = reason;
     652                returnToKernel();
     653        }
     654
     655        /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     656        enable_interrupts_noPoll();
     657        /* paranoid */ verify( kernelTLS.preemption_state.enabled );
     658
     659        return preempted;
    641660}
    642661
     
    646665//-----------------------------------------------------------------------------
    647666// Kernel boot procedures
    648 static void kernel_startup(void) {
     667static void __kernel_startup(void) {
    649668        verify( ! kernelTLS.preemption_state.enabled );
    650669        __cfaabi_dbg_print_safe("Kernel : Starting\n");
     
    664683        // SKULLDUGGERY: the mainThread steals the process main thread
    665684        // which will then be scheduled by the mainProcessor normally
    666         mainThread = (thread_desc *)&storage_mainThread;
     685        mainThread = ($thread *)&storage_mainThread;
    667686        current_stack_info_t info;
    668687        info.storage = (__stack_t*)&storage_mainThreadCtx;
     
    676695        void ?{}(processorCtx_t & this, processor * proc) {
    677696                (this.__cor){ "Processor" };
    678                 this.__cor.starter = NULL;
     697                this.__cor.starter = 0p;
    679698                this.proc = proc;
    680699        }
     
    685704                terminated{ 0 };
    686705                do_terminate = false;
    687                 preemption_alarm = NULL;
     706                preemption_alarm = 0p;
    688707                pending_preemption = false;
    689708                kernel_thread = pthread_self();
     
    707726        // Add the main thread to the ready queue
    708727        // once resume is called on mainProcessor->runner the mainThread needs to be scheduled like any normal thread
    709         ScheduleThread(mainThread);
     728        __schedule_thread(mainThread);
    710729
    711730        // SKULLDUGGERY: Force a context switch to the main processor to set the main thread's context to the current UNIX
    712         // context. Hence, the main thread does not begin through CtxInvokeThread, like all other threads. The trick here is that
     731        // context. Hence, the main thread does not begin through __cfactx_invoke_thread, like all other threads. The trick here is that
    713732        // mainThread is on the ready queue when this call is made.
    714         kernel_first_resume( kernelTLS.this_processor );
     733        __kernel_first_resume( kernelTLS.this_processor );
    715734
    716735
     
    724743}
    725744
    726 static void kernel_shutdown(void) {
     745static void __kernel_shutdown(void) {
    727746        __cfaabi_dbg_print_safe("\n--------------------------------------------------\nKernel : Shutting down\n");
    728747
     
    735754        // which is currently here
    736755        __atomic_store_n(&mainProcessor->do_terminate, true, __ATOMIC_RELEASE);
    737         kernel_last_resume( kernelTLS.this_processor );
     756        __kernel_last_resume( kernelTLS.this_processor );
    738757        mainThread->self_cor.state = Halted;
    739758
     
    761780// Kernel Quiescing
    762781//=============================================================================================
    763 static void halt(processor * this) with( *this ) {
     782static void __halt(processor * this) with( *this ) {
    764783        // verify( ! __atomic_load_n(&do_terminate, __ATOMIC_SEQ_CST) );
    765784
     
    803822                sigemptyset( &mask );
    804823                sigaddset( &mask, SIGALRM );            // block SIGALRM signals
    805                 sigsuspend( &mask );                    // block the processor to prevent further damage during abort
    806                 _exit( EXIT_FAILURE );                  // if processor unblocks before it is killed, terminate it
     824                sigaddset( &mask, SIGUSR1 );            // block SIGALRM signals
     825                sigsuspend( &mask );                            // block the processor to prevent further damage during abort
     826                _exit( EXIT_FAILURE );                          // if processor unblocks before it is killed, terminate it
    807827        }
    808828        else {
     
    815835
    816836void kernel_abort_msg( void * kernel_data, char * abort_text, int abort_text_size ) {
    817         thread_desc * thrd = kernel_data;
     837        $thread * thrd = kernel_data;
    818838
    819839        if(thrd) {
    820840                int len = snprintf( abort_text, abort_text_size, "Error occurred while executing thread %.256s (%p)", thrd->self_cor.name, thrd );
    821                 __cfaabi_dbg_bits_write( abort_text, len );
     841                __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    822842
    823843                if ( &thrd->self_cor != thrd->curr_cor ) {
    824844                        len = snprintf( abort_text, abort_text_size, " in coroutine %.256s (%p).\n", thrd->curr_cor->name, thrd->curr_cor );
    825                         __cfaabi_dbg_bits_write( abort_text, len );
     845                        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    826846                }
    827847                else {
    828                         __cfaabi_dbg_bits_write( ".\n", 2 );
     848                        __cfaabi_bits_write( STDERR_FILENO, ".\n", 2 );
    829849                }
    830850        }
    831851        else {
    832852                int len = snprintf( abort_text, abort_text_size, "Error occurred outside of any thread.\n" );
    833                 __cfaabi_dbg_bits_write( abort_text, len );
     853                __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
    834854        }
    835855}
     
    842862
    843863extern "C" {
    844         void __cfaabi_dbg_bits_acquire() {
     864        void __cfaabi_bits_acquire() {
    845865                lock( kernel_debug_lock __cfaabi_dbg_ctx2 );
    846866        }
    847867
    848         void __cfaabi_dbg_bits_release() {
     868        void __cfaabi_bits_release() {
    849869                unlock( kernel_debug_lock );
    850870        }
     
    871891
    872892                // atomically release spin lock and block
    873                 BlockInternal( &lock );
     893                unlock( lock );
     894                park();
    874895        }
    875896        else {
     
    879900
    880901void V(semaphore & this) with( this ) {
    881         thread_desc * thrd = NULL;
     902        $thread * thrd = 0p;
    882903        lock( lock __cfaabi_dbg_ctx2 );
    883904        count += 1;
     
    890911
    891912        // make new owner
    892         WakeThread( thrd );
     913        unpark( thrd );
    893914}
    894915
     
    907928}
    908929
    909 void doregister( cluster * cltr, thread_desc & thrd ) {
     930void doregister( cluster * cltr, $thread & thrd ) {
    910931        lock      (cltr->thread_list_lock __cfaabi_dbg_ctx2);
    911932        cltr->nthreads += 1;
     
    914935}
    915936
    916 void unregister( cluster * cltr, thread_desc & thrd ) {
     937void unregister( cluster * cltr, $thread & thrd ) {
    917938        lock  (cltr->thread_list_lock __cfaabi_dbg_ctx2);
    918939        remove(cltr->threads, thrd );
     
    939960__cfaabi_dbg_debug_do(
    940961        extern "C" {
    941                 void __cfaabi_dbg_record(__spinlock_t & this, const char * prev_name) {
     962                void __cfaabi_dbg_record(__spinlock_t & this, const char prev_name[]) {
    942963                        this.prev_name = prev_name;
    943964                        this.prev_thrd = kernelTLS.this_thread;
     
    948969//-----------------------------------------------------------------------------
    949970// Debug
    950 bool threading_enabled(void) {
     971bool threading_enabled(void) __attribute__((const)) {
    951972        return true;
    952973}
  • libcfa/src/concurrency/kernel.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 22 11:39:17 2019
    13 // Update Count     : 16
     12// Last Modified On : Tue Feb  4 12:29:26 2020
     13// Update Count     : 22
    1414//
    1515
     
    2020#include "invoke.h"
    2121#include "time_t.hfa"
     22#include "coroutine.hfa"
    2223
    2324extern "C" {
     
    3132        __spinlock_t lock;
    3233        int count;
    33         __queue_t(thread_desc) waiting;
     34        __queue_t($thread) waiting;
    3435};
    3536
     
    4344// Processor
    4445extern struct cluster * mainCluster;
    45 
    46 enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule, Callback };
    47 
    48 typedef void (*__finish_callback_fptr_t)(void);
    49 
    50 //TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI)
    51 struct FinishAction {
    52         FinishOpCode action_code;
    53         /*
    54         // Union of possible actions
    55         union {
    56                 // Option 1 : locks and threads
    57                 struct {
    58                         // 1 thread or N thread
    59                         union {
    60                                 thread_desc * thrd;
    61                                 struct {
    62                                         thread_desc ** thrds;
    63                                         unsigned short thrd_count;
    64                                 };
    65                         };
    66                         // 1 lock or N lock
    67                         union {
    68                                 __spinlock_t * lock;
    69                                 struct {
    70                                         __spinlock_t ** locks;
    71                                         unsigned short lock_count;
    72                                 };
    73                         };
    74                 };
    75                 // Option 2 : action pointer
    76                 __finish_callback_fptr_t callback;
    77         };
    78         /*/
    79         thread_desc * thrd;
    80         thread_desc ** thrds;
    81         unsigned short thrd_count;
    82         __spinlock_t * lock;
    83         __spinlock_t ** locks;
    84         unsigned short lock_count;
    85         __finish_callback_fptr_t callback;
    86         //*/
    87 };
    88 static inline void ?{}(FinishAction & this) {
    89         this.action_code = No_Action;
    90         this.thrd = NULL;
    91         this.lock = NULL;
    92 }
    93 static inline void ^?{}(FinishAction &) {}
    9446
    9547// Processor
     
    11567        // RunThread data
    11668        // Action to do after a thread is ran
    117         struct FinishAction finish;
     69        $thread * destroyer;
    11870
    11971        // Preemption data
     
    13486        semaphore terminated;
    13587
     88        // pthread Stack
     89        void * stack;
     90
    13691        // Link lists fields
    13792        struct __dbg_node_proc {
     
    146101};
    147102
    148 void  ?{}(processor & this, const char * name, struct cluster & cltr);
     103void  ?{}(processor & this, const char name[], struct cluster & cltr);
    149104void ^?{}(processor & this);
    150105
    151106static inline void  ?{}(processor & this)                    { this{ "Anonymous Processor", *mainCluster}; }
    152107static inline void  ?{}(processor & this, struct cluster & cltr)    { this{ "Anonymous Processor", cltr}; }
    153 static inline void  ?{}(processor & this, const char * name) { this{name, *mainCluster }; }
     108static inline void  ?{}(processor & this, const char name[]) { this{name, *mainCluster }; }
    154109
    155 static inline [processor *&, processor *& ] __get( processor & this ) {
    156         return this.node.[next, prev];
    157 }
     110static inline [processor *&, processor *& ] __get( processor & this ) __attribute__((const)) { return this.node.[next, prev]; }
    158111
    159112//-----------------------------------------------------------------------------
     
    164117
    165118        // Ready queue for threads
    166         __queue_t(thread_desc) ready_queue;
     119        __queue_t($thread) ready_queue;
    167120
    168121        // Name of the cluster
     
    180133        // List of threads
    181134        __spinlock_t thread_list_lock;
    182         __dllist_t(struct thread_desc) threads;
     135        __dllist_t(struct $thread) threads;
    183136        unsigned int nthreads;
    184137
     
    191144extern Duration default_preemption();
    192145
    193 void ?{} (cluster & this, const char * name, Duration preemption_rate);
     146void ?{} (cluster & this, const char name[], Duration preemption_rate);
    194147void ^?{}(cluster & this);
    195148
    196149static inline void ?{} (cluster & this)                           { this{"Anonymous Cluster", default_preemption()}; }
    197150static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; }
    198 static inline void ?{} (cluster & this, const char * name)        { this{name, default_preemption()}; }
     151static inline void ?{} (cluster & this, const char name[])        { this{name, default_preemption()}; }
    199152
    200 static inline [cluster *&, cluster *& ] __get( cluster & this ) {
    201         return this.node.[next, prev];
    202 }
     153static inline [cluster *&, cluster *& ] __get( cluster & this ) __attribute__((const)) { return this.node.[next, prev]; }
    203154
    204155static inline struct processor * active_processor() { return TL_GET( this_processor ); } // UNSAFE
  • libcfa/src/concurrency/kernel_private.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Feb 13 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Mar 29 14:06:40 2018
    13 // Update Count     : 3
     12// Last Modified On : Sat Nov 30 19:25:02 2019
     13// Update Count     : 8
    1414//
    1515
     
    3131}
    3232
    33 void ScheduleThread( thread_desc * );
    34 static inline void WakeThread( thread_desc * thrd ) {
    35         if( !thrd ) return;
    36 
    37         disable_interrupts();
    38         ScheduleThread( thrd );
    39         enable_interrupts( __cfaabi_dbg_ctx );
    40 }
    41 thread_desc * nextThread(cluster * this);
     33void __schedule_thread( $thread * ) __attribute__((nonnull (1)));
    4234
    4335//Block current thread and release/wake-up the following resources
    44 void BlockInternal(void);
    45 void BlockInternal(__spinlock_t * lock);
    46 void BlockInternal(thread_desc * thrd);
    47 void BlockInternal(__spinlock_t * lock, thread_desc * thrd);
    48 void BlockInternal(__spinlock_t * locks [], unsigned short count);
    49 void BlockInternal(__spinlock_t * locks [], unsigned short count, thread_desc * thrds [], unsigned short thrd_count);
    50 void BlockInternal(__finish_callback_fptr_t callback);
    51 void LeaveThread(__spinlock_t * lock, thread_desc * thrd);
     36void __leave_thread() __attribute__((noreturn));
    5237
    5338//-----------------------------------------------------------------------------
    5439// Processor
    5540void main(processorCtx_t *);
     41
     42void * __create_pthread( pthread_t *, void * (*)(void *), void * );
    5643
    5744static inline void wake_fast(processor * this) {
     
    8471// Threads
    8572extern "C" {
    86       forall(dtype T | is_thread(T))
    87       void CtxInvokeThread(T * this);
     73      void __cfactx_invoke_thread(void (*main)(void *), void * this);
    8874}
    8975
    90 extern void ThreadCtxSwitch(coroutine_desc * src, coroutine_desc * dst);
    91 
    9276__cfaabi_dbg_debug_do(
    93         extern void __cfaabi_dbg_thread_register  ( thread_desc * thrd );
    94         extern void __cfaabi_dbg_thread_unregister( thread_desc * thrd );
     77        extern void __cfaabi_dbg_thread_register  ( $thread * thrd );
     78        extern void __cfaabi_dbg_thread_unregister( $thread * thrd );
    9579)
    9680
     
    9983#define KERNEL_STORAGE(T,X) static char storage_##X[sizeof(T)]
    10084
     85static inline uint32_t __tls_rand() {
     86        kernelTLS.rand_seed ^= kernelTLS.rand_seed << 6;
     87        kernelTLS.rand_seed ^= kernelTLS.rand_seed >> 21;
     88        kernelTLS.rand_seed ^= kernelTLS.rand_seed << 7;
     89        return kernelTLS.rand_seed;
     90}
     91
    10192
    10293void doregister( struct cluster & cltr );
    10394void unregister( struct cluster & cltr );
    10495
    105 void doregister( struct cluster * cltr, struct thread_desc & thrd );
    106 void unregister( struct cluster * cltr, struct thread_desc & thrd );
     96void doregister( struct cluster * cltr, struct $thread & thrd );
     97void unregister( struct cluster * cltr, struct $thread & thrd );
    10798
    10899void doregister( struct cluster * cltr, struct processor * proc );
  • libcfa/src/concurrency/monitor.cfa

    r9fb8f01 r3d5701e  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // monitor_desc.c --
     7// $monitor.c --
    88//
    99// Author           : Thierry Delisle
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 14:30:26 2018
    13 // Update Count     : 9
     12// Last Modified On : Wed Dec  4 07:55:14 2019
     13// Update Count     : 10
    1414//
    1515
     
    2727//-----------------------------------------------------------------------------
    2828// Forward declarations
    29 static inline void set_owner ( monitor_desc * this, thread_desc * owner );
    30 static inline void set_owner ( monitor_desc * storage [], __lock_size_t count, thread_desc * owner );
    31 static inline void set_mask  ( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask );
    32 static inline void reset_mask( monitor_desc * this );
    33 
    34 static inline thread_desc * next_thread( monitor_desc * this );
    35 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & monitors );
     29static inline void __set_owner ( $monitor * this, $thread * owner );
     30static inline void __set_owner ( $monitor * storage [], __lock_size_t count, $thread * owner );
     31static inline void set_mask  ( $monitor * storage [], __lock_size_t count, const __waitfor_mask_t & mask );
     32static inline void reset_mask( $monitor * this );
     33
     34static inline $thread * next_thread( $monitor * this );
     35static inline bool is_accepted( $monitor * this, const __monitor_group_t & monitors );
    3636
    3737static inline void lock_all  ( __spinlock_t * locks [], __lock_size_t count );
    38 static inline void lock_all  ( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count );
     38static inline void lock_all  ( $monitor * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count );
    3939static inline void unlock_all( __spinlock_t * locks [], __lock_size_t count );
    40 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count );
    41 
    42 static inline void save   ( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] );
    43 static inline void restore( monitor_desc * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );
    44 
    45 static inline void init     ( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
    46 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
    47 
    48 static inline thread_desc *        check_condition   ( __condition_criterion_t * );
     40static inline void unlock_all( $monitor * locks [], __lock_size_t count );
     41
     42static inline void save   ( $monitor * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*out*/ recursions [], __waitfor_mask_t /*out*/ masks [] );
     43static inline void restore( $monitor * ctx [], __lock_size_t count, __spinlock_t * locks [], unsigned int /*in */ recursions [], __waitfor_mask_t /*in */ masks [] );
     44
     45static inline void init     ( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
     46static inline void init_push( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] );
     47
     48static inline $thread *        check_condition   ( __condition_criterion_t * );
    4949static inline void                 brand_condition   ( condition & );
    50 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t &, monitor_desc * monitors [], __lock_size_t count );
     50static inline [$thread *, int] search_entry_queue( const __waitfor_mask_t &, $monitor * monitors [], __lock_size_t count );
    5151
    5252forall(dtype T | sized( T ))
    5353static inline __lock_size_t insert_unique( T * array [], __lock_size_t & size, T * val );
    5454static inline __lock_size_t count_max    ( const __waitfor_mask_t & mask );
    55 static inline __lock_size_t aggregate    ( monitor_desc * storage [], const __waitfor_mask_t & mask );
     55static inline __lock_size_t aggregate    ( $monitor * storage [], const __waitfor_mask_t & mask );
    5656
    5757//-----------------------------------------------------------------------------
     
    6868
    6969#define monitor_ctx( mons, cnt )                                /* Define that create the necessary struct for internal/external scheduling operations */ \
    70         monitor_desc ** monitors = mons;                          /* Save the targeted monitors                                                          */ \
     70        $monitor ** monitors = mons;                          /* Save the targeted monitors                                                          */ \
    7171        __lock_size_t count = cnt;                                /* Save the count to a local variable                                                  */ \
    7272        unsigned int recursions[ count ];                         /* Save the current recursion levels to restore them later                             */ \
     
    8080//-----------------------------------------------------------------------------
    8181// Enter/Leave routines
    82 
    83 
    84 extern "C" {
    85         // Enter single monitor
    86         static void __enter_monitor_desc( monitor_desc * this, const __monitor_group_t & group ) {
    87                 // Lock the monitor spinlock
    88                 lock( this->lock __cfaabi_dbg_ctx2 );
    89                 // Interrupts disable inside critical section
    90                 thread_desc * thrd = kernelTLS.this_thread;
    91 
    92                 __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
    93 
    94                 if( !this->owner ) {
    95                         // No one has the monitor, just take it
    96                         set_owner( this, thrd );
    97 
    98                         __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
    99                 }
    100                 else if( this->owner == thrd) {
    101                         // We already have the monitor, just note how many times we took it
    102                         this->recursion += 1;
    103 
    104                         __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
    105                 }
    106                 else if( is_accepted( this, group) ) {
    107                         // Some one was waiting for us, enter
    108                         set_owner( this, thrd );
    109 
    110                         // Reset mask
    111                         reset_mask( this );
    112 
    113                         __cfaabi_dbg_print_safe( "Kernel :  mon accepts \n" );
    114                 }
    115                 else {
    116                         __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    117 
    118                         // Some one else has the monitor, wait in line for it
    119                         append( this->entry_queue, thrd );
    120 
    121                         BlockInternal( &this->lock );
    122 
    123                         __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    124 
    125                         // BlockInternal will unlock spinlock, no need to unlock ourselves
    126                         return;
    127                 }
     82// Enter single monitor
     83static void __enter( $monitor * this, const __monitor_group_t & group ) {
     84        // Lock the monitor spinlock
     85        lock( this->lock __cfaabi_dbg_ctx2 );
     86        // Interrupts disable inside critical section
     87        $thread * thrd = kernelTLS.this_thread;
     88
     89        __cfaabi_dbg_print_safe( "Kernel : %10p Entering mon %p (%p)\n", thrd, this, this->owner);
     90
     91        if( !this->owner ) {
     92                // No one has the monitor, just take it
     93                __set_owner( this, thrd );
     94
     95                __cfaabi_dbg_print_safe( "Kernel :  mon is free \n" );
     96        }
     97        else if( this->owner == thrd) {
     98                // We already have the monitor, just note how many times we took it
     99                this->recursion += 1;
     100
     101                __cfaabi_dbg_print_safe( "Kernel :  mon already owned \n" );
     102        }
     103        else if( is_accepted( this, group) ) {
     104                // Some one was waiting for us, enter
     105                __set_owner( this, thrd );
     106
     107                // Reset mask
     108                reset_mask( this );
     109
     110                __cfaabi_dbg_print_safe( "Kernel :  mon accepts \n" );
     111        }
     112        else {
     113                __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     114
     115                // Some one else has the monitor, wait in line for it
     116                /* paranoid */ verify( thrd->next == 0p );
     117                append( this->entry_queue, thrd );
     118                /* paranoid */ verify( thrd->next == 1p );
     119
     120                unlock( this->lock );
     121                park();
    128122
    129123                __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
    130124
    131                 // Release the lock and leave
     125                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     126                return;
     127        }
     128
     129        __cfaabi_dbg_print_safe( "Kernel : %10p Entered  mon %p\n", thrd, this);
     130
     131        /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     132        /* paranoid */ verify( this->lock.lock );
     133
     134        // Release the lock and leave
     135        unlock( this->lock );
     136        return;
     137}
     138
     139static void __dtor_enter( $monitor * this, fptr_t func ) {
     140        // Lock the monitor spinlock
     141        lock( this->lock __cfaabi_dbg_ctx2 );
     142        // Interrupts disable inside critical section
     143        $thread * thrd = kernelTLS.this_thread;
     144
     145        __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
     146
     147
     148        if( !this->owner ) {
     149                __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
     150
     151                // No one has the monitor, just take it
     152                __set_owner( this, thrd );
     153
     154                verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     155
    132156                unlock( this->lock );
    133157                return;
    134158        }
    135 
    136         static void __enter_monitor_dtor( monitor_desc * this, fptr_t func ) {
    137                 // Lock the monitor spinlock
    138                 lock( this->lock __cfaabi_dbg_ctx2 );
    139                 // Interrupts disable inside critical section
    140                 thread_desc * thrd = kernelTLS.this_thread;
    141 
    142                 __cfaabi_dbg_print_safe( "Kernel : %10p Entering dtor for mon %p (%p)\n", thrd, this, this->owner);
    143 
    144 
    145                 if( !this->owner ) {
    146                         __cfaabi_dbg_print_safe( "Kernel : Destroying free mon %p\n", this);
    147 
    148                         // No one has the monitor, just take it
    149                         set_owner( this, thrd );
    150 
    151                         unlock( this->lock );
    152                         return;
     159        else if( this->owner == thrd) {
     160                // We already have the monitor... but where about to destroy it so the nesting will fail
     161                // Abort!
     162                abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
     163        }
     164
     165        __lock_size_t count = 1;
     166        $monitor ** monitors = &this;
     167        __monitor_group_t group = { &this, 1, func };
     168        if( is_accepted( this, group) ) {
     169                __cfaabi_dbg_print_safe( "Kernel :  mon accepts dtor, block and signal it \n" );
     170
     171                // Wake the thread that is waiting for this
     172                __condition_criterion_t * urgent = pop( this->signal_stack );
     173                /* paranoid */ verify( urgent );
     174
     175                // Reset mask
     176                reset_mask( this );
     177
     178                // Create the node specific to this wait operation
     179                wait_ctx_primed( thrd, 0 )
     180
     181                // Some one else has the monitor, wait for him to finish and then run
     182                unlock( this->lock );
     183
     184                // Release the next thread
     185                /* paranoid */ verifyf( urgent->owner->waiting_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     186                unpark( urgent->owner->waiting_thread );
     187
     188                // Park current thread waiting
     189                park();
     190
     191                // Some one was waiting for us, enter
     192                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     193        }
     194        else {
     195                __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
     196
     197                wait_ctx( thrd, 0 )
     198                this->dtor_node = &waiter;
     199
     200                // Some one else has the monitor, wait in line for it
     201                /* paranoid */ verify( thrd->next == 0p );
     202                append( this->entry_queue, thrd );
     203                /* paranoid */ verify( thrd->next == 1p );
     204                unlock( this->lock );
     205
     206                // Park current thread waiting
     207                park();
     208
     209                /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     210                return;
     211        }
     212
     213        __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
     214
     215}
     216
     217// Leave single monitor
     218void __leave( $monitor * this ) {
     219        // Lock the monitor spinlock
     220        lock( this->lock __cfaabi_dbg_ctx2 );
     221
     222        __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
     223
     224        /* paranoid */ verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     225
     226        // Leaving a recursion level, decrement the counter
     227        this->recursion -= 1;
     228
     229        // If we haven't left the last level of recursion
     230        // it means we don't need to do anything
     231        if( this->recursion != 0) {
     232                __cfaabi_dbg_print_safe( "Kernel :  recursion still %d\n", this->recursion);
     233                unlock( this->lock );
     234                return;
     235        }
     236
     237        // Get the next thread, will be null on low contention monitor
     238        $thread * new_owner = next_thread( this );
     239
     240        // Check the new owner is consistent with who we wake-up
     241        // new_owner might be null even if someone owns the monitor when the owner is still waiting for another monitor
     242        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     243
     244        // We can now let other threads in safely
     245        unlock( this->lock );
     246
     247        //We need to wake-up the thread
     248        /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     249        unpark( new_owner );
     250}
     251
     252// Leave single monitor for the last time
     253void __dtor_leave( $monitor * this ) {
     254        __cfaabi_dbg_debug_do(
     255                if( TL_GET( this_thread ) != this->owner ) {
     256                        abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
    153257                }
    154                 else if( this->owner == thrd) {
    155                         // We already have the monitor... but where about to destroy it so the nesting will fail
    156                         // Abort!
    157                         abort( "Attempt to destroy monitor %p by thread \"%.256s\" (%p) in nested mutex.", this, thrd->self_cor.name, thrd );
     258                if( this->recursion != 1 ) {
     259                        abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    158260                }
    159 
    160                 __lock_size_t count = 1;
    161                 monitor_desc ** monitors = &this;
    162                 __monitor_group_t group = { &this, 1, func };
    163                 if( is_accepted( this, group) ) {
    164                         __cfaabi_dbg_print_safe( "Kernel :  mon accepts dtor, block and signal it \n" );
    165 
    166                         // Wake the thread that is waiting for this
    167                         __condition_criterion_t * urgent = pop( this->signal_stack );
    168                         verify( urgent );
    169 
    170                         // Reset mask
    171                         reset_mask( this );
    172 
    173                         // Create the node specific to this wait operation
    174                         wait_ctx_primed( thrd, 0 )
    175 
    176                         // Some one else has the monitor, wait for him to finish and then run
    177                         BlockInternal( &this->lock, urgent->owner->waiting_thread );
    178 
    179                         // Some one was waiting for us, enter
    180                         set_owner( this, thrd );
    181                 }
    182                 else {
    183                         __cfaabi_dbg_print_safe( "Kernel :  blocking \n" );
    184 
    185                         wait_ctx( thrd, 0 )
    186                         this->dtor_node = &waiter;
    187 
    188                         // Some one else has the monitor, wait in line for it
    189                         append( this->entry_queue, thrd );
    190                         BlockInternal( &this->lock );
    191 
    192                         // BlockInternal will unlock spinlock, no need to unlock ourselves
    193                         return;
    194                 }
    195 
    196                 __cfaabi_dbg_print_safe( "Kernel : Destroying %p\n", this);
    197 
    198         }
    199 
    200         // Leave single monitor
    201         void __leave_monitor_desc( monitor_desc * this ) {
    202                 // Lock the monitor spinlock
    203                 lock( this->lock __cfaabi_dbg_ctx2 );
    204 
    205                 __cfaabi_dbg_print_safe( "Kernel : %10p Leaving mon %p (%p)\n", kernelTLS.this_thread, this, this->owner);
    206 
    207                 verifyf( kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
    208 
    209                 // Leaving a recursion level, decrement the counter
    210                 this->recursion -= 1;
    211 
    212                 // If we haven't left the last level of recursion
    213                 // it means we don't need to do anything
    214                 if( this->recursion != 0) {
    215                         __cfaabi_dbg_print_safe( "Kernel :  recursion still %d\n", this->recursion);
    216                         unlock( this->lock );
    217                         return;
    218                 }
    219 
    220                 // Get the next thread, will be null on low contention monitor
    221                 thread_desc * new_owner = next_thread( this );
    222 
    223                 // We can now let other threads in safely
    224                 unlock( this->lock );
    225 
    226                 //We need to wake-up the thread
    227                 WakeThread( new_owner );
    228         }
    229 
    230         // Leave single monitor for the last time
    231         void __leave_dtor_monitor_desc( monitor_desc * this ) {
    232                 __cfaabi_dbg_debug_do(
    233                         if( TL_GET( this_thread ) != this->owner ) {
    234                                 abort( "Destroyed monitor %p has inconsistent owner, expected %p got %p.\n", this, TL_GET( this_thread ), this->owner);
    235                         }
    236                         if( this->recursion != 1 ) {
    237                                 abort( "Destroyed monitor %p has %d outstanding nested calls.\n", this, this->recursion - 1);
    238                         }
    239                 )
    240         }
    241 
     261        )
     262}
     263
     264extern "C" {
    242265        // Leave the thread monitor
    243266        // last routine called by a thread.
    244267        // Should never return
    245         void __leave_thread_monitor( thread_desc * thrd ) {
    246                 monitor_desc * this = &thrd->self_mon;
     268        void __cfactx_thrd_leave() {
     269                $thread * thrd = TL_GET( this_thread );
     270                $monitor * this = &thrd->self_mon;
    247271
    248272                // Lock the monitor now
     
    251275                disable_interrupts();
    252276
    253                 thrd->self_cor.state = Halted;
    254 
    255                 verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
     277                thrd->state = Halted;
     278
     279                /* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
    256280
    257281                // Leaving a recursion level, decrement the counter
     
    263287
    264288                // Fetch the next thread, can be null
    265                 thread_desc * new_owner = next_thread( this );
    266 
    267                 // Leave the thread, this will unlock the spinlock
    268                 // Use leave thread instead of BlockInternal which is
    269                 // specialized for this case and supports null new_owner
    270                 LeaveThread( &this->lock, new_owner );
     289                $thread * new_owner = next_thread( this );
     290
     291                // Release the monitor lock
     292                unlock( this->lock );
     293
     294                // Unpark the next owner if needed
     295                /* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
     296                /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
     297                /* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
     298                /* paranoid */ verify( thrd->state == Halted );
     299
     300                kernelTLS.this_processor->destroyer = new_owner;
     301
     302                // Leave the thread
     303                __leave_thread();
    271304
    272305                // Control flow should never reach here!
     
    278311static inline void enter( __monitor_group_t monitors ) {
    279312        for( __lock_size_t i = 0; i < monitors.size; i++) {
    280                 __enter_monitor_desc( monitors[i], monitors );
     313                __enter( monitors[i], monitors );
    281314        }
    282315}
     
    284317// Leave multiple monitor
    285318// relies on the monitor array being sorted
    286 static inline void leave(monitor_desc * monitors [], __lock_size_t count) {
     319static inline void leave($monitor * monitors [], __lock_size_t count) {
    287320        for( __lock_size_t i = count - 1; i >= 0; i--) {
    288                 __leave_monitor_desc( monitors[i] );
     321                __leave( monitors[i] );
    289322        }
    290323}
     
    292325// Ctor for monitor guard
    293326// Sorts monitors before entering
    294 void ?{}( monitor_guard_t & this, monitor_desc * m [], __lock_size_t count, fptr_t func ) {
    295         thread_desc * thrd = TL_GET( this_thread );
     327void ?{}( monitor_guard_t & this, $monitor * m [], __lock_size_t count, fptr_t func ) {
     328        $thread * thrd = TL_GET( this_thread );
    296329
    297330        // Store current array
     
    333366// Ctor for monitor guard
    334367// Sorts monitors before entering
    335 void ?{}( monitor_dtor_guard_t & this, monitor_desc * m [], fptr_t func ) {
     368void ?{}( monitor_dtor_guard_t & this, $monitor * m [], fptr_t func ) {
    336369        // optimization
    337         thread_desc * thrd = TL_GET( this_thread );
     370        $thread * thrd = TL_GET( this_thread );
    338371
    339372        // Store current array
     
    346379        (thrd->monitors){m, 1, func};
    347380
    348         __enter_monitor_dtor( this.m, func );
     381        __dtor_enter( this.m, func );
    349382}
    350383
     
    352385void ^?{}( monitor_dtor_guard_t & this ) {
    353386        // Leave the monitors in order
    354         __leave_dtor_monitor_desc( this.m );
     387        __dtor_leave( this.m );
    355388
    356389        // Restore thread context
     
    360393//-----------------------------------------------------------------------------
    361394// Internal scheduling types
    362 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
     395void ?{}(__condition_node_t & this, $thread * waiting_thread, __lock_size_t count, uintptr_t user_info ) {
    363396        this.waiting_thread = waiting_thread;
    364397        this.count = count;
    365         this.next = NULL;
     398        this.next = 0p;
    366399        this.user_info = user_info;
    367400}
     
    369402void ?{}(__condition_criterion_t & this ) with( this ) {
    370403        ready  = false;
    371         target = NULL;
    372         owner  = NULL;
    373         next   = NULL;
    374 }
    375 
    376 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t & owner ) {
     404        target = 0p;
     405        owner  = 0p;
     406        next   = 0p;
     407}
     408
     409void ?{}(__condition_criterion_t & this, $monitor * target, __condition_node_t & owner ) {
    377410        this.ready  = false;
    378411        this.target = target;
    379412        this.owner  = &owner;
    380         this.next   = NULL;
     413        this.next   = 0p;
    381414}
    382415
     
    387420
    388421        // Check that everything is as expected
    389         assertf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
     422        assertf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
    390423        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    391424        verifyf( this.monitor_count < 32u, "Excessive monitor count (%"PRIiFAST16")", this.monitor_count );
     
    399432        // Append the current wait operation to the ones already queued on the condition
    400433        // We don't need locks for that since conditions must always be waited on inside monitor mutual exclusion
     434        /* paranoid */ verify( waiter.next == 0p );
    401435        append( this.blocked, &waiter );
     436        /* paranoid */ verify( waiter.next == 1p );
    402437
    403438        // Lock all monitors (aggregates the locks as well)
     
    406441        // Find the next thread(s) to run
    407442        __lock_size_t thread_count = 0;
    408         thread_desc * threads[ count ];
     443        $thread * threads[ count ];
    409444        __builtin_memset( threads, 0, sizeof( threads ) );
    410445
     
    414449        // Remove any duplicate threads
    415450        for( __lock_size_t i = 0; i < count; i++) {
    416                 thread_desc * new_owner = next_thread( monitors[i] );
     451                $thread * new_owner = next_thread( monitors[i] );
    417452                insert_unique( threads, thread_count, new_owner );
    418453        }
    419454
     455        // Unlock the locks, we don't need them anymore
     456        for(int i = 0; i < count; i++) {
     457                unlock( *locks[i] );
     458        }
     459
     460        // Wake the threads
     461        for(int i = 0; i < thread_count; i++) {
     462                unpark( threads[i] );
     463        }
     464
    420465        // Everything is ready to go to sleep
    421         BlockInternal( locks, count, threads, thread_count );
     466        park();
    422467
    423468        // We are back, restore the owners and recursions
     
    434479        //Some more checking in debug
    435480        __cfaabi_dbg_debug_do(
    436                 thread_desc * this_thrd = TL_GET( this_thread );
     481                $thread * this_thrd = TL_GET( this_thread );
    437482                if ( this.monitor_count != this_thrd->monitors.size ) {
    438483                        abort( "Signal on condition %p made with different number of monitor(s), expected %zi got %zi", &this, this.monitor_count, this_thrd->monitors.size );
     
    449494
    450495        // Lock all monitors
    451         lock_all( this.monitors, NULL, count );
     496        lock_all( this.monitors, 0p, count );
    452497
    453498        //Pop the head of the waiting queue
     
    471516
    472517        //Check that everything is as expected
    473         verifyf( this.monitors != NULL, "Waiting with no monitors (%p)", this.monitors );
     518        verifyf( this.monitors != 0p, "Waiting with no monitors (%p)", this.monitors );
    474519        verifyf( this.monitor_count != 0, "Waiting with 0 monitors (%"PRIiFAST16")", this.monitor_count );
    475520
     
    488533
    489534        //Find the thread to run
    490         thread_desc * signallee = pop_head( this.blocked )->waiting_thread;
    491         set_owner( monitors, count, signallee );
     535        $thread * signallee = pop_head( this.blocked )->waiting_thread;
     536        /* paranoid */ verify( signallee->next == 0p );
     537        __set_owner( monitors, count, signallee );
    492538
    493539        __cfaabi_dbg_print_buffer_decl( "Kernel : signal_block condition %p (s: %p)\n", &this, signallee );
    494540
     541        // unlock all the monitors
     542        unlock_all( locks, count );
     543
     544        // unpark the thread we signalled
     545        unpark( signallee );
     546
    495547        //Everything is ready to go to sleep
    496         BlockInternal( locks, count, &signallee, 1 );
     548        park();
    497549
    498550
     
    535587        // Create one!
    536588        __lock_size_t max = count_max( mask );
    537         monitor_desc * mon_storage[max];
     589        $monitor * mon_storage[max];
    538590        __builtin_memset( mon_storage, 0, sizeof( mon_storage ) );
    539591        __lock_size_t actual_count = aggregate( mon_storage, mask );
     
    553605        {
    554606                // Check if the entry queue
    555                 thread_desc * next; int index;
     607                $thread * next; int index;
    556608                [next, index] = search_entry_queue( mask, monitors, count );
    557609
     
    563615                                verifyf( accepted.size == 1,  "ERROR: Accepted dtor has more than 1 mutex parameter." );
    564616
    565                                 monitor_desc * mon2dtor = accepted[0];
     617                                $monitor * mon2dtor = accepted[0];
    566618                                verifyf( mon2dtor->dtor_node, "ERROR: Accepted monitor has no dtor_node." );
    567619
     
    589641
    590642                                // Set the owners to be the next thread
    591                                 set_owner( monitors, count, next );
    592 
    593                                 // Everything is ready to go to sleep
    594                                 BlockInternal( locks, count, &next, 1 );
     643                                __set_owner( monitors, count, next );
     644
     645                                // unlock all the monitors
     646                                unlock_all( locks, count );
     647
     648                                // unpark the thread we signalled
     649                                unpark( next );
     650
     651                                //Everything is ready to go to sleep
     652                                park();
    595653
    596654                                // We are back, restore the owners and recursions
     
    630688        }
    631689
     690        // unlock all the monitors
     691        unlock_all( locks, count );
     692
    632693        //Everything is ready to go to sleep
    633         BlockInternal( locks, count );
     694        park();
    634695
    635696
     
    648709// Utilities
    649710
    650 static inline void set_owner( monitor_desc * this, thread_desc * owner ) {
    651         // __cfaabi_dbg_print_safe( "Kernal :   Setting owner of %p to %p ( was %p)\n", this, owner, this->owner );
     711static inline void __set_owner( $monitor * this, $thread * owner ) {
     712        /* paranoid */ verify( this->lock.lock );
    652713
    653714        //Pass the monitor appropriately
     
    658719}
    659720
    660 static inline void set_owner( monitor_desc * monitors [], __lock_size_t count, thread_desc * owner ) {
    661         monitors[0]->owner     = owner;
    662         monitors[0]->recursion = 1;
     721static inline void __set_owner( $monitor * monitors [], __lock_size_t count, $thread * owner ) {
     722        /* paranoid */ verify ( monitors[0]->lock.lock );
     723        /* paranoid */ verifyf( monitors[0]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[0]->owner, monitors[0]->recursion, monitors[0] );
     724        monitors[0]->owner        = owner;
     725        monitors[0]->recursion    = 1;
    663726        for( __lock_size_t i = 1; i < count; i++ ) {
    664                 monitors[i]->owner     = owner;
    665                 monitors[i]->recursion = 0;
    666         }
    667 }
    668 
    669 static inline void set_mask( monitor_desc * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {
     727                /* paranoid */ verify ( monitors[i]->lock.lock );
     728                /* paranoid */ verifyf( monitors[i]->owner == kernelTLS.this_thread, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, monitors[i]->owner, monitors[i]->recursion, monitors[i] );
     729                monitors[i]->owner        = owner;
     730                monitors[i]->recursion    = 0;
     731        }
     732}
     733
     734static inline void set_mask( $monitor * storage [], __lock_size_t count, const __waitfor_mask_t & mask ) {
    670735        for( __lock_size_t i = 0; i < count; i++) {
    671736                storage[i]->mask = mask;
     
    673738}
    674739
    675 static inline void reset_mask( monitor_desc * this ) {
    676         this->mask.accepted = NULL;
    677         this->mask.data = NULL;
     740static inline void reset_mask( $monitor * this ) {
     741        this->mask.accepted = 0p;
     742        this->mask.data = 0p;
    678743        this->mask.size = 0;
    679744}
    680745
    681 static inline thread_desc * next_thread( monitor_desc * this ) {
     746static inline $thread * next_thread( $monitor * this ) {
    682747        //Check the signaller stack
    683748        __cfaabi_dbg_print_safe( "Kernel :  mon %p AS-stack top %p\n", this, this->signal_stack.top);
     
    687752                //regardless of if we are ready to baton pass,
    688753                //we need to set the monitor as in use
    689                 set_owner( this,  urgent->owner->waiting_thread );
     754                /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     755                __set_owner( this,  urgent->owner->waiting_thread );
    690756
    691757                return check_condition( urgent );
     
    694760        // No signaller thread
    695761        // Get the next thread in the entry_queue
    696         thread_desc * new_owner = pop_head( this->entry_queue );
    697         set_owner( this, new_owner );
     762        $thread * new_owner = pop_head( this->entry_queue );
     763        /* paranoid */ verifyf( !this->owner || kernelTLS.this_thread == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", kernelTLS.this_thread, this->owner, this->recursion, this );
     764        /* paranoid */ verify( !new_owner || new_owner->next == 0p );
     765        __set_owner( this, new_owner );
    698766
    699767        return new_owner;
    700768}
    701769
    702 static inline bool is_accepted( monitor_desc * this, const __monitor_group_t & group ) {
     770static inline bool is_accepted( $monitor * this, const __monitor_group_t & group ) {
    703771        __acceptable_t * it = this->mask.data; // Optim
    704772        __lock_size_t count = this->mask.size;
     
    722790}
    723791
    724 static inline void init( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     792static inline void init( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    725793        for( __lock_size_t i = 0; i < count; i++) {
    726794                (criteria[i]){ monitors[i], waiter };
     
    730798}
    731799
    732 static inline void init_push( __lock_size_t count, monitor_desc * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
     800static inline void init_push( __lock_size_t count, $monitor * monitors [], __condition_node_t & waiter, __condition_criterion_t criteria [] ) {
    733801        for( __lock_size_t i = 0; i < count; i++) {
    734802                (criteria[i]){ monitors[i], waiter };
     
    746814}
    747815
    748 static inline void lock_all( monitor_desc * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
     816static inline void lock_all( $monitor * source [], __spinlock_t * /*out*/ locks [], __lock_size_t count ) {
    749817        for( __lock_size_t i = 0; i < count; i++ ) {
    750818                __spinlock_t * l = &source[i]->lock;
     
    760828}
    761829
    762 static inline void unlock_all( monitor_desc * locks [], __lock_size_t count ) {
     830static inline void unlock_all( $monitor * locks [], __lock_size_t count ) {
    763831        for( __lock_size_t i = 0; i < count; i++ ) {
    764832                unlock( locks[i]->lock );
     
    767835
    768836static inline void save(
    769         monitor_desc * ctx [],
     837        $monitor * ctx [],
    770838        __lock_size_t count,
    771839        __attribute((unused)) __spinlock_t * locks [],
     
    780848
    781849static inline void restore(
    782         monitor_desc * ctx [],
     850        $monitor * ctx [],
    783851        __lock_size_t count,
    784852        __spinlock_t * locks [],
     
    798866// 2 - Checks if all the monitors are ready to run
    799867//     if so return the thread to run
    800 static inline thread_desc * check_condition( __condition_criterion_t * target ) {
     868static inline $thread * check_condition( __condition_criterion_t * target ) {
    801869        __condition_node_t * node = target->owner;
    802870        unsigned short count = node->count;
     
    816884        }
    817885
    818         __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : NULL );
    819         return ready2run ? node->waiting_thread : NULL;
     886        __cfaabi_dbg_print_safe( "Kernel :  Runing %i (%p)\n", ready2run, ready2run ? node->waiting_thread : 0p );
     887        return ready2run ? node->waiting_thread : 0p;
    820888}
    821889
    822890static inline void brand_condition( condition & this ) {
    823         thread_desc * thrd = TL_GET( this_thread );
     891        $thread * thrd = TL_GET( this_thread );
    824892        if( !this.monitors ) {
    825893                // __cfaabi_dbg_print_safe( "Branding\n" );
    826                 assertf( thrd->monitors.data != NULL, "No current monitor to brand condition %p", thrd->monitors.data );
     894                assertf( thrd->monitors.data != 0p, "No current monitor to brand condition %p", thrd->monitors.data );
    827895                this.monitor_count = thrd->monitors.size;
    828896
    829                 this.monitors = (monitor_desc **)malloc( this.monitor_count * sizeof( *this.monitors ) );
     897                this.monitors = ($monitor **)malloc( this.monitor_count * sizeof( *this.monitors ) );
    830898                for( int i = 0; i < this.monitor_count; i++ ) {
    831899                        this.monitors[i] = thrd->monitors[i];
     
    834902}
    835903
    836 static inline [thread_desc *, int] search_entry_queue( const __waitfor_mask_t & mask, monitor_desc * monitors [], __lock_size_t count ) {
    837 
    838         __queue_t(thread_desc) & entry_queue = monitors[0]->entry_queue;
     904static inline [$thread *, int] search_entry_queue( const __waitfor_mask_t & mask, $monitor * monitors [], __lock_size_t count ) {
     905
     906        __queue_t($thread) & entry_queue = monitors[0]->entry_queue;
    839907
    840908        // For each thread in the entry-queue
    841         for(    thread_desc ** thrd_it = &entry_queue.head;
    842                 *thrd_it;
     909        for(    $thread ** thrd_it = &entry_queue.head;
     910                *thrd_it != 1p;
    843911                thrd_it = &(*thrd_it)->next
    844912        ) {
     
    883951}
    884952
    885 static inline __lock_size_t aggregate( monitor_desc * storage [], const __waitfor_mask_t & mask ) {
     953static inline __lock_size_t aggregate( $monitor * storage [], const __waitfor_mask_t & mask ) {
    886954        __lock_size_t size = 0;
    887955        for( __lock_size_t i = 0; i < mask.size; i++ ) {
  • libcfa/src/concurrency/monitor.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thd Feb 23 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Oct  7 18:06:45 2017
    13 // Update Count     : 10
     12// Last Modified On : Wed Dec  4 07:55:32 2019
     13// Update Count     : 11
    1414//
    1515
     
    2323
    2424trait is_monitor(dtype T) {
    25         monitor_desc * get_monitor( T & );
     25        $monitor * get_monitor( T & );
    2626        void ^?{}( T & mutex );
    2727};
    2828
    29 static inline void ?{}(monitor_desc & this) with( this ) {
     29static inline void ?{}($monitor & this) with( this ) {
    3030        lock{};
    3131        entry_queue{};
    3232        signal_stack{};
    33         owner         = NULL;
     33        owner         = 0p;
    3434        recursion     = 0;
    35         mask.accepted = NULL;
    36         mask.data     = NULL;
     35        mask.accepted = 0p;
     36        mask.data     = 0p;
    3737        mask.size     = 0;
    38         dtor_node     = NULL;
     38        dtor_node     = 0p;
    3939}
    4040
     41static inline void ^?{}($monitor & ) {}
     42
    4143struct monitor_guard_t {
    42         monitor_desc **         m;
     44        $monitor **     m;
    4345        __lock_size_t           count;
    4446        __monitor_group_t prev;
    4547};
    4648
    47 void ?{}( monitor_guard_t & this, monitor_desc ** m, __lock_size_t count, void (*func)() );
     49void ?{}( monitor_guard_t & this, $monitor ** m, __lock_size_t count, void (*func)() );
    4850void ^?{}( monitor_guard_t & this );
    4951
    5052struct monitor_dtor_guard_t {
    51         monitor_desc *    m;
     53        $monitor *    m;
    5254        __monitor_group_t prev;
    5355};
    5456
    55 void ?{}( monitor_dtor_guard_t & this, monitor_desc ** m, void (*func)() );
     57void ?{}( monitor_dtor_guard_t & this, $monitor ** m, void (*func)() );
    5658void ^?{}( monitor_dtor_guard_t & this );
    5759
     
    7072
    7173        // The monitor this criterion concerns
    72         monitor_desc * target;
     74        $monitor * target;
    7375
    7476        // The parent node to which this criterion belongs
     
    8587struct __condition_node_t {
    8688        // Thread that needs to be woken when all criteria are met
    87         thread_desc * waiting_thread;
     89        $thread * waiting_thread;
    8890
    8991        // Array of criteria (Criterions are contiguous in memory)
     
    104106}
    105107
    106 void ?{}(__condition_node_t & this, thread_desc * waiting_thread, __lock_size_t count, uintptr_t user_info );
     108void ?{}(__condition_node_t & this, $thread * waiting_thread, __lock_size_t count, uintptr_t user_info );
    107109void ?{}(__condition_criterion_t & this );
    108 void ?{}(__condition_criterion_t & this, monitor_desc * target, __condition_node_t * owner );
     110void ?{}(__condition_criterion_t & this, $monitor * target, __condition_node_t * owner );
    109111
    110112struct condition {
     
    113115
    114116        // Array of monitor pointers (Monitors are NOT contiguous in memory)
    115         monitor_desc ** monitors;
     117        $monitor ** monitors;
    116118
    117119        // Number of monitors in the array
     
    120122
    121123static inline void ?{}( condition & this ) {
    122         this.monitors = NULL;
     124        this.monitors = 0p;
    123125        this.monitor_count = 0;
    124126}
     
    131133              bool signal      ( condition & this );
    132134              bool signal_block( condition & this );
    133 static inline bool is_empty    ( condition & this ) { return !this.blocked.head; }
     135static inline bool is_empty    ( condition & this ) { return this.blocked.head == 1p; }
    134136         uintptr_t front       ( condition & this );
    135137
  • libcfa/src/concurrency/mutex.cfa

    r9fb8f01 r3d5701e  
    1111// Author           : Thierry Delisle
    1212// Created On       : Fri May 25 01:37:11 2018
    13 // Last Modified By : Thierry Delisle
    14 // Last Modified On : Fri May 25 01:37:51 2018
    15 // Update Count     : 0
     13// Last Modified By : Peter A. Buhr
     14// Last Modified On : Wed Dec  4 09:16:39 2019
     15// Update Count     : 1
    1616//
    1717
     
    4040        if( is_locked ) {
    4141                append( blocked_threads, kernelTLS.this_thread );
    42                 BlockInternal( &lock );
     42                unlock( lock );
     43                park();
    4344        }
    4445        else {
     
    6263        lock( this.lock __cfaabi_dbg_ctx2 );
    6364        this.is_locked = (this.blocked_threads != 0);
    64         WakeThread(
     65        unpark(
    6566                pop_head( this.blocked_threads )
    6667        );
     
    7374        this.lock{};
    7475        this.blocked_threads{};
    75         this.owner = NULL;
     76        this.owner = 0p;
    7677        this.recursion_count = 0;
    7778}
     
    8384void lock(recursive_mutex_lock & this) with(this) {
    8485        lock( lock __cfaabi_dbg_ctx2 );
    85         if( owner == NULL ) {
     86        if( owner == 0p ) {
    8687                owner = kernelTLS.this_thread;
    8788                recursion_count = 1;
     
    9495        else {
    9596                append( blocked_threads, kernelTLS.this_thread );
    96                 BlockInternal( &lock );
     97                unlock( lock );
     98                park();
    9799        }
    98100}
     
    101103        bool ret = false;
    102104        lock( lock __cfaabi_dbg_ctx2 );
    103         if( owner == NULL ) {
     105        if( owner == 0p ) {
    104106                owner = kernelTLS.this_thread;
    105107                recursion_count = 1;
     
    118120        recursion_count--;
    119121        if( recursion_count == 0 ) {
    120                 thread_desc * thrd = pop_head( blocked_threads );
     122                $thread * thrd = pop_head( blocked_threads );
    121123                owner = thrd;
    122124                recursion_count = (thrd ? 1 : 0);
    123                 WakeThread( thrd );
     125                unpark( thrd );
    124126        }
    125127        unlock( lock );
     
    138140void notify_one(condition_variable & this) with(this) {
    139141        lock( lock __cfaabi_dbg_ctx2 );
    140         WakeThread(
     142        unpark(
    141143                pop_head( this.blocked_threads )
    142144        );
     
    147149        lock( lock __cfaabi_dbg_ctx2 );
    148150        while(this.blocked_threads) {
    149                 WakeThread(
     151                unpark(
    150152                        pop_head( this.blocked_threads )
    151153                );
     
    157159        lock( this.lock __cfaabi_dbg_ctx2 );
    158160        append( this.blocked_threads, kernelTLS.this_thread );
    159         BlockInternal( &this.lock );
     161        unlock( this.lock );
     162        park();
    160163}
    161164
     
    164167        lock( this.lock __cfaabi_dbg_ctx2 );
    165168        append( this.blocked_threads, kernelTLS.this_thread );
    166         void __unlock(void) {
    167                 unlock(l);
    168                 unlock(this.lock);
    169         }
    170         BlockInternal( __unlock );
     169        unlock(l);
     170        unlock(this.lock);
     171        park();
    171172        lock(l);
    172173}
  • libcfa/src/concurrency/mutex.hfa

    r9fb8f01 r3d5701e  
    1111// Author           : Thierry Delisle
    1212// Created On       : Fri May 25 01:24:09 2018
    13 // Last Modified By : Thierry Delisle
    14 // Last Modified On : Fri May 25 01:24:12 2018
    15 // Update Count     : 0
     13// Last Modified By : Peter A. Buhr
     14// Last Modified On : Wed Dec  4 09:16:53 2019
     15// Update Count     : 1
    1616//
    1717
     
    3636
    3737        // List of blocked threads
    38         __queue_t(struct thread_desc) blocked_threads;
     38        __queue_t(struct $thread) blocked_threads;
    3939
    4040        // Locked flag
     
    5555
    5656        // List of blocked threads
    57         __queue_t(struct thread_desc) blocked_threads;
     57        __queue_t(struct $thread) blocked_threads;
    5858
    5959        // Current thread owning the lock
    60         struct thread_desc * owner;
     60        struct $thread * owner;
    6161
    6262        // Number of recursion level
     
    8383
    8484        // List of blocked threads
    85         __queue_t(struct thread_desc) blocked_threads;
     85        __queue_t(struct $thread) blocked_threads;
    8686};
    8787
     
    110110
    111111        static inline void ?{}(lock_scope(L) & this) {
    112                 this.locks = NULL;
     112                this.locks = 0p;
    113113                this.count = 0;
    114114        }
  • libcfa/src/concurrency/preemption.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Jun 5 14:20:42 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jun  5 17:35:49 2018
    13 // Update Count     : 37
     12// Last Modified On : Thu Dec  5 16:34:05 2019
     13// Update Count     : 43
    1414//
    1515
     
    2424#include <string.h>
    2525#include <unistd.h>
     26#include <limits.h>                                                                             // PTHREAD_STACK_MIN
    2627}
    2728
     
    3839// FwdDeclarations : timeout handlers
    3940static void preempt( processor   * this );
    40 static void timeout( thread_desc * this );
     41static void timeout( $thread * this );
    4142
    4243// FwdDeclarations : Signal handlers
     
    6465event_kernel_t * event_kernel;                        // kernel public handle to even kernel
    6566static pthread_t alarm_thread;                        // pthread handle to alarm thread
     67static void * alarm_stack;                                                        // pthread stack for alarm thread
    6668
    6769static void ?{}(event_kernel_t & this) with( this ) {
     
    8183// Get next expired node
    8284static inline alarm_node_t * get_expired( alarm_list_t * alarms, Time currtime ) {
    83         if( !alarms->head ) return NULL;                          // If no alarms return null
    84         if( alarms->head->alarm >= currtime ) return NULL;        // If alarms head not expired return null
    85         return pop(alarms);                                       // Otherwise just pop head
     85        if( !alarms->head ) return 0p;                                          // If no alarms return null
     86        if( alarms->head->alarm >= currtime ) return 0p;        // If alarms head not expired return null
     87        return pop(alarms);                                                                     // Otherwise just pop head
    8688}
    8789
    8890// Tick one frame of the Discrete Event Simulation for alarms
    8991static void tick_preemption() {
    90         alarm_node_t * node = NULL;                     // Used in the while loop but cannot be declared in the while condition
    91         alarm_list_t * alarms = &event_kernel->alarms;  // Local copy for ease of reading
    92         Time currtime = __kernel_get_time();                    // Check current time once so we everything "happens at once"
     92        alarm_node_t * node = 0p;                                                       // Used in the while loop but cannot be declared in the while condition
     93        alarm_list_t * alarms = &event_kernel->alarms;          // Local copy for ease of reading
     94        Time currtime = __kernel_get_time();                            // Check current time once so everything "happens at once"
    9395
    9496        //Loop throught every thing expired
     
    182184
    183185        // Enable interrupts by decrementing the counter
    184         // If counter reaches 0, execute any pending CtxSwitch
     186        // If counter reaches 0, execute any pending __cfactx_switch
    185187        void enable_interrupts( __cfaabi_dbg_ctx_param ) {
    186188                processor   * proc = kernelTLS.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
    187                 thread_desc * thrd = kernelTLS.this_thread;       // Cache the thread now since interrupts can start happening after the atomic store
    188189
    189190                with( kernelTLS.preemption_state ){
     
    207208                                if( proc->pending_preemption ) {
    208209                                        proc->pending_preemption = false;
    209                                         BlockInternal( thrd );
     210                                        force_yield( __POLL_PREEMPTION );
    210211                                }
    211212                        }
     
    217218
    218219        // Disable interrupts by incrementint the counter
    219         // Don't execute any pending CtxSwitch even if counter reaches 0
     220        // Don't execute any pending __cfactx_switch even if counter reaches 0
    220221        void enable_interrupts_noPoll() {
    221222                unsigned short prev = kernelTLS.preemption_state.disable_count;
     
    243244        sigaddset( &mask, sig );
    244245
    245         if ( pthread_sigmask( SIG_UNBLOCK, &mask, NULL ) == -1 ) {
     246        if ( pthread_sigmask( SIG_UNBLOCK, &mask, 0p ) == -1 ) {
    246247            abort( "internal error, pthread_sigmask" );
    247248        }
     
    254255        sigaddset( &mask, sig );
    255256
    256         if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     257        if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    257258            abort( "internal error, pthread_sigmask" );
    258259        }
     
    266267
    267268// reserved for future use
    268 static void timeout( thread_desc * this ) {
     269static void timeout( $thread * this ) {
    269270        //TODO : implement waking threads
    270271}
    271272
    272273// KERNEL ONLY
    273 // Check if a CtxSwitch signal handler shoud defer
     274// Check if a __cfactx_switch signal handler shoud defer
    274275// If true  : preemption is safe
    275276// If false : preemption is unsafe and marked as pending
     
    301302
    302303        // Setup proper signal handlers
    303         __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART );         // CtxSwitch handler
     304        __cfaabi_sigaction( SIGUSR1, sigHandler_ctxSwitch, SA_SIGINFO | SA_RESTART ); // __cfactx_switch handler
    304305
    305306        signal_block( SIGALRM );
    306307
    307         pthread_create( &alarm_thread, NULL, alarm_loop, NULL );
     308        alarm_stack = __create_pthread( &alarm_thread, alarm_loop, 0p );
    308309}
    309310
     
    316317        sigset_t mask;
    317318        sigfillset( &mask );
    318         sigprocmask( SIG_BLOCK, &mask, NULL );
     319        sigprocmask( SIG_BLOCK, &mask, 0p );
    319320
    320321        // Notify the alarm thread of the shutdown
     
    323324
    324325        // Wait for the preemption thread to finish
    325         pthread_join( alarm_thread, NULL );
     326
     327        pthread_join( alarm_thread, 0p );
     328        free( alarm_stack );
    326329
    327330        // Preemption is now fully stopped
     
    380383        static_assert( sizeof( sigset_t ) == sizeof( cxt->uc_sigmask ), "Expected cxt->uc_sigmask to be of sigset_t" );
    381384        #endif
    382         if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), NULL ) == -1 ) {
     385        if ( pthread_sigmask( SIG_SETMASK, (sigset_t *)&(cxt->uc_sigmask), 0p ) == -1 ) {
    383386                abort( "internal error, sigprocmask" );
    384387        }
     
    390393        // Preemption can occur here
    391394
    392         BlockInternal( kernelTLS.this_thread ); // Do the actual CtxSwitch
     395        force_yield( __ALARM_PREEMPTION ); // Do the actual __cfactx_switch
    393396}
    394397
     
    399402        sigset_t mask;
    400403        sigfillset(&mask);
    401         if ( pthread_sigmask( SIG_BLOCK, &mask, NULL ) == -1 ) {
     404        if ( pthread_sigmask( SIG_BLOCK, &mask, 0p ) == -1 ) {
    402405            abort( "internal error, pthread_sigmask" );
    403406        }
     
    420423                                        {__cfaabi_dbg_print_buffer_decl( " KERNEL: Spurious wakeup %d.\n", err );}
    421424                                        continue;
    422                         case EINVAL :
     425                                case EINVAL :
    423426                                        abort( "Timeout was invalid." );
    424427                                default:
     
    453456EXIT:
    454457        __cfaabi_dbg_print_safe( "Kernel : Preemption thread stopping\n" );
    455         return NULL;
     458        return 0p;
    456459}
    457460
     
    466469        sigset_t oldset;
    467470        int ret;
    468         ret = pthread_sigmask(0, NULL, &oldset);
     471        ret = pthread_sigmask(0, 0p, &oldset);
    469472        if(ret != 0) { abort("ERROR sigprocmask returned %d", ret); }
    470473
  • libcfa/src/concurrency/thread.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Mar 30 17:19:52 2018
    13 // Update Count     : 8
     12// Last Modified On : Wed Dec  4 09:17:49 2019
     13// Update Count     : 9
    1414//
    1515
     
    2323#include "invoke.h"
    2424
    25 extern "C" {
    26         #include <fenv.h>
    27         #include <stddef.h>
    28 }
    29 
    30 //extern volatile thread_local processor * this_processor;
    31 
    3225//-----------------------------------------------------------------------------
    3326// Thread ctors and dtors
    34 void ?{}(thread_desc & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
    35         context{ NULL, NULL };
     27void ?{}($thread & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
     28        context{ 0p, 0p };
    3629        self_cor{ name, storage, storageSize };
    3730        state = Start;
     31        preempted = __NO_PREEMPTION;
    3832        curr_cor = &self_cor;
    3933        self_mon.owner = &this;
     
    4135        self_mon_p = &self_mon;
    4236        curr_cluster = &cl;
    43         next = NULL;
     37        next = 0p;
    4438
    45         node.next = NULL;
    46         node.prev = NULL;
     39        node.next = 0p;
     40        node.prev = 0p;
    4741        doregister(curr_cluster, this);
    4842
     
    5044}
    5145
    52 void ^?{}(thread_desc& this) with( this ) {
     46void ^?{}($thread& this) with( this ) {
    5347        unregister(curr_cluster, this);
    5448        ^self_cor{};
    5549}
    5650
     51//-----------------------------------------------------------------------------
     52// Starting and stopping threads
     53forall( dtype T | is_thread(T) )
     54void __thrd_start( T & this, void (*main_p)(T &) ) {
     55        $thread * this_thrd = get_thread(this);
     56
     57        disable_interrupts();
     58        __cfactx_start(main_p, get_coroutine(this), this, __cfactx_invoke_thread);
     59
     60        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
     61        verify( this_thrd->context.SP );
     62
     63        __schedule_thread(this_thrd);
     64        enable_interrupts( __cfaabi_dbg_ctx );
     65}
     66
     67//-----------------------------------------------------------------------------
     68// Support for threads that don't ues the thread keyword
    5769forall( dtype T | sized(T) | is_thread(T) | { void ?{}(T&); } )
    5870void ?{}( scoped(T)& this ) with( this ) {
    5971        handle{};
    60         __thrd_start(handle);
     72        __thrd_start(handle, main);
    6173}
    6274
     
    6476void ?{}( scoped(T)& this, P params ) with( this ) {
    6577        handle{ params };
    66         __thrd_start(handle);
     78        __thrd_start(handle, main);
    6779}
    6880
     
    7284}
    7385
    74 //-----------------------------------------------------------------------------
    75 // Starting and stopping threads
    76 forall( dtype T | is_thread(T) )
    77 void __thrd_start( T& this ) {
    78         thread_desc * this_thrd = get_thread(this);
    79         thread_desc * curr_thrd = TL_GET( this_thread );
    80 
    81         disable_interrupts();
    82         CtxStart(&this, CtxInvokeThread);
    83         this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
    84         verify( this_thrd->context.SP );
    85         CtxSwitch( &curr_thrd->context, &this_thrd->context );
    86 
    87         ScheduleThread(this_thrd);
    88         enable_interrupts( __cfaabi_dbg_ctx );
    89 }
    90 
    91 extern "C" {
    92         // KERNEL ONLY
    93         void __finish_creation(thread_desc * this) {
    94                 // set new coroutine that the processor is executing
    95                 // and context switch to it
    96                 verify( kernelTLS.this_thread != this );
    97                 verify( kernelTLS.this_thread->context.SP );
    98                 CtxSwitch( &this->context, &kernelTLS.this_thread->context );
    99         }
    100 }
    101 
    102 void yield( void ) {
    103         // Safety note : This could cause some false positives due to preemption
    104       verify( TL_GET( preemption_state.enabled ) );
    105         BlockInternal( TL_GET( this_thread ) );
    106         // Safety note : This could cause some false positives due to preemption
    107       verify( TL_GET( preemption_state.enabled ) );
    108 }
    109 
    110 void yield( unsigned times ) {
    111         for( unsigned i = 0; i < times; i++ ) {
    112                 yield();
    113         }
    114 }
    115 
    11686// Local Variables: //
    11787// mode: c //
  • libcfa/src/concurrency/thread.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jan 17 12:27:26 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 17:51:33 2019
    13 // Update Count     : 5
     12// Last Modified On : Wed Dec  4 09:18:14 2019
     13// Update Count     : 6
    1414//
    1515
     
    2828      void ^?{}(T& mutex this);
    2929      void main(T& this);
    30       thread_desc* get_thread(T& this);
     30      $thread* get_thread(T& this);
    3131};
    3232
    33 #define DECL_THREAD(X) thread_desc* get_thread(X& this) { return &this.__thrd; } void main(X& this)
     33// define that satisfies the trait without using the thread keyword
     34#define DECL_THREAD(X) $thread* get_thread(X& this) __attribute__((const)) { return &this.__thrd; } void main(X& this)
     35
     36// Inline getters for threads/coroutines/monitors
     37forall( dtype T | is_thread(T) )
     38static inline $coroutine* get_coroutine(T & this) __attribute__((const)) { return &get_thread(this)->self_cor; }
    3439
    3540forall( dtype T | is_thread(T) )
    36 static inline coroutine_desc* get_coroutine(T & this) {
    37         return &get_thread(this)->self_cor;
    38 }
     41static inline $monitor  * get_monitor  (T & this) __attribute__((const)) { return &get_thread(this)->self_mon; }
    3942
    40 forall( dtype T | is_thread(T) )
    41 static inline monitor_desc* get_monitor(T & this) {
    42         return &get_thread(this)->self_mon;
    43 }
     43static inline $coroutine* get_coroutine($thread * this) __attribute__((const)) { return &this->self_cor; }
     44static inline $monitor  * get_monitor  ($thread * this) __attribute__((const)) { return &this->self_mon; }
    4445
    45 static inline coroutine_desc* get_coroutine(thread_desc * this) {
    46         return &this->self_cor;
    47 }
    48 
    49 static inline monitor_desc* get_monitor(thread_desc * this) {
    50         return &this->self_mon;
    51 }
    52 
     46//-----------------------------------------------------------------------------
     47// forward declarations needed for threads
    5348extern struct cluster * mainCluster;
    5449
    5550forall( dtype T | is_thread(T) )
    56 void __thrd_start( T & this );
     51void __thrd_start( T & this, void (*)(T &) );
    5752
    5853//-----------------------------------------------------------------------------
    5954// Ctors and dtors
    60 void ?{}(thread_desc & this, const char * const name, struct cluster & cl, void * storage, size_t storageSize );
    61 void ^?{}(thread_desc & this);
     55void ?{}($thread & this, const char * const name, struct cluster & cl, void * storage, size_t storageSize );
     56void ^?{}($thread & this);
    6257
    63 static inline void ?{}(thread_desc & this)                                                                  { this{ "Anonymous Thread", *mainCluster, NULL, 65000 }; }
    64 static inline void ?{}(thread_desc & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, NULL, stackSize }; }
    65 static inline void ?{}(thread_desc & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
    66 static inline void ?{}(thread_desc & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, NULL, 65000 }; }
    67 static inline void ?{}(thread_desc & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, NULL, stackSize }; }
    68 static inline void ?{}(thread_desc & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
    69 static inline void ?{}(thread_desc & this, const char * const name)                                         { this{ name, *mainCluster, NULL, 65000 }; }
    70 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl )                   { this{ name, cl, NULL, 65000 }; }
    71 static inline void ?{}(thread_desc & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, NULL, stackSize }; }
     58static inline void ?{}($thread & this)                                                                  { this{ "Anonymous Thread", *mainCluster, 0p, 65000 }; }
     59static inline void ?{}($thread & this, size_t stackSize )                                               { this{ "Anonymous Thread", *mainCluster, 0p, stackSize }; }
     60static inline void ?{}($thread & this, void * storage, size_t storageSize )                             { this{ "Anonymous Thread", *mainCluster, storage, storageSize }; }
     61static inline void ?{}($thread & this, struct cluster & cl )                                            { this{ "Anonymous Thread", cl, 0p, 65000 }; }
     62static inline void ?{}($thread & this, struct cluster & cl, size_t stackSize )                          { this{ "Anonymous Thread", cl, 0p, stackSize }; }
     63static inline void ?{}($thread & this, struct cluster & cl, void * storage, size_t storageSize )        { this{ "Anonymous Thread", cl, storage, storageSize }; }
     64static inline void ?{}($thread & this, const char * const name)                                         { this{ name, *mainCluster, 0p, 65000 }; }
     65static inline void ?{}($thread & this, const char * const name, struct cluster & cl )                   { this{ name, cl, 0p, 65000 }; }
     66static inline void ?{}($thread & this, const char * const name, struct cluster & cl, size_t stackSize ) { this{ name, cl, 0p, stackSize }; }
    7267
    7368//-----------------------------------------------------------------------------
     
    8883void ^?{}( scoped(T)& this );
    8984
    90 void yield();
    91 void yield( unsigned times );
     85//-----------------------------------------------------------------------------
     86// Thread getters
     87static inline struct $thread * active_thread () { return TL_GET( this_thread ); }
    9288
    93 static inline struct thread_desc * active_thread () { return TL_GET( this_thread ); }
     89//-----------------------------------------------------------------------------
     90// Scheduler API
     91
     92//----------
     93// Park thread: block until corresponding call to unpark, won't block if unpark is already called
     94void park( void );
     95
     96//----------
     97// Unpark a thread, if the thread is already blocked, schedule it
     98//                  if the thread is not yet block, signal that it should rerun immediately
     99void unpark( $thread * this );
     100
     101forall( dtype T | is_thread(T) )
     102static inline void unpark( T & this ) { if(!&this) return; unpark( get_thread( this ) );}
     103
     104//----------
     105// Yield: force thread to block and be rescheduled
     106bool force_yield( enum __Preemption_Reason );
     107
     108static inline void yield() {
     109        force_yield(__MANUAL_PREEMPTION);
     110}
     111
     112// Yield: yield N times
     113static inline void yield( unsigned times ) {
     114        for( times ) {
     115                yield();
     116        }
     117}
    94118
    95119// Local Variables: //
  • libcfa/src/exception.c

    r9fb8f01 r3d5701e  
    6969
    7070
    71 // This macro should be the only thing that needs to change across machines.  Used in the personality function, way down
    72 // in termination.
     71// This macro should be the only thing that needs to change across machines.
     72// Used in the personality function, way down in termination.
    7373// struct _Unwind_Context * -> _Unwind_Reason_Code(*)(exception_t *)
    7474#define MATCHER_FROM_CONTEXT(ptr_to_context) \
     
    102102}
    103103
    104 // Do we control where exceptions get thrown even with concurency?  If not these are not quite thread safe, the cleanup
    105 // hook has to be added after the node is built but before it is made the top node.
     104// Do we control where exceptions get thrown even with concurency?
     105// If not these are not quite thread safe, the cleanup hook has to
     106// be added after the node is built but before it is made the top node.
    106107
    107108void __cfaabi_ehm__try_resume_setup(struct __cfaabi_ehm__try_resume_node * node,
     
    212213        _Unwind_Reason_Code ret = _Unwind_RaiseException( &this_exception_storage );
    213214
    214         // If we reach here it means something happened.  For resumption to work we need to find a way to return back to
    215         // here.  Most of them will probably boil down to setting a global flag and making the phase 1 either stop or
    216         // fail.  Causing an error on purpose may help avoiding unnecessary work but it might have some weird side
    217         // effects.  If we just pretend no handler was found that would work but may be expensive for no reason since we
    218         // will always search the whole stack.
     215        // If we reach here it means something happened. For resumption to work we need to find a way
     216        // to return back to here. Most of them will probably boil down to setting a global flag and
     217        // making the phase 1 either stop or fail. Causing an error on purpose may help avoiding
     218        // unnecessary work but it might have some weird side effects. If we just pretend no handler
     219        // was found that would work but may be expensive for no reason since we will always search
     220        // the whole stack.
    219221
    220222        if( ret == _URC_END_OF_STACK ) {
    221                 // No proper handler was found.  This can be handled in several way.  C++ calls std::terminate Here we
    222                 // force unwind the stack, basically raising a cancellation.
     223                // No proper handler was found. This can be handled in many ways, C++ calls std::terminate.
     224                // Here we force unwind the stack, basically raising a cancellation.
    223225                printf("Uncaught exception %p\n", &this_exception_storage);
    224226
     
    228230        }
    229231
    230         // We did not simply reach the end of the stack without finding a handler.  Something wen't wrong
     232        // We did not simply reach the end of the stack without finding a handler. This is an error.
    231233        printf("UNWIND ERROR %d after raise exception\n", ret);
    232234        abort();
     
    246248}
    247249
    248 #if defined(PIC)
    249 #warning Exceptions not yet supported when using Position-Independent Code
    250 __attribute__((noinline))
    251 void __cfaabi_ehm__try_terminate(void (*try_block)(),
    252                 void (*catch_block)(int index, exception_t * except),
    253                 __attribute__((unused)) int (*match_block)(exception_t * except)) {
    254         abort();
    255 }
    256 #else
    257 // This is our personality routine.  For every stack frame anotated with ".cfi_personality 0x3,__gcfa_personality_v0".
    258 // This function will be called twice when unwinding.  Once in the search phased and once in the cleanup phase.
     250#pragma GCC push_options
     251#pragma GCC optimize("O0")
     252
     253// This is our personality routine. For every stack frame annotated with
     254// ".cfi_personality 0x3,__gcfa_personality_v0" this function will be called twice when unwinding.
     255//  Once in the search phase and once in the cleanup phase.
    259256_Unwind_Reason_Code __gcfa_personality_v0 (
    260257                int version, _Unwind_Action actions, unsigned long long exceptionClass,
     
    264261
    265262        //__cfaabi_dbg_print_safe("CFA: 0x%lx\n", _Unwind_GetCFA(context));
    266         __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):", version, actions, exceptionClass, unwind_exception, context);
     263        __cfaabi_dbg_print_safe("Personality function (%d, %x, %llu, %p, %p):",
     264                        version, actions, exceptionClass, unwind_exception, context);
    267265
    268266        // If we've reached the end of the stack then there is nothing much we can do...
     
    291289        // Get the instuction pointer and a reading pointer into the exception table
    292290        lsda_header_info lsd_info;
    293         const unsigned char * cur_ptr = parse_lsda_header( context, lsd, &lsd_info);
     291        const unsigned char * cur_ptr = parse_lsda_header(context, lsd, &lsd_info);
    294292        _Unwind_Ptr instruction_ptr = _Unwind_GetIP( context );
    295293
     
    302300
    303301                // Decode the common stuff we have in here
    304                 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_start);
    305                 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_len);
    306                 cur_ptr = read_encoded_value (0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad);
    307                 cur_ptr = read_uleb128 (cur_ptr, &callsite_action);
     302                cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_start);
     303                cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_len);
     304                cur_ptr = read_encoded_value(0, lsd_info.call_site_encoding, cur_ptr, &callsite_landing_pad);
     305                cur_ptr = read_uleb128(cur_ptr, &callsite_action);
    308306
    309307                // Have we reach the correct frame info yet?
     
    316314                        void * ep = (void*)lsd_info.Start + callsite_start + callsite_len;
    317315                        void * ip = (void*)instruction_ptr;
    318                         __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n", bp, ep, ls, cs, cl, ip);
     316                        __cfaabi_dbg_print_safe("\nfound %p - %p (%p, %p, %p), looking for %p\n",
     317                                        bp, ep, ls, cs, cl, ip);
    319318#endif // __CFA_DEBUG_PRINT__
    320319                        continue;
    321320                }
    322321
    323                 // Have we gone too far
     322                // Have we gone too far?
    324323                if( lsd_info.Start + callsite_start > instruction_ptr ) {
    325324                        printf(" gone too far");
     
    331330                        // Which phase are we in
    332331                        if (actions & _UA_SEARCH_PHASE) {
    333                                 // Search phase, this means we probably found a potential handler and must check if it is a match
    334 
    335                                 // If we have arbitrarily decided that 0 means nothing to do and 1 means there is a potential handler
    336                                 // This doesn't seem to conflict the gcc default behavior
     332                                // In search phase, these means we found a potential handler we must check.
     333
     334                                // We have arbitrarily decided that 0 means nothing to do and 1 means there is
     335                                // a potential handler. This doesn't seem to conflict the gcc default behavior.
    337336                                if (callsite_action != 0) {
    338337                                        // Now we want to run some code to see if the handler matches
     
    351350                                        // The current apprach uses one exception table entry per try block
    352351                                        _uleb128_t imatcher;
    353                                         // Get the relative offset to the
    354                                         cur_ptr = read_uleb128 (cur_ptr, &imatcher);
    355 
    356                                         // Get a function pointer from the relative offset and call it
    357                                         // _Unwind_Reason_Code (*matcher)() = (_Unwind_Reason_Code (*)())lsd_info.LPStart + imatcher;
     352                                        // Get the relative offset to the {...}?
     353                                        cur_ptr = read_uleb128(cur_ptr, &imatcher);
    358354
    359355                                        _Unwind_Reason_Code (*matcher)(exception_t *) =
     
    414410}
    415411
    416 // Try statements are hoisted out see comments for details.  With this could probably be unique and simply linked from
    417 // libcfa but there is one problem left, see the exception table for details
     412// Try statements are hoisted out see comments for details. While this could probably be unique
     413// and simply linked from libcfa but there is one problem left, see the exception table for details
    418414__attribute__((noinline))
    419415void __cfaabi_ehm__try_terminate(void (*try_block)(),
     
    428424        // assembly works.
    429425
    430         // Setup the personality routine
     426        // Setup the personality routine and exception table.
     427#ifdef __PIC__
     428        asm volatile (".cfi_personality 0x9b,CFA.ref.__gcfa_personality_v0");
     429        asm volatile (".cfi_lsda 0x1b, .LLSDACFA2");
     430#else
    431431        asm volatile (".cfi_personality 0x3,__gcfa_personality_v0");
    432         // Setup the exception table
    433432        asm volatile (".cfi_lsda 0x3, .LLSDACFA2");
     433#endif
    434434
    435435        // Label which defines the start of the area for which the handler is setup.
     
    442442        asm volatile goto ("" : : : : CATCH );
    443443
    444         // Normal return
     444        // Normal return for when there is no throw.
    445445        return;
    446446
     
    459459}
    460460
    461 // Exception table data we need to generate.  While this is almost generic, the custom data refers to foo_try_match try
    462 // match, which is no way generic.  Some more works need to be done if we want to have a single call to the try routine.
    463 
     461// Exception table data we need to generate. While this is almost generic, the custom data refers
     462// to {*}try_terminate, which is no way generic. Some more works need to be done if we want to
     463// have a single call to the try routine.
     464
     465#ifdef __PIC__
    464466#if defined( __i386 ) || defined( __x86_64 )
    465467asm (
    466         //HEADER
     468        // HEADER
    467469        ".LFECFA1:\n"
    468470        "       .globl  __gcfa_personality_v0\n"
    469471        "       .section        .gcc_except_table,\"a\",@progbits\n"
    470         ".LLSDACFA2:\n"                                                 //TABLE header
     472        // TABLE HEADER (important field is the BODY length at the end)
     473        ".LLSDACFA2:\n"
    471474        "       .byte   0xff\n"
    472475        "       .byte   0xff\n"
    473476        "       .byte   0x1\n"
    474         "       .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n"         // BODY length
    475         // Body uses language specific data and therefore could be modified arbitrarily
    476         ".LLSDACSBCFA2:\n"                                              // BODY start
    477         "       .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n"               // Handled area start  (relative to start of function)
    478         "       .uleb128 .TRYEND-.TRYSTART\n"                           // Handled area length
    479         "       .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n"                          // Hanlder landing pad adress  (relative to start of function)
    480         "       .uleb128 1\n"                                           // Action code, gcc seems to use always 0
    481         ".LLSDACSECFA2:\n"                                              // BODY end
    482         "       .text\n"                                                        // TABLE footer
     477        "       .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n"
     478        // BODY (language specific data)
     479        // This uses language specific data and can be modified arbitrarily
     480        // We use handled area offset, handled area length,
     481        // handler landing pad offset and 1 (action code, gcc seems to use 0).
     482        ".LLSDACSBCFA2:\n"
     483        "       .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n"
     484        "       .uleb128 .TRYEND-.TRYSTART\n"
     485        "       .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n"
     486        "       .uleb128 1\n"
     487        ".LLSDACSECFA2:\n"
     488        // TABLE FOOTER
     489        "       .text\n"
     490        "       .size   __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"
     491);
     492
     493// Somehow this piece of helps with the resolution of debug symbols.
     494__attribute__((unused)) static const int dummy = 0;
     495
     496asm (
     497        // Add a hidden symbol which points at the function.
     498        "       .hidden CFA.ref.__gcfa_personality_v0\n"
     499        "       .weak   CFA.ref.__gcfa_personality_v0\n"
     500        // No clue what this does specifically
     501        "       .section        .data.rel.local.CFA.ref.__gcfa_personality_v0,\"awG\",@progbits,CFA.ref.__gcfa_personality_v0,comdat\n"
     502        "       .align 8\n"
     503        "       .type CFA.ref.__gcfa_personality_v0, @object\n"
     504        "       .size CFA.ref.__gcfa_personality_v0, 8\n"
     505        "CFA.ref.__gcfa_personality_v0:\n"
     506#if defined( __x86_64 )
     507        "       .quad __gcfa_personality_v0\n"
     508#else // then __i386
     509        "   .long __gcfa_personality_v0\n"
     510#endif
     511);
     512#else
     513#error Exception Handling: unknown architecture for position independent code.
     514#endif // __i386 || __x86_64
     515#else // __PIC__
     516#if defined( __i386 ) || defined( __x86_64 )
     517asm (
     518        // HEADER
     519        ".LFECFA1:\n"
     520        "       .globl  __gcfa_personality_v0\n"
     521        "       .section        .gcc_except_table,\"a\",@progbits\n"
     522        // TABLE HEADER (important field is the BODY length at the end)
     523        ".LLSDACFA2:\n"
     524        "       .byte   0xff\n"
     525        "       .byte   0xff\n"
     526        "       .byte   0x1\n"
     527        "       .uleb128 .LLSDACSECFA2-.LLSDACSBCFA2\n"
     528        // BODY (language specific data)
     529        ".LLSDACSBCFA2:\n"
     530        //      Handled area start (relative to start of function)
     531        "       .uleb128 .TRYSTART-__cfaabi_ehm__try_terminate\n"
     532        //      Handled area length
     533        "       .uleb128 .TRYEND-.TRYSTART\n"
     534        //      Handler landing pad address (relative to start of function)
     535        "       .uleb128 .CATCH-__cfaabi_ehm__try_terminate\n"
     536        //      Action code, gcc seems to always use 0.
     537        "       .uleb128 1\n"
     538        // TABLE FOOTER
     539        ".LLSDACSECFA2:\n"
     540        "       .text\n"
    483541        "       .size   __cfaabi_ehm__try_terminate, .-__cfaabi_ehm__try_terminate\n"
    484542        "       .ident  \"GCC: (Ubuntu 6.2.0-3ubuntu11~16.04) 6.2.0 20160901\"\n"
    485 //      "       .section        .note.GNU-stack,\"x\",@progbits\n"
     543        "       .section        .note.GNU-stack,\"x\",@progbits\n"
    486544);
     545#else
     546#error Exception Handling: unknown architecture for position dependent code.
    487547#endif // __i386 || __x86_64
    488 #endif //PIC
     548#endif // __PIC__
     549
     550#pragma GCC pop_options
  • libcfa/src/executor.cfa

    r9fb8f01 r3d5701e  
    88#include <stdio.h>
    99
    10 forall( otype T | is_node(T) | is_monitor(T) ) {
    11     monitor Buffer {                                    // unbounded buffer
    12         __queue_t( T ) queue;                           // unbounded list of work requests
    13         condition delay;
    14     }; // Buffer
    15 
     10forall( dtype T )
     11monitor Buffer {                                        // unbounded buffer
     12    __queue_t( T ) queue;                               // unbounded list of work requests
     13    condition delay;
     14}; // Buffer
     15forall( dtype T | is_node(T) ) {
    1616    void insert( Buffer( T ) & mutex buf, T * elem ) with(buf) {
    1717        append( queue, elem );                          // insert element into buffer
     
    2020
    2121    T * remove( Buffer( T ) & mutex buf ) with(buf) {
    22         if ( ! queue ) wait( delay );                   // no request to process ? => wait
    23         return pop_head( queue );
     22        if ( queue.head != 0 ) wait( delay );                   // no request to process ? => wait
     23//      return pop_head( queue );
    2424    } // remove
    2525} // distribution
  • libcfa/src/fstream.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul 15 18:11:26 2019
    13 // Update Count     : 349
     12// Last Modified On : Fri Feb  7 19:01:01 2020
     13// Update Count     : 363
    1414//
    1515
     
    3232
    3333void ?{}( ofstream & os, void * file ) {
    34         os.file = file;
    35         os.sepDefault = true;
    36         os.sepOnOff = false;
    37         os.nlOnOff = true;
    38         os.prt = false;
    39         os.sawNL = false;
     34        os.$file = file;
     35        os.$sepDefault = true;
     36        os.$sepOnOff = false;
     37        os.$nlOnOff = true;
     38        os.$prt = false;
     39        os.$sawNL = false;
     40        $sepSetCur( os, sepGet( os ) );
    4041        sepSet( os, " " );
    41         sepSetCur( os, sepGet( os ) );
    4242        sepSetTuple( os, ", " );
    4343} // ?{}
    4444
    4545// private
    46 bool sepPrt( ofstream & os ) { setNL( os, false ); return os.sepOnOff; }
    47 void sepReset( ofstream & os ) { os.sepOnOff = os.sepDefault; }
    48 void sepReset( ofstream & os, bool reset ) { os.sepDefault = reset; os.sepOnOff = os.sepDefault; }
    49 const char * sepGetCur( ofstream & os ) { return os.sepCur; }
    50 void sepSetCur( ofstream & os, const char * sepCur ) { os.sepCur = sepCur; }
    51 bool getNL( ofstream & os ) { return os.sawNL; }
    52 void setNL( ofstream & os, bool state ) { os.sawNL = state; }
    53 bool getANL( ofstream & os ) { return os.nlOnOff; }
    54 bool getPrt( ofstream & os ) { return os.prt; }
    55 void setPrt( ofstream & os, bool state ) { os.prt = state; }
     46bool $sepPrt( ofstream & os ) { $setNL( os, false ); return os.$sepOnOff; }
     47void $sepReset( ofstream & os ) { os.$sepOnOff = os.$sepDefault; }
     48void $sepReset( ofstream & os, bool reset ) { os.$sepDefault = reset; os.$sepOnOff = os.$sepDefault; }
     49const char * $sepGetCur( ofstream & os ) { return os.$sepCur; }
     50void $sepSetCur( ofstream & os, const char sepCur[] ) { os.$sepCur = sepCur; }
     51bool $getNL( ofstream & os ) { return os.$sawNL; }
     52void $setNL( ofstream & os, bool state ) { os.$sawNL = state; }
     53bool $getANL( ofstream & os ) { return os.$nlOnOff; }
     54bool $getPrt( ofstream & os ) { return os.$prt; }
     55void $setPrt( ofstream & os, bool state ) { os.$prt = state; }
    5656
    5757// public
    58 void ?{}( ofstream & os ) { os.file = 0; }
    59 
    60 void ?{}( ofstream & os, const char * name, const char * mode ) {
     58void ?{}( ofstream & os ) { os.$file = 0p; }
     59
     60void ?{}( ofstream & os, const char name[], const char mode[] ) {
    6161        open( os, name, mode );
    6262} // ?{}
    6363
    64 void ?{}( ofstream & os, const char * name ) {
     64void ?{}( ofstream & os, const char name[] ) {
    6565        open( os, name, "w" );
    6666} // ?{}
    6767
    68 void sepOn( ofstream & os ) { os.sepOnOff = ! getNL( os ); }
    69 void sepOff( ofstream & os ) { os.sepOnOff = false; }
     68void ^?{}( ofstream & os ) {
     69        close( os );
     70} // ^?{}
     71
     72void sepOn( ofstream & os ) { os.$sepOnOff = ! $getNL( os ); }
     73void sepOff( ofstream & os ) { os.$sepOnOff = false; }
    7074
    7175bool sepDisable( ofstream & os ) {
    72         bool temp = os.sepDefault;
    73         os.sepDefault = false;
    74         sepReset( os );
     76        bool temp = os.$sepDefault;
     77        os.$sepDefault = false;
     78        $sepReset( os );
    7579        return temp;
    7680} // sepDisable
    7781
    7882bool sepEnable( ofstream & os ) {
    79         bool temp = os.sepDefault;
    80         os.sepDefault = true;
    81         if ( os.sepOnOff ) sepReset( os );                                      // start of line ?
     83        bool temp = os.$sepDefault;
     84        os.$sepDefault = true;
     85        if ( os.$sepOnOff ) $sepReset( os );                            // start of line ?
    8286        return temp;
    8387} // sepEnable
    8488
    85 void nlOn( ofstream & os ) { os.nlOnOff = true; }
    86 void nlOff( ofstream & os ) { os.nlOnOff = false; }
    87 
    88 const char * sepGet( ofstream & os ) { return os.separator; }
    89 void sepSet( ofstream & os, const char * s ) {
     89void nlOn( ofstream & os ) { os.$nlOnOff = true; }
     90void nlOff( ofstream & os ) { os.$nlOnOff = false; }
     91
     92const char * sepGet( ofstream & os ) { return os.$separator; }
     93void sepSet( ofstream & os, const char s[] ) {
    9094        assert( s );
    91         strncpy( os.separator, s, sepSize - 1 );
    92         os.separator[sepSize - 1] = '\0';
     95        strncpy( os.$separator, s, sepSize - 1 );
     96        os.$separator[sepSize - 1] = '\0';
    9397} // sepSet
    9498
    95 const char * sepGetTuple( ofstream & os ) { return os.tupleSeparator; }
    96 void sepSetTuple( ofstream & os, const char * s ) {
     99const char * sepGetTuple( ofstream & os ) { return os.$tupleSeparator; }
     100void sepSetTuple( ofstream & os, const char s[] ) {
    97101        assert( s );
    98         strncpy( os.tupleSeparator, s, sepSize - 1 );
    99         os.tupleSeparator[sepSize - 1] = '\0';
     102        strncpy( os.$tupleSeparator, s, sepSize - 1 );
     103        os.$tupleSeparator[sepSize - 1] = '\0';
    100104} // sepSet
    101105
    102106void ends( ofstream & os ) {
    103         if ( getANL( os ) ) nl( os );
    104         else setPrt( os, false );                                                       // turn off
     107        if ( $getANL( os ) ) nl( os );
     108        else $setPrt( os, false );                                                      // turn off
    105109        if ( &os == &exit ) exit( EXIT_FAILURE );
    106110        if ( &os == &abort ) abort();
     
    108112
    109113int fail( ofstream & os ) {
    110         return os.file == 0 || ferror( (FILE *)(os.file) );
     114        return os.$file == 0 || ferror( (FILE *)(os.$file) );
    111115} // fail
    112116
    113117int flush( ofstream & os ) {
    114         return fflush( (FILE *)(os.file) );
     118        return fflush( (FILE *)(os.$file) );
    115119} // flush
    116120
    117 void open( ofstream & os, const char * name, const char * mode ) {
     121void open( ofstream & os, const char name[], const char mode[] ) {
    118122        FILE * file = fopen( name, mode );
    119123        #ifdef __CFA_DEBUG__
    120         if ( file == 0 ) {
     124        if ( file == 0p ) {
    121125                abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno );
    122126        } // if
     
    125129} // open
    126130
    127 void open( ofstream & os, const char * name ) {
     131void open( ofstream & os, const char name[] ) {
    128132        open( os, name, "w" );
    129133} // open
    130134
    131135void close( ofstream & os ) {
    132         if ( (FILE *)(os.file) == stdout || (FILE *)(os.file) == stderr ) return;
    133 
    134         if ( fclose( (FILE *)(os.file) ) == EOF ) {
     136        if ( (FILE *)(os.$file) == stdout || (FILE *)(os.$file) == stderr ) return;
     137
     138        if ( fclose( (FILE *)(os.$file) ) == EOF ) {
    135139                abort | IO_MSG "close output" | nl | strerror( errno );
    136140        } // if
    137141} // close
    138142
    139 ofstream & write( ofstream & os, const char * data, size_t size ) {
     143ofstream & write( ofstream & os, const char data[], size_t size ) {
    140144        if ( fail( os ) ) {
    141145                abort | IO_MSG "attempt write I/O on failed stream";
    142146        } // if
    143147
    144         if ( fwrite( data, 1, size, (FILE *)(os.file) ) != size ) {
     148        if ( fwrite( data, 1, size, (FILE *)(os.$file) ) != size ) {
    145149                abort | IO_MSG "write" | nl | strerror( errno );
    146150        } // if
     
    151155        va_list args;
    152156        va_start( args, format );
    153         int len = vfprintf( (FILE *)(os.file), format, args );
     157        int len = vfprintf( (FILE *)(os.$file), format, args );
    154158        if ( len == EOF ) {
    155                 if ( ferror( (FILE *)(os.file) ) ) {
     159                if ( ferror( (FILE *)(os.$file) ) ) {
    156160                        abort | IO_MSG "invalid write";
    157161                } // if
     
    159163        va_end( args );
    160164
    161         setPrt( os, true );                                                                     // called in output cascade
    162         sepReset( os );                                                                         // reset separator
     165        $setPrt( os, true );                                                            // called in output cascade
     166        $sepReset( os );                                                                        // reset separator
    163167        return len;
    164168} // fmt
    165169
    166 static ofstream soutFile = { (FILE *)(&_IO_2_1_stdout_) };
     170static ofstream soutFile = { (FILE *)stdout };
    167171ofstream & sout = soutFile, & stdout = soutFile;
    168 static ofstream serrFile = { (FILE *)(&_IO_2_1_stderr_) };
     172static ofstream serrFile = { (FILE *)stderr };
    169173ofstream & serr = serrFile, & stderr = serrFile;
    170174
    171 static ofstream exitFile = { (FILE *)(&_IO_2_1_stdout_) };
     175static ofstream exitFile = { (FILE *)stdout };
    172176ofstream & exit = exitFile;
    173 static ofstream abortFile = { (FILE *)(&_IO_2_1_stderr_) };
     177static ofstream abortFile = { (FILE *)stderr };
    174178ofstream & abort = abortFile;
    175179
     
    180184// private
    181185void ?{}( ifstream & is, void * file ) {
    182         is.file = file;
    183         is.nlOnOff = false;
     186        is.$file = file;
     187        is.$nlOnOff = false;
    184188} // ?{}
    185189
    186190// public
    187 void ?{}( ifstream & is ) {     is.file = 0; }
    188 
    189 void ?{}( ifstream & is, const char * name, const char * mode ) {
     191void ?{}( ifstream & is ) { is.$file = 0p; }
     192
     193void ?{}( ifstream & is, const char name[], const char mode[] ) {
    190194        open( is, name, mode );
    191195} // ?{}
    192196
    193 void ?{}( ifstream & is, const char * name ) {
     197void ?{}( ifstream & is, const char name[] ) {
    194198        open( is, name, "r" );
    195199} // ?{}
    196200
    197 void nlOn( ifstream & os ) { os.nlOnOff = true; }
    198 void nlOff( ifstream & os ) { os.nlOnOff = false; }
    199 bool getANL( ifstream & os ) { return os.nlOnOff; }
     201void ^?{}( ifstream & is ) {
     202        close( is );
     203} // ^?{}
     204
     205void nlOn( ifstream & os ) { os.$nlOnOff = true; }
     206void nlOff( ifstream & os ) { os.$nlOnOff = false; }
     207bool getANL( ifstream & os ) { return os.$nlOnOff; }
    200208
    201209int fail( ifstream & is ) {
    202         return is.file == 0 || ferror( (FILE *)(is.file) );
     210        return is.$file == 0p || ferror( (FILE *)(is.$file) );
    203211} // fail
    204212
    205213int eof( ifstream & is ) {
    206         return feof( (FILE *)(is.file) );
     214        return feof( (FILE *)(is.$file) );
    207215} // eof
    208216
    209 void open( ifstream & is, const char * name, const char * mode ) {
     217void open( ifstream & is, const char name[], const char mode[] ) {
    210218        FILE * file = fopen( name, mode );
    211219        #ifdef __CFA_DEBUG__
    212         if ( file == 0 ) {
     220        if ( file == 0p ) {
    213221                abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno );
    214222        } // if
    215223        #endif // __CFA_DEBUG__
    216         is.file = file;
    217 } // open
    218 
    219 void open( ifstream & is, const char * name ) {
     224        is.$file = file;
     225} // open
     226
     227void open( ifstream & is, const char name[] ) {
    220228        open( is, name, "r" );
    221229} // open
    222230
    223231void close( ifstream & is ) {
    224         if ( (FILE *)(is.file) == stdin ) return;
    225 
    226         if ( fclose( (FILE *)(is.file) ) == EOF ) {
     232        if ( (FILE *)(is.$file) == stdin ) return;
     233
     234        if ( fclose( (FILE *)(is.$file) ) == EOF ) {
    227235                abort | IO_MSG "close input" | nl | strerror( errno );
    228236        } // if
     
    234242        } // if
    235243
    236         if ( fread( data, size, 1, (FILE *)(is.file) ) == 0 ) {
     244        if ( fread( data, size, 1, (FILE *)(is.$file) ) == 0 ) {
    237245                abort | IO_MSG "read" | nl | strerror( errno );
    238246        } // if
     
    245253        } // if
    246254
    247         if ( ungetc( c, (FILE *)(is.file) ) == EOF ) {
     255        if ( ungetc( c, (FILE *)(is.$file) ) == EOF ) {
    248256                abort | IO_MSG "ungetc" | nl | strerror( errno );
    249257        } // if
     
    255263
    256264        va_start( args, format );
    257         int len = vfscanf( (FILE *)(is.file), format, args );
     265        int len = vfscanf( (FILE *)(is.$file), format, args );
    258266        if ( len == EOF ) {
    259                 if ( ferror( (FILE *)(is.file) ) ) {
     267                if ( ferror( (FILE *)(is.$file) ) ) {
    260268                        abort | IO_MSG "invalid read";
    261269                } // if
     
    265273} // fmt
    266274
    267 
    268 static ifstream sinFile = { (FILE *)(&_IO_2_1_stdin_) };
     275static ifstream sinFile = { (FILE *)stdin };
    269276ifstream & sin = sinFile, & stdin = sinFile;
    270277
  • libcfa/src/fstream.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul 15 18:10:23 2019
    13 // Update Count     : 167
     12// Last Modified On : Mon Feb 17 08:29:23 2020
     13// Update Count     : 175
    1414//
    1515
     
    2424enum { sepSize = 16 };
    2525struct ofstream {
    26         void * file;
    27         bool sepDefault;
    28         bool sepOnOff;
    29         bool nlOnOff;
    30         bool prt;                                                                                       // print text
    31         bool sawNL;
    32         const char * sepCur;
    33         char separator[sepSize];
    34         char tupleSeparator[sepSize];
     26        void * $file;
     27        bool $sepDefault;
     28        bool $sepOnOff;
     29        bool $nlOnOff;
     30        bool $prt;                                                                                      // print text
     31        bool $sawNL;
     32        const char * $sepCur;
     33        char $separator[sepSize];
     34        char $tupleSeparator[sepSize];
    3535}; // ofstream
    3636
    3737// private
    38 bool sepPrt( ofstream & );
    39 void sepReset( ofstream & );
    40 void sepReset( ofstream &, bool );
    41 const char * sepGetCur( ofstream & );
    42 void sepSetCur( ofstream &, const char * );
    43 bool getNL( ofstream & );
    44 void setNL( ofstream &, bool );
    45 bool getANL( ofstream & );
    46 bool getPrt( ofstream & );
    47 void setPrt( ofstream &, bool );
     38bool $sepPrt( ofstream & );
     39void $sepReset( ofstream & );
     40void $sepReset( ofstream &, bool );
     41const char * $sepGetCur( ofstream & );
     42void $sepSetCur( ofstream &, const char [] );
     43bool $getNL( ofstream & );
     44void $setNL( ofstream &, bool );
     45bool $getANL( ofstream & );
     46bool $getPrt( ofstream & );
     47void $setPrt( ofstream &, bool );
    4848
    4949// public
     
    5656
    5757const char * sepGet( ofstream & );
    58 void sepSet( ofstream &, const char * );
     58void sepSet( ofstream &, const char [] );
    5959const char * sepGetTuple( ofstream & );
    60 void sepSetTuple( ofstream &, const char * );
     60void sepSetTuple( ofstream &, const char [] );
    6161
    6262void ends( ofstream & os );
    6363int fail( ofstream & );
    6464int flush( ofstream & );
    65 void open( ofstream &, const char * name, const char * mode );
    66 void open( ofstream &, const char * name );
     65void open( ofstream &, const char name[], const char mode[] );
     66void open( ofstream &, const char name[] );
    6767void close( ofstream & );
    68 ofstream & write( ofstream &, const char * data, size_t size );
    69 int fmt( ofstream &, const char format[], ... );
     68ofstream & write( ofstream &, const char data[], size_t size );
     69int fmt( ofstream &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    7070
    7171void ?{}( ofstream & os );
    72 void ?{}( ofstream & os, const char * name, const char * mode );
    73 void ?{}( ofstream & os, const char * name );
     72void ?{}( ofstream & os, const char name[], const char mode[] );
     73void ?{}( ofstream & os, const char name[] );
     74void ^?{}( ofstream & os );
    7475
    7576extern ofstream & sout, & stdout, & serr, & stderr;             // aliases
     
    8182
    8283struct ifstream {
    83         void * file;
    84         bool nlOnOff;
     84        void * $file;
     85        bool $nlOnOff;
    8586}; // ifstream
    8687
     
    9192int fail( ifstream & is );
    9293int eof( ifstream & is );
    93 void open( ifstream & is, const char * name, const char * mode );
    94 void open( ifstream & is, const char * name );
     94void open( ifstream & is, const char name[], const char mode[] );
     95void open( ifstream & is, const char name[] );
    9596void close( ifstream & is );
    9697ifstream & read( ifstream & is, char * data, size_t size );
    9798ifstream & ungetc( ifstream & is, char c );
    98 int fmt( ifstream &, const char format[], ... );
     99int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) ));
    99100
    100101void ?{}( ifstream & is );
    101 void ?{}( ifstream & is, const char * name, const char * mode );
    102 void ?{}( ifstream & is, const char * name );
     102void ?{}( ifstream & is, const char name[], const char mode[] );
     103void ?{}( ifstream & is, const char name[] );
     104void ^?{}( ifstream & is );
    103105
    104106extern ifstream & sin, & stdin;                                                 // aliases
  • libcfa/src/gmp.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Apr 19 08:43:43 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 13 15:25:05 2019
    13 // Update Count     : 27
     12// Last Modified On : Sun Feb  9 09:56:54 2020
     13// Update Count     : 31
    1414//
    1515
     
    2424
    2525static inline {
    26         // constructor
     26        // constructor, zero_t/one_t are unnecessary because of relationship with signed/unsigned int
    2727        void ?{}( Int & this ) { mpz_init( this.mpz ); }
    2828        void ?{}( Int & this, Int init ) { mpz_init_set( this.mpz, init.mpz ); }
    29         void ?{}( Int & this, zero_t ) { mpz_init_set_si( this.mpz, 0 ); }
    30         void ?{}( Int & this, one_t ) { mpz_init_set_si( this.mpz, 1 ); }
    3129        void ?{}( Int & this, signed long int init ) { mpz_init_set_si( this.mpz, init ); }
    3230        void ?{}( Int & this, unsigned long int init ) { mpz_init_set_ui( this.mpz, init ); }
    33         void ?{}( Int & this, const char * val ) { if ( mpz_init_set_str( this.mpz, val, 0 ) ) abort(); }
     31        void ?{}( Int & this, const char val[] ) { if ( mpz_init_set_str( this.mpz, val, 0 ) ) abort(); }
    3432        void ^?{}( Int & this ) { mpz_clear( this.mpz ); }
    3533
     
    3735        Int ?`mp( signed long int init ) { return (Int){ init }; }
    3836        Int ?`mp( unsigned long int init ) { return (Int){ init }; }
    39         Int ?`mp( const char * init ) { return (Int){ init }; }
     37        Int ?`mp( const char init[] ) { return (Int){ init }; }
    4038
    4139        // assignment
     
    4341        Int ?=?( Int & lhs, long int rhs ) { mpz_set_si( lhs.mpz, rhs ); return lhs; }
    4442        Int ?=?( Int & lhs, unsigned long int rhs ) { mpz_set_ui( lhs.mpz, rhs ); return lhs; }
    45         Int ?=?( Int & lhs, const char * rhs ) { if ( mpz_set_str( lhs.mpz, rhs, 0 ) ) { abort | "invalid string conversion"; } return lhs; }
     43        Int ?=?( Int & lhs, const char rhs[] ) { if ( mpz_set_str( lhs.mpz, rhs, 0 ) ) { abort | "invalid string conversion"; } return lhs; }
    4644
    4745        char ?=?( char & lhs, Int rhs ) { char val = mpz_get_si( rhs.mpz ); lhs = val; return lhs; }
     
    265263        forall( dtype ostype | ostream( ostype ) ) {
    266264                ostype & ?|?( ostype & os, Int mp ) {
    267                         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     265                        if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    268266                        gmp_printf( "%Zd", mp.mpz );
    269267                        sepOn( os );
  • libcfa/src/heap.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 24 13:12:45 2019
    13 // Update Count     : 550
     12// Last Modified On : Tue Feb  4 10:04:51 2020
     13// Update Count     : 648
    1414//
    1515
     
    1818#include <stdio.h>                                                                              // snprintf, fileno
    1919#include <errno.h>                                                                              // errno
     20#include <string.h>                                                                             // memset, memcpy
    2021extern "C" {
    2122#include <sys/mman.h>                                                                   // mmap, munmap
     
    2728#include "bits/locks.hfa"                                                               // __spinlock_t
    2829#include "startup.hfa"                                                                  // STARTUP_PRIORITY_MEMORY
    29 #include "stdlib.hfa"                                                                   // bsearchl
     30//#include "stdlib.hfa"                                                                 // bsearchl
    3031#include "malloc.h"
    3132
     33#define MIN(x, y) (y > x ? x : y)
    3234
    3335static bool traceHeap = false;
    3436
    35 inline bool traceHeap() {
    36         return traceHeap;
    37 } // traceHeap
     37inline bool traceHeap() { return traceHeap; }
    3838
    3939bool traceHeapOn() {
     
    4949} // traceHeapOff
    5050
    51 
    52 static bool checkFree = false;
    53 
    54 inline bool checkFree() {
    55         return checkFree;
    56 } // checkFree
    57 
    58 bool checkFreeOn() {
    59         bool temp = checkFree;
    60         checkFree = true;
     51bool traceHeapTerm() { return false; }
     52
     53
     54static bool prtFree = false;
     55
     56inline bool prtFree() {
     57        return prtFree;
     58} // prtFree
     59
     60bool prtFreeOn() {
     61        bool temp = prtFree;
     62        prtFree = true;
    6163        return temp;
    62 } // checkFreeOn
    63 
    64 bool checkFreeOff() {
    65         bool temp = checkFree;
    66         checkFree = false;
     64} // prtFreeOn
     65
     66bool prtFreeOff() {
     67        bool temp = prtFree;
     68        prtFree = false;
    6769        return temp;
    68 } // checkFreeOff
    69 
    70 
    71 // static bool traceHeapTerm = false;
    72 
    73 // inline bool traceHeapTerm() {
    74 //      return traceHeapTerm;
    75 // } // traceHeapTerm
    76 
    77 // bool traceHeapTermOn() {
    78 //      bool temp = traceHeapTerm;
    79 //      traceHeapTerm = true;
    80 //      return temp;
    81 // } // traceHeapTermOn
    82 
    83 // bool traceHeapTermOff() {
    84 //      bool temp = traceHeapTerm;
    85 //      traceHeapTerm = false;
    86 //      return temp;
    87 // } // traceHeapTermOff
     70} // prtFreeOff
    8871
    8972
    9073enum {
     74        // Define the default extension heap amount in units of bytes. When the uC++ supplied heap reaches the brk address,
     75        // the brk address is extended by the extension amount.
     76        __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
     77
     78        // Define the mmap crossover point during allocation. Allocations less than this amount are allocated from buckets;
     79        // values greater than or equal to this value are mmap from the operating system.
    9180        __CFA_DEFAULT_MMAP_START__ = (512 * 1024 + 1),
    92         __CFA_DEFAULT_HEAP_EXPANSION__ = (1 * 1024 * 1024),
    9381};
    9482
     
    10593static unsigned int allocFree;                                                  // running total of allocations minus frees
    10694
    107 static void checkUnfreed() {
     95static void prtUnfreed() {
    10896        if ( allocFree != 0 ) {
    10997                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    110                 // char helpText[512];
    111                 // int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
    112                 //                                      "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
    113                 //                                      (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
    114                 // __cfaabi_dbg_bits_write( helpText, len );
    115         } // if
    116 } // checkUnfreed
     98                char helpText[512];
     99                int len = snprintf( helpText, sizeof(helpText), "CFA warning (UNIX pid:%ld) : program terminating with %u(0x%x) bytes of storage allocated but not freed.\n"
     100                                                        "Possible cause is unfreed storage allocated by the program or system/library routines called from the program.\n",
     101                                                        (long int)getpid(), allocFree, allocFree ); // always print the UNIX pid
     102                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
     103        } // if
     104} // prtUnfreed
    117105
    118106extern "C" {
     
    123111        void heapAppStop() {                                                            // called by __cfaabi_appready_startdown
    124112                fclose( stdin ); fclose( stdout );
    125                 checkUnfreed();
     113                prtUnfreed();
    126114        } // heapAppStop
    127115} // extern "C"
    128116#endif // __CFA_DEBUG__
     117
    129118
    130119// statically allocated variables => zero filled.
     
    134123static unsigned int maxBucketsUsed;                                             // maximum number of buckets in use
    135124
    136 
    137 // #comment TD : This defined is significantly different from the __ALIGN__ define from locks.hfa
    138 #define ALIGN 16
    139125
    140126#define SPINLOCK 0
     
    147133// Recursive definitions: HeapManager needs size of bucket array and bucket area needs sizeof HeapManager storage.
    148134// Break recusion by hardcoding number of buckets and statically checking number is correct after bucket array defined.
    149 enum { NoBucketSizes = 93 };                                                    // number of buckets sizes
     135enum { NoBucketSizes = 91 };                                                    // number of buckets sizes
    150136
    151137struct HeapManager {
     
    194180                        } kind; // Kind
    195181                } header; // Header
    196                 char pad[ALIGN - sizeof( Header )];
     182                char pad[libAlign() - sizeof( Header )];
    197183                char data[0];                                                                   // storage
    198184        }; // Storage
    199185
    200         static_assert( ALIGN >= sizeof( Storage ), "ALIGN < sizeof( Storage )" );
     186        static_assert( libAlign() >= sizeof( Storage ), "libAlign() < sizeof( Storage )" );
    201187
    202188        struct FreeHeader {
     
    228214#define __STATISTICS__
    229215
     216// Bucket size must be multiple of 16.
    230217// Powers of 2 are common allocation sizes, so make powers of 2 generate the minimum required size.
    231218static const unsigned int bucketSizes[] @= {                    // different bucket sizes
    232         16, 32, 48, 64,
    233         64 + sizeof(HeapManager.Storage), 96, 112, 128, 128 + sizeof(HeapManager.Storage), 160, 192, 224,
    234         256 + sizeof(HeapManager.Storage), 320, 384, 448, 512 + sizeof(HeapManager.Storage), 640, 768, 896,
    235         1_024 + sizeof(HeapManager.Storage), 1_536, 2_048 + sizeof(HeapManager.Storage), 2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), 6_144,
    236         8_192 + sizeof(HeapManager.Storage), 9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360,
    237         16_384 + sizeof(HeapManager.Storage), 18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720,
    238         32_768 + sizeof(HeapManager.Storage), 36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440,
    239         65_536 + sizeof(HeapManager.Storage), 73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880,
    240         131_072 + sizeof(HeapManager.Storage), 147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760,
    241         262_144 + sizeof(HeapManager.Storage), 294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520,
    242         524_288 + sizeof(HeapManager.Storage), 655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), 1_179_648, 1_310_720, 1_441_792,
    243         1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), 2_621_440, 3_145_728, 3_670_016,
    244         4_194_304 + sizeof(HeapManager.Storage)
     219        16, 32, 48, 64 + sizeof(HeapManager.Storage), // 4
     220        96, 112, 128 + sizeof(HeapManager.Storage), // 3
     221        160, 192, 224, 256 + sizeof(HeapManager.Storage), // 4
     222        320, 384, 448, 512 + sizeof(HeapManager.Storage), // 4
     223        640, 768, 896, 1_024 + sizeof(HeapManager.Storage), // 4
     224        1_536, 2_048 + sizeof(HeapManager.Storage), // 2
     225        2_560, 3_072, 3_584, 4_096 + sizeof(HeapManager.Storage), // 4
     226        6_144, 8_192 + sizeof(HeapManager.Storage), // 2
     227        9_216, 10_240, 11_264, 12_288, 13_312, 14_336, 15_360, 16_384 + sizeof(HeapManager.Storage), // 8
     228        18_432, 20_480, 22_528, 24_576, 26_624, 28_672, 30_720, 32_768 + sizeof(HeapManager.Storage), // 8
     229        36_864, 40_960, 45_056, 49_152, 53_248, 57_344, 61_440, 65_536 + sizeof(HeapManager.Storage), // 8
     230        73_728, 81_920, 90_112, 98_304, 106_496, 114_688, 122_880, 131_072 + sizeof(HeapManager.Storage), // 8
     231        147_456, 163_840, 180_224, 196_608, 212_992, 229_376, 245_760, 262_144 + sizeof(HeapManager.Storage), // 8
     232        294_912, 327_680, 360_448, 393_216, 425_984, 458_752, 491_520, 524_288 + sizeof(HeapManager.Storage), // 8
     233        655_360, 786_432, 917_504, 1_048_576 + sizeof(HeapManager.Storage), // 4
     234        1_179_648, 1_310_720, 1_441_792, 1_572_864, 1_703_936, 1_835_008, 1_966_080, 2_097_152 + sizeof(HeapManager.Storage), // 8
     235        2_621_440, 3_145_728, 3_670_016, 4_194_304 + sizeof(HeapManager.Storage), // 4
    245236};
    246237
     
    251242static unsigned char lookup[LookupSizes];                               // O(1) lookup for small sizes
    252243#endif // FASTLOOKUP
     244
    253245static int mmapFd = -1;                                                                 // fake or actual fd for anonymous file
    254 
    255 
    256246#ifdef __CFA_DEBUG__
    257247static bool heapBoot = 0;                                                               // detect recursion during boot
     
    259249static HeapManager heapManager __attribute__(( aligned (128) )) @= {}; // size of cache line to prevent false sharing
    260250
    261 // #comment TD : The return type of this function should be commented
    262 static inline bool setMmapStart( size_t value ) {
    263   if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
    264         mmapStart = value;                                                                      // set global
    265 
    266         // find the closest bucket size less than or equal to the mmapStart size
    267         maxBucketsUsed = bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
    268         assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
    269         assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
    270         return false;
    271 } // setMmapStart
    272 
    273 
    274 static void ?{}( HeapManager & manager ) with ( manager ) {
    275         pageSize = sysconf( _SC_PAGESIZE );
    276 
    277         for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
    278                 freeLists[i].blockSize = bucketSizes[i];
    279         } // for
    280 
    281         #ifdef FASTLOOKUP
    282         unsigned int idx = 0;
    283         for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
    284                 if ( i > bucketSizes[idx] ) idx += 1;
    285                 lookup[i] = idx;
    286         } // for
    287         #endif // FASTLOOKUP
    288 
    289         if ( setMmapStart( default_mmap_start() ) ) {
    290                 abort( "HeapManager : internal error, mmap start initialization failure." );
    291         } // if
    292         heapExpand = default_heap_expansion();
    293 
    294         char * End = (char *)sbrk( 0 );
    295         sbrk( (char *)libCeiling( (long unsigned int)End, libAlign() ) - End ); // move start of heap to multiple of alignment
    296         heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
    297 } // HeapManager
    298 
    299 
    300 static void ^?{}( HeapManager & ) {
    301         #ifdef __STATISTICS__
    302         // if ( traceHeapTerm() ) {
    303         //      printStats();
    304         //      if ( checkfree() ) checkFree( heapManager, true );
    305         // } // if
    306         #endif // __STATISTICS__
    307 } // ~HeapManager
    308 
    309 
    310 static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
    311 void memory_startup( void ) {
    312         #ifdef __CFA_DEBUG__
    313         if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
    314                 // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
    315                 abort( "boot() : internal error, recursively invoked during system boot." );
    316         } // if
    317         heapBoot = true;
    318         #endif // __CFA_DEBUG__
    319 
    320         //assert( heapManager.heapBegin != 0 );
    321         //heapManager{};
    322         if ( heapManager.heapBegin == 0 ) heapManager{};
    323 } // memory_startup
    324 
    325 static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
    326 void memory_shutdown( void ) {
    327         ^heapManager{};
    328 } // memory_shutdown
    329 
    330251
    331252#ifdef __STATISTICS__
    332 static unsigned long long int mmap_storage;                             // heap statistics counters
     253// Heap statistics counters.
     254static unsigned long long int mmap_storage;
    333255static unsigned int mmap_calls;
    334256static unsigned long long int munmap_storage;
     
    348270static unsigned long long int realloc_storage;
    349271static unsigned int realloc_calls;
    350 
    351 static int statfd;                                                                              // statistics file descriptor (changed by malloc_stats_fd)
    352 
     272// Statistics file descriptor (changed by malloc_stats_fd).
     273static int statfd = STDERR_FILENO;                                              // default stderr
    353274
    354275// Use "write" because streams may be shutdown when calls are made.
    355276static void printStats() {
    356277        char helpText[512];
    357         __cfaabi_dbg_bits_print_buffer( helpText, sizeof(helpText),
     278        __cfaabi_bits_print_buffer( STDERR_FILENO, helpText, sizeof(helpText),
    358279                                                                        "\nHeap statistics:\n"
    359280                                                                        "  malloc: calls %u / storage %llu\n"
     
    405326                                                sbrk_calls, sbrk_storage
    406327                );
    407         return write( fileno( stream ), helpText, len );        // -1 => error
     328        __cfaabi_bits_write( fileno( stream ), helpText, len ); // ensures all bytes written or exit
     329        return len;
    408330} // printStatsXML
    409331#endif // __STATISTICS__
    410332
    411 // #comment TD : Is this the samething as Out-of-Memory?
    412 static inline void noMemory() {
    413         abort( "Heap memory exhausted at %zu bytes.\n"
    414                    "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
    415                    ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
    416 } // noMemory
     333
     334// static inline void noMemory() {
     335//      abort( "Heap memory exhausted at %zu bytes.\n"
     336//                 "Possible cause is very large memory allocation and/or large amount of unfreed storage allocated by the program or system/library routines.",
     337//                 ((char *)(sbrk( 0 )) - (char *)(heapManager.heapBegin)) );
     338// } // noMemory
    417339
    418340
    419341static inline void checkAlign( size_t alignment ) {
    420         if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) {
    421                 abort( "Alignment %zu for memory allocation is less than sizeof(void *) and/or not a power of 2.", alignment );
     342        if ( alignment < libAlign() || ! libPow2( alignment ) ) {
     343                abort( "Alignment %zu for memory allocation is less than %d and/or not a power of 2.", alignment, libAlign() );
    422344        } // if
    423345} // checkAlign
     
    431353
    432354
    433 static inline void checkHeader( bool check, const char * name, void * addr ) {
    434         if ( unlikely( check ) ) {                                                      // bad address ?
    435                 abort( "Attempt to %s storage %p with address outside the heap.\n"
    436                            "Possible cause is duplicate free on same block or overwriting of memory.",
    437                            name, addr );
    438         } // if
    439 } // checkHeader
    440 
    441 // #comment TD : function should be commented and/or have a more evocative name
    442 //               this isn't either a check or a constructor which is what I would expect this function to be
    443 static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & size, size_t & alignment ) {
    444         if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
    445                 size_t offset = header->kind.fake.offset;
    446                 alignment = header->kind.fake.alignment & -2;   // remove flag from value
    447                 #ifdef __CFA_DEBUG__
    448                 checkAlign( alignment );                                                // check alignment
    449                 #endif // __CFA_DEBUG__
    450                 header = (HeapManager.Storage.Header *)((char *)header - offset);
    451         } // if
    452 } // fakeHeader
    453 
    454 // #comment TD : Why is this a define
    455 #define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
    456 
    457 static inline bool headers( const char * name, void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
    458         header = headerAddr( addr );
    459 
    460         if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
    461                 fakeHeader( header, size, alignment );
    462                 size = header->kind.real.blockSize & -3;                // mmap size
    463                 return true;
    464         } // if
    465 
    466         #ifdef __CFA_DEBUG__
    467         checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
    468         #endif // __CFA_DEBUG__
    469 
    470         // #comment TD : This code looks weird...
    471         //               It's called as the first statement of both branches of the last if, with the same parameters in all cases
    472 
    473         // header may be safe to dereference
    474         fakeHeader( header, size, alignment );
    475         #ifdef __CFA_DEBUG__
    476         checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
    477         #endif // __CFA_DEBUG__
    478 
    479         freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
    480         #ifdef __CFA_DEBUG__
    481         if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
    482                 abort( "Attempt to %s storage %p with corrupted header.\n"
    483                            "Possible cause is duplicate free on same block or overwriting of header information.",
    484                            name, addr );
    485         } // if
    486         #endif // __CFA_DEBUG__
    487         size = freeElem->blockSize;
    488         return false;
    489 } // headers
    490 
    491 
    492 static inline void * extend( size_t size ) with ( heapManager ) {
    493         lock( extlock __cfaabi_dbg_ctx2 );
    494         ptrdiff_t rem = heapRemaining - size;
    495         if ( rem < 0 ) {
    496                 // If the size requested is bigger than the current remaining storage, increase the size of the heap.
    497 
    498                 size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
    499                 if ( sbrk( increase ) == (void *)-1 ) {
    500                         unlock( extlock );
    501                         errno = ENOMEM;
    502                         return 0;
    503                 } // if
    504                 #ifdef __STATISTICS__
    505                 sbrk_calls += 1;
    506                 sbrk_storage += increase;
    507                 #endif // __STATISTICS__
    508                 #ifdef __CFA_DEBUG__
    509                 // Set new memory to garbage so subsequent uninitialized usages might fail.
    510                 memset( (char *)heapEnd + heapRemaining, '\377', increase );
    511                 #endif // __CFA_DEBUG__
    512                 rem = heapRemaining + increase - size;
    513         } // if
    514 
    515         HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
    516         heapRemaining = rem;
    517         heapEnd = (char *)heapEnd + size;
    518         unlock( extlock );
    519         return block;
    520 } // extend
    521 
    522 
     355// thunk problem
    523356size_t Bsearchl( unsigned int key, const unsigned int * vals, size_t dim ) {
    524357        size_t l = 0, m, h = dim;
     
    535368
    536369
     370static inline bool setMmapStart( size_t value ) {               // true => mmapped, false => sbrk
     371  if ( value < pageSize || bucketSizes[NoBucketSizes - 1] < value ) return true;
     372        mmapStart = value;                                                                      // set global
     373
     374        // find the closest bucket size less than or equal to the mmapStart size
     375        maxBucketsUsed = Bsearchl( (unsigned int)mmapStart, bucketSizes, NoBucketSizes ); // binary search
     376        assert( maxBucketsUsed < NoBucketSizes );                       // subscript failure ?
     377        assert( mmapStart <= bucketSizes[maxBucketsUsed] ); // search failure ?
     378        return false;
     379} // setMmapStart
     380
     381
     382static inline void checkHeader( bool check, const char name[], void * addr ) {
     383        if ( unlikely( check ) ) {                                                      // bad address ?
     384                abort( "Attempt to %s storage %p with address outside the heap.\n"
     385                           "Possible cause is duplicate free on same block or overwriting of memory.",
     386                           name, addr );
     387        } // if
     388} // checkHeader
     389
     390
     391static inline void fakeHeader( HeapManager.Storage.Header *& header, size_t & alignment ) {
     392        if ( unlikely( (header->kind.fake.alignment & 1) == 1 ) ) { // fake header ?
     393                size_t offset = header->kind.fake.offset;
     394                alignment = header->kind.fake.alignment & -2;   // remove flag from value
     395                #ifdef __CFA_DEBUG__
     396                checkAlign( alignment );                                                // check alignment
     397                #endif // __CFA_DEBUG__
     398                header = (HeapManager.Storage.Header *)((char *)header - offset);
     399        } // if
     400} // fakeHeader
     401
     402
     403// <-------+----------------------------------------------------> bsize (bucket size)
     404// |header |addr
     405//==================================================================================
     406//                                | alignment
     407// <-----------------<------------+-----------------------------> bsize (bucket size)
     408//                   |fake-header | addr
     409#define headerAddr( addr ) ((HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) ))
     410
     411// <-------<<--------------------- dsize ---------------------->> bsize (bucket size)
     412// |header |addr
     413//==================================================================================
     414//                                | alignment
     415// <------------------------------<<---------- dsize --------->>> bsize (bucket size)
     416//                   |fake-header |addr
     417#define dataStorage( bsize, addr, header ) (bsize - ( (char *)addr - (char *)header ))
     418
     419
     420static inline bool headers( const char name[] __attribute__(( unused )), void * addr, HeapManager.Storage.Header *& header, HeapManager.FreeHeader *& freeElem, size_t & size, size_t & alignment ) with ( heapManager ) {
     421        header = headerAddr( addr );
     422
     423        if ( unlikely( heapEnd < addr ) ) {                                     // mmapped ?
     424                fakeHeader( header, alignment );
     425                size = header->kind.real.blockSize & -3;                // mmap size
     426                return true;
     427        } // if
     428
     429        #ifdef __CFA_DEBUG__
     430        checkHeader( addr < heapBegin || header < (HeapManager.Storage.Header *)heapBegin, name, addr ); // bad low address ?
     431        #endif // __CFA_DEBUG__
     432
     433        // header may be safe to dereference
     434        fakeHeader( header, alignment );
     435        #ifdef __CFA_DEBUG__
     436        checkHeader( header < (HeapManager.Storage.Header *)heapBegin || (HeapManager.Storage.Header *)heapEnd < header, name, addr ); // bad address ? (offset could be + or -)
     437        #endif // __CFA_DEBUG__
     438
     439        freeElem = (HeapManager.FreeHeader *)((size_t)header->kind.real.home & -3);
     440        #ifdef __CFA_DEBUG__
     441        if ( freeElem < &freeLists[0] || &freeLists[NoBucketSizes] <= freeElem ) {
     442                abort( "Attempt to %s storage %p with corrupted header.\n"
     443                           "Possible cause is duplicate free on same block or overwriting of header information.",
     444                           name, addr );
     445        } // if
     446        #endif // __CFA_DEBUG__
     447        size = freeElem->blockSize;
     448        return false;
     449} // headers
     450
     451
     452static inline void * extend( size_t size ) with ( heapManager ) {
     453        lock( extlock __cfaabi_dbg_ctx2 );
     454        ptrdiff_t rem = heapRemaining - size;
     455        if ( rem < 0 ) {
     456                // If the size requested is bigger than the current remaining storage, increase the size of the heap.
     457
     458                size_t increase = libCeiling( size > heapExpand ? size : heapExpand, libAlign() );
     459                if ( sbrk( increase ) == (void *)-1 ) {
     460                        unlock( extlock );
     461                        errno = ENOMEM;
     462                        return 0p;
     463                } // if
     464                #ifdef __STATISTICS__
     465                sbrk_calls += 1;
     466                sbrk_storage += increase;
     467                #endif // __STATISTICS__
     468                #ifdef __CFA_DEBUG__
     469                // Set new memory to garbage so subsequent uninitialized usages might fail.
     470                memset( (char *)heapEnd + heapRemaining, '\377', increase );
     471                #endif // __CFA_DEBUG__
     472                rem = heapRemaining + increase - size;
     473        } // if
     474
     475        HeapManager.Storage * block = (HeapManager.Storage *)heapEnd;
     476        heapRemaining = rem;
     477        heapEnd = (char *)heapEnd + size;
     478        unlock( extlock );
     479        return block;
     480} // extend
     481
     482
    537483static inline void * doMalloc( size_t size ) with ( heapManager ) {
    538484        HeapManager.Storage * block;                                            // pointer to new block of storage
     
    541487        // along with the block and is a multiple of the alignment size.
    542488
     489  if ( unlikely( size > ~0ul - sizeof(HeapManager.Storage) ) ) return 0p;
    543490        size_t tsize = size + sizeof(HeapManager.Storage);
    544491        if ( likely( tsize < mmapStart ) ) {                            // small size => sbrk
     
    573520                block = freeElem->freeList.pop();
    574521                #endif // SPINLOCK
    575                 if ( unlikely( block == 0 ) ) {                                 // no free block ?
     522                if ( unlikely( block == 0p ) ) {                                // no free block ?
    576523                        #if defined( SPINLOCK )
    577524                        unlock( freeElem->lock );
     
    582529
    583530                        block = (HeapManager.Storage *)extend( tsize ); // mutual exclusion on call
    584   if ( unlikely( block == 0 ) ) return 0;
    585                         #if defined( SPINLOCK )
     531  if ( unlikely( block == 0p ) ) return 0p;
     532                #if defined( SPINLOCK )
    586533                } else {
    587534                        freeElem->freeList = block->header.kind.real.next;
    588535                        unlock( freeElem->lock );
    589                         #endif // SPINLOCK
     536                #endif // SPINLOCK
    590537                } // if
    591538
    592539                block->header.kind.real.home = freeElem;                // pointer back to free list of apropriate size
    593540        } else {                                                                                        // large size => mmap
     541  if ( unlikely( size > ~0ul - pageSize ) ) return 0p;
    594542                tsize = libCeiling( tsize, pageSize );                  // must be multiple of page size
    595543                #ifdef __STATISTICS__
     
    609557        } // if
    610558
    611         void * area = &(block->data);                                           // adjust off header to user bytes
     559        void * addr = &(block->data);                                           // adjust off header to user bytes
    612560
    613561        #ifdef __CFA_DEBUG__
    614         assert( ((uintptr_t)area & (libAlign() - 1)) == 0 ); // minimum alignment ?
     562        assert( ((uintptr_t)addr & (libAlign() - 1)) == 0 ); // minimum alignment ?
    615563        __atomic_add_fetch( &allocFree, tsize, __ATOMIC_SEQ_CST );
    616564        if ( traceHeap() ) {
    617565                enum { BufferSize = 64 };
    618566                char helpText[BufferSize];
    619                 int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", area, size, tsize );
    620                 // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", area, size );
    621                 __cfaabi_dbg_bits_write( helpText, len );
     567                int len = snprintf( helpText, BufferSize, "%p = Malloc( %zu ) (allocated %zu)\n", addr, size, tsize );
     568                // int len = snprintf( helpText, BufferSize, "Malloc %p %zu\n", addr, size );
     569                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    622570        } // if
    623571        #endif // __CFA_DEBUG__
    624572
    625         return area;
     573        return addr;
    626574} // doMalloc
    627575
     
    629577static inline void doFree( void * addr ) with ( heapManager ) {
    630578        #ifdef __CFA_DEBUG__
    631         if ( unlikely( heapManager.heapBegin == 0 ) ) {
     579        if ( unlikely( heapManager.heapBegin == 0p ) ) {
    632580                abort( "doFree( %p ) : internal error, called before heap is initialized.", addr );
    633581        } // if
     
    675623                char helpText[BufferSize];
    676624                int len = snprintf( helpText, sizeof(helpText), "Free( %p ) size:%zu\n", addr, size );
    677                 __cfaabi_dbg_bits_write( helpText, len );
     625                __cfaabi_bits_write( STDERR_FILENO, helpText, len ); // print debug/nodebug
    678626        } // if
    679627        #endif // __CFA_DEBUG__
     
    681629
    682630
    683 size_t checkFree( HeapManager & manager ) with ( manager ) {
     631size_t prtFree( HeapManager & manager ) with ( manager ) {
    684632        size_t total = 0;
    685633        #ifdef __STATISTICS__
    686         __cfaabi_dbg_bits_acquire();
    687         __cfaabi_dbg_bits_print_nolock( "\nBin lists (bin size : free blocks on list)\n" );
     634        __cfaabi_bits_acquire();
     635        __cfaabi_bits_print_nolock( STDERR_FILENO, "\nBin lists (bin size : free blocks on list)\n" );
    688636        #endif // __STATISTICS__
    689637        for ( unsigned int i = 0; i < maxBucketsUsed; i += 1 ) {
     
    694642
    695643                #if defined( SPINLOCK )
    696                 for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0; p = p->header.kind.real.next ) {
     644                for ( HeapManager.Storage * p = freeLists[i].freeList; p != 0p; p = p->header.kind.real.next ) {
    697645                #else
    698                 for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0; p = p->header.kind.real.next.top ) {
     646                for ( HeapManager.Storage * p = freeLists[i].freeList.top(); p != 0p; p = p->header.kind.real.next.top ) {
    699647                #endif // SPINLOCK
    700648                        total += size;
     
    705653
    706654                #ifdef __STATISTICS__
    707                 __cfaabi_dbg_bits_print_nolock( "%7zu, %-7u  ", size, N );
    708                 if ( (i + 1) % 8 == 0 ) __cfaabi_dbg_bits_print_nolock( "\n" );
     655                __cfaabi_bits_print_nolock( STDERR_FILENO, "%7zu, %-7u  ", size, N );
     656                if ( (i + 1) % 8 == 0 ) __cfaabi_bits_print_nolock( STDERR_FILENO, "\n" );
    709657                #endif // __STATISTICS__
    710658        } // for
    711659        #ifdef __STATISTICS__
    712         __cfaabi_dbg_bits_print_nolock( "\ntotal free blocks:%zu\n", total );
    713         __cfaabi_dbg_bits_release();
     660        __cfaabi_bits_print_nolock( STDERR_FILENO, "\ntotal free blocks:%zu\n", total );
     661        __cfaabi_bits_release();
    714662        #endif // __STATISTICS__
    715663        return (char *)heapEnd - (char *)heapBegin - total;
    716 } // checkFree
     664} // prtFree
     665
     666
     667static void ?{}( HeapManager & manager ) with ( manager ) {
     668        pageSize = sysconf( _SC_PAGESIZE );
     669
     670        for ( unsigned int i = 0; i < NoBucketSizes; i += 1 ) { // initialize the free lists
     671                freeLists[i].blockSize = bucketSizes[i];
     672        } // for
     673
     674        #ifdef FASTLOOKUP
     675        unsigned int idx = 0;
     676        for ( unsigned int i = 0; i < LookupSizes; i += 1 ) {
     677                if ( i > bucketSizes[idx] ) idx += 1;
     678                lookup[i] = idx;
     679        } // for
     680        #endif // FASTLOOKUP
     681
     682        if ( setMmapStart( default_mmap_start() ) ) {
     683                abort( "HeapManager : internal error, mmap start initialization failure." );
     684        } // if
     685        heapExpand = default_heap_expansion();
     686
     687        char * end = (char *)sbrk( 0 );
     688        sbrk( (char *)libCeiling( (long unsigned int)end, libAlign() ) - end ); // move start of heap to multiple of alignment
     689        heapBegin = heapEnd = sbrk( 0 );                                        // get new start point
     690} // HeapManager
     691
     692
     693static void ^?{}( HeapManager & ) {
     694        #ifdef __STATISTICS__
     695        if ( traceHeapTerm() ) {
     696                printStats();
     697                // if ( prtfree() ) prtFree( heapManager, true );
     698        } // if
     699        #endif // __STATISTICS__
     700} // ~HeapManager
     701
     702
     703static void memory_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_MEMORY ) ));
     704void memory_startup( void ) {
     705        #ifdef __CFA_DEBUG__
     706        if ( unlikely( heapBoot ) ) {                                           // check for recursion during system boot
     707                // DO NOT USE STREAMS AS THEY MAY BE UNAVAILABLE AT THIS POINT.
     708                abort( "boot() : internal error, recursively invoked during system boot." );
     709        } // if
     710        heapBoot = true;
     711        #endif // __CFA_DEBUG__
     712
     713        //assert( heapManager.heapBegin != 0 );
     714        //heapManager{};
     715        if ( heapManager.heapBegin == 0p ) heapManager{};
     716} // memory_startup
     717
     718static void memory_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_MEMORY ) ));
     719void memory_shutdown( void ) {
     720        ^heapManager{};
     721} // memory_shutdown
    717722
    718723
    719724static inline void * mallocNoStats( size_t size ) {             // necessary for malloc statistics
    720725        //assert( heapManager.heapBegin != 0 );
    721         if ( unlikely( heapManager.heapBegin == 0 ) ) heapManager{}; // called before memory_startup ?
    722         void * area = doMalloc( size );
    723         if ( unlikely( area == 0 ) ) errno = ENOMEM;            // POSIX
    724         return area;
     726        if ( unlikely( heapManager.heapBegin == 0p ) ) heapManager{}; // called before memory_startup ?
     727        void * addr = doMalloc( size );
     728        if ( unlikely( addr == 0p ) ) errno = ENOMEM;           // POSIX
     729        return addr;
    725730} // mallocNoStats
     731
     732
     733static inline void * callocNoStats( size_t noOfElems, size_t elemSize ) {
     734        size_t size = noOfElems * elemSize;
     735        char * addr = (char *)mallocNoStats( size );
     736  if ( unlikely( addr == 0p ) ) return 0p;
     737
     738        HeapManager.Storage.Header * header;
     739        HeapManager.FreeHeader * freeElem;
     740        size_t bsize, alignment;
     741        bool mapped __attribute__(( unused )) = headers( "calloc", addr, header, freeElem, bsize, alignment );
     742        #ifndef __CFA_DEBUG__
     743        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     744        if ( ! mapped )
     745        #endif // __CFA_DEBUG__
     746                // Zero entire data space even when > than size => realloc without a new allocation and zero fill works.
     747                // <-------00000000000000000000000000000000000000000000000000000> bsize (bucket size)
     748                // `-header`-addr                      `-size
     749                memset( addr, '\0', bsize - sizeof(HeapManager.Storage) ); // set to zeros
     750
     751        header->kind.real.blockSize |= 2;                                       // mark as zero filled
     752        return addr;
     753} // callocNoStats
    726754
    727755
     
    743771        // subtract libAlign() because it is already the minimum alignment
    744772        // add sizeof(Storage) for fake header
    745         // #comment TD : this is the only place that calls doMalloc without calling mallocNoStats, why ?
    746         char * area = (char *)doMalloc( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
    747   if ( unlikely( area == 0 ) ) return area;
     773        char * addr = (char *)mallocNoStats( size + alignment - libAlign() + sizeof(HeapManager.Storage) );
     774  if ( unlikely( addr == 0p ) ) return addr;
    748775
    749776        // address in the block of the "next" alignment address
    750         char * user = (char *)libCeiling( (uintptr_t)(area + sizeof(HeapManager.Storage)), alignment );
     777        char * user = (char *)libCeiling( (uintptr_t)(addr + sizeof(HeapManager.Storage)), alignment );
    751778
    752779        // address of header from malloc
    753         HeapManager.Storage.Header * realHeader = headerAddr( area );
     780        HeapManager.Storage.Header * realHeader = headerAddr( addr );
    754781        // address of fake header * before* the alignment location
    755782        HeapManager.Storage.Header * fakeHeader = headerAddr( user );
     
    761788        return user;
    762789} // memalignNoStats
     790
     791
     792static inline void * cmemalignNoStats( size_t alignment, size_t noOfElems, size_t elemSize ) {
     793        size_t size = noOfElems * elemSize;
     794        char * addr = (char *)memalignNoStats( alignment, size );
     795  if ( unlikely( addr == 0p ) ) return 0p;
     796        HeapManager.Storage.Header * header;
     797        HeapManager.FreeHeader * freeElem;
     798        size_t bsize;
     799        bool mapped __attribute__(( unused )) = headers( "cmemalign", addr, header, freeElem, bsize, alignment );
     800        #ifndef __CFA_DEBUG__
     801        // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
     802        if ( ! mapped )
     803        #endif // __CFA_DEBUG__
     804                memset( addr, '\0', dataStorage( bsize, addr, header ) ); // set to zeros
     805        header->kind.real.blockSize |= 2;                               // mark as zero filled
     806
     807        return addr;
     808} // cmemalignNoStats
    763809
    764810
     
    774820extern "C" {
    775821        // The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not
    776         // initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be
     822        // initialized. If size is 0, then malloc() returns either 0p, or a unique pointer value that can later be
    777823        // successfully passed to free().
    778824        void * malloc( size_t size ) {
     
    786832
    787833        // The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to
    788         // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a
     834        // the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either 0p, or a
    789835        // unique pointer value that can later be successfully passed to free().
    790836        void * calloc( size_t noOfElems, size_t elemSize ) {
    791                 size_t size = noOfElems * elemSize;
    792837                #ifdef __STATISTICS__
    793838                __atomic_add_fetch( &calloc_calls, 1, __ATOMIC_SEQ_CST );
    794                 __atomic_add_fetch( &calloc_storage, size, __ATOMIC_SEQ_CST );
    795                 #endif // __STATISTICS__
    796 
    797                 char * area = (char *)mallocNoStats( size );
    798           if ( unlikely( area == 0 ) ) return 0;
     839                __atomic_add_fetch( &calloc_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
     840                #endif // __STATISTICS__
     841
     842                return callocNoStats( noOfElems, elemSize );
     843        } // calloc
     844
     845        // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
     846        // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
     847        // is larger than the old size, the added memory will not be initialized.  If ptr is 0p, then the call is
     848        // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not 0p, then the call
     849        // is equivalent to free(ptr). Unless ptr is 0p, it must have been returned by an earlier call to malloc(),
     850        // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
     851        void * realloc( void * oaddr, size_t size ) {
     852                #ifdef __STATISTICS__
     853                __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     854                #endif // __STATISTICS__
     855
     856                // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     857          if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases
     858          if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
    799859
    800860                HeapManager.Storage.Header * header;
    801861                HeapManager.FreeHeader * freeElem;
    802                 size_t asize, alignment;
    803                 bool mapped __attribute__(( unused )) = headers( "calloc", area, header, freeElem, asize, alignment );
    804                 #ifndef __CFA_DEBUG__
    805                 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    806                 if ( ! mapped )
    807                 #endif // __CFA_DEBUG__
    808                         memset( area, '\0', asize - sizeof(HeapManager.Storage) ); // set to zeros
    809 
    810                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    811                 return area;
    812         } // calloc
    813 
    814         // #comment TD : Document this function
    815         void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
    816                 size_t size = noOfElems * elemSize;
    817                 #ifdef __STATISTICS__
    818                 __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
    819                 __atomic_add_fetch( &cmemalign_storage, size, __ATOMIC_SEQ_CST );
    820                 #endif // __STATISTICS__
    821 
    822                 char * area = (char *)memalignNoStats( alignment, size );
    823           if ( unlikely( area == 0 ) ) return 0;
    824                 HeapManager.Storage.Header * header;
    825                 HeapManager.FreeHeader * freeElem;
    826                 size_t asize;
    827                 bool mapped __attribute__(( unused )) = headers( "cmemalign", area, header, freeElem, asize, alignment );
    828                 #ifndef __CFA_DEBUG__
    829                 // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    830                 if ( ! mapped )
    831                         #endif // __CFA_DEBUG__
    832                         memset( area, '\0', asize - ( (char *)area - (char *)header ) ); // set to zeros
    833                 header->kind.real.blockSize |= 2;                               // mark as zero filled
    834 
    835                 return area;
    836         } // cmemalign
    837 
    838         // The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be
    839         // unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size
    840         // is larger than the old size, the added memory will not be initialized.  If ptr is NULL, then the call is
    841         // equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call
    842         // is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(),
    843         // calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.
    844         void * realloc( void * addr, size_t size ) {
    845                 #ifdef __STATISTICS__
    846                 __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
    847                 #endif // __STATISTICS__
    848 
    849           if ( unlikely( addr == 0 ) ) return mallocNoStats( size ); // special cases
    850           if ( unlikely( size == 0 ) ) { free( addr ); return 0; }
    851 
    852                 HeapManager.Storage.Header * header;
    853                 HeapManager.FreeHeader * freeElem;
    854                 size_t asize, alignment = 0;
    855                 headers( "realloc", addr, header, freeElem, asize, alignment );
    856 
    857                 size_t usize = asize - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    858                 if ( usize >= size ) {                                                  // already sufficient storage
     862                size_t bsize, oalign = 0;
     863                headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     864
     865                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     866          if ( size <= odsize && odsize <= size * 2 ) { // allow up to 50% wasted storage in smaller size
     867                        // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know
     868                        // where to start filling, i.e., do not overwrite existing values in space.
     869                        //
    859870                        // This case does not result in a new profiler entry because the previous one still exists and it must match with
    860871                        // the free for this memory.  Hence, this realloc does not appear in the profiler output.
    861                         return addr;
     872                        return oaddr;
    862873                } // if
    863874
     
    866877                #endif // __STATISTICS__
    867878
    868                 void * area;
    869                 if ( unlikely( alignment != 0 ) ) {                             // previous request memalign?
    870                         area = memalign( alignment, size );                     // create new aligned area
     879                // change size and copy old content to new storage
     880
     881                void * naddr;
     882                if ( unlikely( oalign != 0 ) ) {                                // previous request memalign?
     883                        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     884                                naddr = cmemalignNoStats( oalign, 1, size ); // create new aligned area
     885                        } else {
     886                                naddr = memalignNoStats( oalign, size ); // create new aligned area
     887                        } // if
    871888                } else {
    872                         area = mallocNoStats( size );                           // create new area
     889                        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     890                                naddr = callocNoStats( 1, size );               // create new area
     891                        } else {
     892                                naddr = mallocNoStats( size );                  // create new area
     893                        } // if
    873894                } // if
    874           if ( unlikely( area == 0 ) ) return 0;
    875                 if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill (calloc/cmemalign) ?
    876                         assert( (header->kind.real.blockSize & 1) == 0 );
    877                         bool mapped __attribute__(( unused )) = headers( "realloc", area, header, freeElem, asize, alignment );
    878                         #ifndef __CFA_DEBUG__
    879                         // Mapped storage is zero filled, but in debug mode mapped memory is scrubbed in doMalloc, so it has to be reset to zero.
    880                         if ( ! mapped )
    881                         #endif // __CFA_DEBUG__
    882                                 memset( (char *)area + usize, '\0', asize - ( (char *)area - (char *)header ) - usize ); // zero-fill back part
    883                         header->kind.real.blockSize |= 2;                       // mark new request as zero fill
    884                 } // if
    885                 memcpy( area, addr, usize );                                    // copy bytes
    886                 free( addr );
    887                 return area;
     895          if ( unlikely( naddr == 0p ) ) return 0p;
     896
     897                headers( "realloc", naddr, header, freeElem, bsize, oalign );
     898                size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
     899                // To preserve prior fill, the entire bucket must be copied versus the size.
     900                memcpy( naddr, oaddr, MIN( odsize, ndsize ) );  // copy bytes
     901                free( oaddr );
     902                return naddr;
    888903        } // realloc
    889 
    890904
    891905        // The obsolete function memalign() allocates size bytes and returns a pointer to the allocated memory. The memory
     
    897911                #endif // __STATISTICS__
    898912
    899                 void * area = memalignNoStats( alignment, size );
    900 
    901                 return area;
     913                return memalignNoStats( alignment, size );
    902914        } // memalign
     915
     916
     917        // The cmemalign() function is the same as calloc() with memory alignment.
     918        void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ) {
     919                #ifdef __STATISTICS__
     920                __atomic_add_fetch( &cmemalign_calls, 1, __ATOMIC_SEQ_CST );
     921                __atomic_add_fetch( &cmemalign_storage, noOfElems * elemSize, __ATOMIC_SEQ_CST );
     922                #endif // __STATISTICS__
     923
     924                return cmemalignNoStats( alignment, noOfElems, elemSize );
     925        } // cmemalign
    903926
    904927        // The function aligned_alloc() is the same as memalign(), except for the added restriction that size should be a
     
    911934        // The function posix_memalign() allocates size bytes and places the address of the allocated memory in *memptr. The
    912935        // address of the allocated memory will be a multiple of alignment, which must be a power of two and a multiple of
    913         // sizeof(void *). If size is 0, then posix_memalign() returns either NULL, or a unique pointer value that can later
     936        // sizeof(void *). If size is 0, then posix_memalign() returns either 0p, or a unique pointer value that can later
    914937        // be successfully passed to free(3).
    915938        int posix_memalign( void ** memptr, size_t alignment, size_t size ) {
    916939          if ( alignment < sizeof(void *) || ! libPow2( alignment ) ) return EINVAL; // check alignment
    917940                * memptr = memalign( alignment, size );
    918           if ( unlikely( * memptr == 0 ) ) return ENOMEM;
     941          if ( unlikely( * memptr == 0p ) ) return ENOMEM;
    919942                return 0;
    920943        } // posix_memalign
     
    929952        // The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to
    930953        // malloc(), calloc() or realloc().  Otherwise, or if free(ptr) has already been called before, undefined behavior
    931         // occurs. If ptr is NULL, no operation is performed.
     954        // occurs. If ptr is 0p, no operation is performed.
    932955        void free( void * addr ) {
    933956                #ifdef __STATISTICS__
     
    935958                #endif // __STATISTICS__
    936959
    937                 // #comment TD : To decrease nesting I would but the special case in the
    938                 //               else instead, plus it reads more naturally to have the
    939                 //               short / normal case instead
    940                 if ( unlikely( addr == 0 ) ) {                                  // special case
    941                         #ifdef __CFA_DEBUG__
    942                         if ( traceHeap() ) {
    943                                 #define nullmsg "Free( 0x0 ) size:0\n"
    944                                 // Do not debug print free( 0 ), as it can cause recursive entry from sprintf.
    945                                 __cfaabi_dbg_bits_write( nullmsg, sizeof(nullmsg) - 1 );
    946                         } // if
    947                         #endif // __CFA_DEBUG__
     960          if ( unlikely( addr == 0p ) ) {                                       // special case
     961                        // #ifdef __CFA_DEBUG__
     962                        // if ( traceHeap() ) {
     963                        //      #define nullmsg "Free( 0x0 ) size:0\n"
     964                        //      // Do not debug print free( 0p ), as it can cause recursive entry from sprintf.
     965                        //      __cfaabi_dbg_write( nullmsg, sizeof(nullmsg) - 1 );
     966                        // } // if
     967                        // #endif // __CFA_DEBUG__
    948968                        return;
    949969                } // exit
     
    951971                doFree( addr );
    952972        } // free
     973
     974
     975        // The malloc_alignment() function returns the alignment of the allocation.
     976        size_t malloc_alignment( void * addr ) {
     977          if ( unlikely( addr == 0p ) ) return libAlign();      // minimum alignment
     978                HeapManager.Storage.Header * header = headerAddr( addr );
     979                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     980                        return header->kind.fake.alignment & -2;        // remove flag from value
     981                } else {
     982                        return libAlign ();                                                     // minimum alignment
     983                } // if
     984        } // malloc_alignment
     985
     986
     987        // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
     988        bool malloc_zero_fill( void * addr ) {
     989          if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     990                HeapManager.Storage.Header * header = headerAddr( addr );
     991                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     992                        header = (HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset);
     993                } // if
     994                return (header->kind.real.blockSize & 2) != 0;  // zero filled (calloc/cmemalign) ?
     995        } // malloc_zero_fill
     996
     997
     998        // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
     999        // a block of memory allocated by malloc(3) or a related function.
     1000        size_t malloc_usable_size( void * addr ) {
     1001          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
     1002                HeapManager.Storage.Header * header;
     1003                HeapManager.FreeHeader * freeElem;
     1004                size_t bsize, alignment;
     1005
     1006                headers( "malloc_usable_size", addr, header, freeElem, bsize, alignment );
     1007                return dataStorage( bsize, addr, header );      // data storage in bucket
     1008        } // malloc_usable_size
     1009
     1010
     1011        // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
     1012        // related functions.
     1013        void malloc_stats( void ) {
     1014                #ifdef __STATISTICS__
     1015                printStats();
     1016                if ( prtFree() ) prtFree( heapManager );
     1017                #endif // __STATISTICS__
     1018        } // malloc_stats
     1019
     1020        // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.
     1021        int malloc_stats_fd( int fd __attribute__(( unused )) ) {
     1022                #ifdef __STATISTICS__
     1023                int temp = statfd;
     1024                statfd = fd;
     1025                return temp;
     1026                #else
     1027                return -1;
     1028                #endif // __STATISTICS__
     1029        } // malloc_stats_fd
     1030
    9531031
    9541032        // The mallopt() function adjusts parameters that control the behavior of the memory-allocation functions (see
     
    9581036                choose( option ) {
    9591037                  case M_TOP_PAD:
    960                         if ( setHeapExpand( value ) ) fallthru default;
     1038                        if ( setHeapExpand( value ) ) return 1;
    9611039                  case M_MMAP_THRESHOLD:
    962                         if ( setMmapStart( value ) ) fallthru default;
    963                   default:
    964                         // #comment TD : 1 for unsopported feels wrong
    965                         return 1;                                                                       // success, or unsupported
     1040                        if ( setMmapStart( value ) ) return 1;
    9661041                } // switch
    967                 return 0;                                                                               // error
     1042                return 0;                                                                               // error, unsupported
    9681043        } // mallopt
    9691044
     
    9741049        } // malloc_trim
    9751050
    976         // The malloc_usable_size() function returns the number of usable bytes in the block pointed to by ptr, a pointer to
    977         // a block of memory allocated by malloc(3) or a related function.
    978         size_t malloc_usable_size( void * addr ) {
    979           if ( unlikely( addr == 0 ) ) return 0;                        // null allocation has 0 size
    980 
    981                 HeapManager.Storage.Header * header;
    982                 HeapManager.FreeHeader * freeElem;
    983                 size_t size, alignment;
    984 
    985                 headers( "malloc_usable_size", addr, header, freeElem, size, alignment );
    986                 size_t usize = size - ( (char *)addr - (char *)header ); // compute the amount of user storage in the block
    987                 return usize;
    988         } // malloc_usable_size
    989 
    990 
    991     // The malloc_alignment() function returns the alignment of the allocation.
    992         size_t malloc_alignment( void * addr ) {
    993           if ( unlikely( addr == 0 ) ) return libAlign();       // minimum alignment
    994                 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
    995                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    996                         return header->kind.fake.alignment & -2;        // remove flag from value
    997                 } else {
    998                         return libAlign ();                                                     // minimum alignment
    999                 } // if
    1000         } // malloc_alignment
    1001 
    1002 
    1003     // The malloc_zero_fill() function returns true if the allocation is zero filled, i.e., initially allocated by calloc().
    1004         bool malloc_zero_fill( void * addr ) {
    1005           if ( unlikely( addr == 0 ) ) return false;            // null allocation is not zero fill
    1006 
    1007                 HeapManager.Storage.Header * header = (HeapManager.Storage.Header *)( (char *)addr - sizeof(HeapManager.Storage) );
    1008                 if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
    1009                         header = (HeapManager.Storage.Header *)((char *)header - header->kind.fake.offset);
    1010                 } // if
    1011                 return (header->kind.real.blockSize & 2) != 0;  // zero filled (calloc/cmemalign) ?
    1012         } // malloc_zero_fill
    1013 
    1014 
    1015     // The malloc_stats() function prints (on default standard error) statistics about memory allocated by malloc(3) and
    1016     // related functions.
    1017         void malloc_stats( void ) {
    1018                 #ifdef __STATISTICS__
    1019                 printStats();
    1020                 if ( checkFree() ) checkFree( heapManager );
    1021                 #endif // __STATISTICS__
    1022         } // malloc_stats
    1023 
    1024         // The malloc_stats_fd() function changes the file descripter where malloc_stats() writes the statistics.
    1025         int malloc_stats_fd( int fd ) {
    1026                 #ifdef __STATISTICS__
    1027                 int temp = statfd;
    1028                 statfd = fd;
    1029                 return temp;
    1030                 #else
    1031                 return -1;
    1032                 #endif // __STATISTICS__
    1033         } // malloc_stats_fd
    10341051
    10351052        // The malloc_info() function exports an XML string that describes the current state of the memory-allocation
     
    10371054        // information about all arenas (see malloc(3)).
    10381055        int malloc_info( int options, FILE * stream ) {
     1056                if ( options != 0 ) { errno = EINVAL; return -1; }
    10391057                return printStatsXML( stream );
    10401058        } // malloc_info
     
    10461064        // structure is returned as the function result.  (It is the caller's responsibility to free(3) this memory.)
    10471065        void * malloc_get_state( void ) {
    1048                 return 0;                                                                               // unsupported
     1066                return 0p;                                                                              // unsupported
    10491067        } // malloc_get_state
    10501068
     
    10581076
    10591077
     1078// Must have CFA linkage to overload with C linkage realloc.
     1079void * realloc( void * oaddr, size_t nalign, size_t size ) {
     1080        #ifdef __STATISTICS__
     1081        __atomic_add_fetch( &realloc_calls, 1, __ATOMIC_SEQ_CST );
     1082        #endif // __STATISTICS__
     1083
     1084        // If size is equal to 0, either NULL or a pointer suitable to be passed to free() is returned.
     1085  if ( unlikely( size == 0 ) ) { free( oaddr ); return mallocNoStats( size ); } // special cases
     1086  if ( unlikely( oaddr == 0p ) ) return mallocNoStats( size );
     1087
     1088        if ( unlikely( nalign == 0 ) ) nalign = libAlign();     // reset alignment to minimum
     1089        #ifdef __CFA_DEBUG__
     1090        else
     1091                checkAlign( nalign );                                                   // check alignment
     1092        #endif // __CFA_DEBUG__
     1093
     1094        HeapManager.Storage.Header * header;
     1095        HeapManager.FreeHeader * freeElem;
     1096        size_t bsize, oalign = 0;
     1097        headers( "realloc", oaddr, header, freeElem, bsize, oalign );
     1098        size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
     1099
     1100  if ( oalign != 0 && (uintptr_t)oaddr % nalign == 0 ) { // has alignment and just happens to work out
     1101                headerAddr( oaddr )->kind.fake.alignment = nalign | 1; // update alignment (could be the same)
     1102                return realloc( oaddr, size );
     1103        } // if
     1104
     1105        #ifdef __STATISTICS__
     1106        __atomic_add_fetch( &realloc_storage, size, __ATOMIC_SEQ_CST );
     1107        #endif // __STATISTICS__
     1108
     1109        // change size and copy old content to new storage
     1110
     1111        void * naddr;
     1112        if ( unlikely( header->kind.real.blockSize & 2 ) ) { // previous request zero fill
     1113                naddr = cmemalignNoStats( nalign, 1, size );    // create new aligned area
     1114        } else {
     1115                naddr = memalignNoStats( nalign, size );                // create new aligned area
     1116        } // if
     1117
     1118        headers( "realloc", naddr, header, freeElem, bsize, oalign );
     1119        size_t ndsize = dataStorage( bsize, naddr, header ); // data storage avilable in bucket
     1120        // To preserve prior fill, the entire bucket must be copied versus the size.
     1121        memcpy( naddr, oaddr, MIN( odsize, ndsize ) );          // copy bytes
     1122        free( oaddr );
     1123        return naddr;
     1124} // realloc
     1125
     1126
    10601127// Local Variables: //
    10611128// tab-width: 4 //
  • libcfa/src/interpose.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 22:57:16 2019
    13 // Update Count     : 116
     12// Last Modified On : Mon Feb 17 10:18:53 2020
     13// Update Count     : 166
    1414//
    1515
     
    2929#include "bits/signal.hfa"                                                              // sigHandler_?
    3030#include "startup.hfa"                                                                  // STARTUP_PRIORITY_CORE
     31#include <assert.h>
    3132
    3233//=============================================================================================
     
    4041
    4142typedef void (* generic_fptr_t)(void);
    42 generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
     43generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    4344        const char * error;
    4445
     
    9596        void __cfaabi_interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
    9697        void __cfaabi_interpose_startup( void ) {
    97                 const char *version = NULL;
     98                const char *version = 0p;
    9899
    99100                preload_libgcc();
     
    105106#pragma GCC diagnostic pop
    106107
     108                // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
     109                // task stacks might be very small (4K) and the signal delivery corrupts memory to the point that a clean
     110                // shutdown is impossible. Also, when a stack overflow encounters the non-accessible sentinel page (debug only)
     111                // and generates a segment fault, the signal cannot be delivered on the sentinel page. Finally, calls to abort
     112                // print a stack trace that uses substantial stack space.
     113
     114                #define MINSTKSZ SIGSTKSZ * 8
     115                static char stack[MINSTKSZ] __attribute__(( aligned (16) ));
     116                static stack_t ss;
     117
     118                ss.ss_sp = stack;
     119                ss.ss_size = MINSTKSZ;
     120                ss.ss_flags = 0;
     121                if ( sigaltstack( &ss, 0p ) == -1 ) {
     122                        abort( "__cfaabi_interpose_startup : internal error, sigaltstack error(%d) %s.", errno, strerror( errno ) );
     123                } // if
     124
    107125                // Failure handler
    108                 __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO );
    109                 __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO );
    110                 __cfaabi_sigaction( SIGILL , sigHandler_ill  , SA_SIGINFO );
    111                 __cfaabi_sigaction( SIGFPE , sigHandler_fpe  , SA_SIGINFO );
    112                 __cfaabi_sigaction( SIGABRT, sigHandler_abrt, SA_SIGINFO | SA_RESETHAND);
    113                 __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO );
    114                 __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO );
     126                __cfaabi_sigaction( SIGSEGV, sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
     127                __cfaabi_sigaction( SIGBUS , sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
     128                __cfaabi_sigaction( SIGILL , sigHandler_ill , SA_SIGINFO | SA_ONSTACK );
     129                __cfaabi_sigaction( SIGFPE , sigHandler_fpe , SA_SIGINFO | SA_ONSTACK );
     130                __cfaabi_sigaction( SIGTERM, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // one shot handler, return to default
     131                __cfaabi_sigaction( SIGINT , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
     132                __cfaabi_sigaction( SIGABRT, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
     133                __cfaabi_sigaction( SIGHUP , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // terminal hangup
    115134        }
    116135}
     
    123142void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    124143void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     144void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    125145
    126146extern "C" {
    127147        void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    128                 abort( NULL );
     148                abort( false, "%s", "" );
    129149        }
    130150
     
    132152                va_list argp;
    133153                va_start( argp, fmt );
    134                 abort( fmt, argp );
     154                abort( false, fmt, argp );
    135155                va_end( argp );
    136156        }
     
    141161}
    142162
    143 void * kernel_abort    ( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return NULL; }
    144 void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
     163void * kernel_abort( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 0p; }
     164void kernel_abort_msg( void * data, char buffer[], int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
     165// See concurrency/kernel.cfa for strong definition used in multi-processor mode.
    145166int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; }
    146167
    147168enum { abort_text_size = 1024 };
    148169static char abort_text[ abort_text_size ];
    149 static int abort_lastframe;
    150 
    151 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
    152     va_list args;
    153     va_start( args, fmt );
    154     vfprintf( stderr, fmt, args );
    155     va_end( args );
    156         __cabi_libc.exit( status );
    157 }
    158 
    159 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
    160         void * kernel_data = kernel_abort();                    // must be done here to lock down kernel
    161         int len;
    162 
    163         abort_lastframe = kernel_abort_lastframe();
    164         len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
    165         __cfaabi_dbg_bits_write( abort_text, len );
    166 
    167         if ( fmt ) {
    168                 va_list args;
    169                 va_start( args, fmt );
    170 
    171                 len = vsnprintf( abort_text, abort_text_size, fmt, args );
    172                 va_end( args );
    173                 __cfaabi_dbg_bits_write( abort_text, len );
    174 
    175                 if ( fmt[strlen( fmt ) - 1] != '\n' ) {         // add optional newline if missing at the end of the format text
    176                         __cfaabi_dbg_bits_write( "\n", 1 );
    177                 }
    178         }
    179 
    180         kernel_abort_msg( kernel_data, abort_text, abort_text_size );
    181         __cabi_libc.abort();
    182 }
    183 
    184 static void __cfaabi_backtrace() {
    185         enum {
    186                 Frames = 50,                                                                    // maximum number of stack frames
    187                 Start = 8,                                                                              // skip first N stack frames
    188         };
     170
     171static void __cfaabi_backtrace( int start ) {
     172        enum { Frames = 50, };                                                          // maximum number of stack frames
     173        int last = kernel_abort_lastframe();                            // skip last N stack frames
    189174
    190175        void * array[Frames];
    191176        size_t size = backtrace( array, Frames );
    192         char ** messages = backtrace_symbols( array, size );
    193 
    194         // find executable name
    195         *index( messages[0], '(' ) = '\0';
    196         __cfaabi_dbg_bits_print_nolock( "Stack back trace for: %s\n", messages[0]);
    197 
    198         for ( int i = Start; i < size - abort_lastframe && messages != NULL; i += 1 ) {
    199                 char * name = NULL, * offset_begin = NULL, * offset_end = NULL;
    200 
    201                 for ( char * p = messages[i]; *p; ++p ) {
    202                         //__cfaabi_dbg_bits_print_nolock( "X %s\n", p);
    203                         // find parantheses and +offset
     177        char ** messages = backtrace_symbols( array, size ); // does not demangle names
     178
     179        *index( messages[0], '(' ) = '\0';                                      // find executable name
     180        __cfaabi_bits_print_nolock( STDERR_FILENO, "Stack back trace for: %s\n", messages[0]);
     181
     182        for ( unsigned int i = start; i < size - last && messages != 0p; i += 1 ) {
     183                char * name = 0p, * offset_begin = 0p, * offset_end = 0p;
     184
     185                for ( char * p = messages[i]; *p; p += 1 ) {    // find parantheses and +offset
     186                        //__cfaabi_bits_print_nolock( "X %s\n", p);
    204187                        if ( *p == '(' ) {
    205188                                name = p;
     
    212195                }
    213196
    214                 // if line contains symbol print it
    215                 int frameNo = i - Start;
     197                // if line contains symbol, print it
     198                int frameNo = i - start;
    216199                if ( name && offset_begin && offset_end && name < offset_begin ) {
    217                         // delimit strings
    218                         *name++ = '\0';
     200                        *name++ = '\0';                                                         // delimit strings
    219201                        *offset_begin++ = '\0';
    220202                        *offset_end++ = '\0';
    221203
    222                         __cfaabi_dbg_bits_print_nolock( "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     204                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
    223205                } else {                                                                                // otherwise, print the whole line
    224                         __cfaabi_dbg_bits_print_nolock( "(%i) %s\n", frameNo, messages[i] );
     206                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s\n", frameNo, messages[i] );
    225207                }
    226208        }
     
    228210}
    229211
     212void exit( int status, const char fmt[], ... ) {
     213        va_list args;
     214        va_start( args, fmt );
     215        vfprintf( stderr, fmt, args );
     216        va_end( args );
     217        __cabi_libc.exit( status );
     218}
     219
     220void abort( bool signalAbort, const char fmt[], ... ) {
     221        void * kernel_data = kernel_abort();                            // must be done here to lock down kernel
     222        int len;
     223
     224        signal( SIGABRT, SIG_DFL );                                                     // prevent final "real" abort from recursing to handler
     225
     226        len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
     227        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
     228
     229        assert( fmt );
     230        va_list args;
     231        va_start( args, fmt );
     232
     233        len = vsnprintf( abort_text, abort_text_size, fmt, args );
     234        va_end( args );
     235        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
     236
     237        if ( fmt[strlen( fmt ) - 1] != '\n' ) {                         // add optional newline if missing at the end of the format text
     238                __cfaabi_dbg_write( "\n", 1 );
     239        } // if
     240        kernel_abort_msg( kernel_data, abort_text, abort_text_size );
     241
     242        __cfaabi_backtrace( signalAbort ? 4 : 2 );
     243
     244        __cabi_libc.abort();                                                            // print stack trace in handler
     245}
     246
     247void abort( const char fmt[], ... ) {
     248        va_list args;
     249        va_start( args, fmt );
     250        abort( false, fmt, args );
     251        va_end( args );
     252}
     253
    230254void sigHandler_segv( __CFA_SIGPARMS__ ) {
    231         abort( "Addressing invalid memory at location %p\n"
    232                         "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
    233                         sfp->si_addr );
     255                if ( sfp->si_addr == 0p ) {
     256                        abort( true, "Null pointer (0p) dereference.\n" );
     257                } else {
     258                        abort( true, "%s at memory location %p.\n"
     259                                   "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
     260                                   (sig == SIGSEGV ? "Segment fault" : "Bus error"), sfp->si_addr );
     261                }
    234262}
    235263
    236264void sigHandler_ill( __CFA_SIGPARMS__ ) {
    237         abort( "Executing illegal instruction at location %p.\n"
     265        abort( true, "Executing illegal instruction at location %p.\n"
    238266                        "Possible cause is stack corruption.\n",
    239267                        sfp->si_addr );
     
    251279          default: msg = "unknown";
    252280        } // choose
    253         abort( "Computation error %s at location %p.\n", msg, sfp->si_addr );
    254 }
    255 
    256 void sigHandler_abrt( __CFA_SIGPARMS__ ) {
    257         __cfaabi_backtrace();
    258 
    259         // reset default signal handler
    260         __cfaabi_sigdefault( SIGABRT );
    261 
    262         raise( SIGABRT );
     281        abort( true, "Computation error %s at location %p.\n", msg, sfp->si_addr );
    263282}
    264283
    265284void sigHandler_term( __CFA_SIGPARMS__ ) {
    266         abort( "Application stopped by %s signal.", sig == SIGINT ? "an interrupt (SIGINT)" : "a terminate (SIGTERM)" );
     285        abort( true, "Application interrupted by signal: %s.\n", strsignal( sig ) );
    267286}
    268287
  • libcfa/src/iostream.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 13 08:07:59 2019
    13 // Update Count     : 821
     12// Last Modified On : Thu Feb 20 15:53:23 2020
     13// Update Count     : 829
    1414//
    1515
     
    1919#include <stdio.h>
    2020#include <stdbool.h>                                                                    // true/false
     21#include <stdint.h>                                                                             // UINT64_MAX
    2122//#include <string.h>                                                                   // strlen, strcmp
    2223extern size_t strlen (const char *__s) __attribute__ ((__nothrow__ , __leaf__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1)));
     
    3536forall( dtype ostype | ostream( ostype ) ) {
    3637        ostype & ?|?( ostype & os, zero_t ) {
    37                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     38                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    3839                fmt( os, "%d", 0n );
    3940                return os;
     
    4445
    4546        ostype & ?|?( ostype & os, one_t ) {
    46                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     47                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    4748                fmt( os, "%d", 1n );
    4849                return os;
     
    5354
    5455        ostype & ?|?( ostype & os, bool b ) {
    55                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     56                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    5657                fmt( os, "%s", b ? "true" : "false" );
    5758                return os;
     
    6364        ostype & ?|?( ostype & os, char c ) {
    6465                fmt( os, "%c", c );
    65                 if ( c == '\n' ) setNL( os, true );
     66                if ( c == '\n' ) $setNL( os, true );
    6667                return sepOff( os );
    6768        } // ?|?
     
    7172
    7273        ostype & ?|?( ostype & os, signed char sc ) {
    73                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     74                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    7475                fmt( os, "%hhd", sc );
    7576                return os;
     
    8081
    8182        ostype & ?|?( ostype & os, unsigned char usc ) {
    82                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     83                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    8384                fmt( os, "%hhu", usc );
    8485                return os;
     
    8990
    9091        ostype & ?|?( ostype & os, short int si ) {
    91                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     92                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    9293                fmt( os, "%hd", si );
    9394                return os;
     
    9899
    99100        ostype & ?|?( ostype & os, unsigned short int usi ) {
    100                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     101                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    101102                fmt( os, "%hu", usi );
    102103                return os;
     
    107108
    108109        ostype & ?|?( ostype & os, int i ) {
    109                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     110                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    110111                fmt( os, "%d", i );
    111112                return os;
     
    116117
    117118        ostype & ?|?( ostype & os, unsigned int ui ) {
    118                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     119                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    119120                fmt( os, "%u", ui );
    120121                return os;
     
    125126
    126127        ostype & ?|?( ostype & os, long int li ) {
    127                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     128                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    128129                fmt( os, "%ld", li );
    129130                return os;
     
    134135
    135136        ostype & ?|?( ostype & os, unsigned long int uli ) {
    136                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     137                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    137138                fmt( os, "%lu", uli );
    138139                return os;
     
    143144
    144145        ostype & ?|?( ostype & os, long long int lli ) {
    145                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     146                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    146147                fmt( os, "%lld", lli );
    147148                return os;
     
    152153
    153154        ostype & ?|?( ostype & os, unsigned long long int ulli ) {
    154                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     155                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    155156                fmt( os, "%llu", ulli );
    156157                return os;
     
    159160                (ostype &)(os | ulli); ends( os );
    160161        } // ?|?
     162
     163#if defined( __SIZEOF_INT128__ )
     164        //      UINT64_MAX 18_446_744_073_709_551_615_ULL
     165        #define P10_UINT64 10_000_000_000_000_000_000_ULL       // 19 zeroes
     166
     167        static void base10_128( ostype & os, unsigned int128 val ) {
     168                if ( val > UINT64_MAX ) {
     169                        base10_128( os, val / P10_UINT64 );                     // recursive
     170                        fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) );
     171                } else {
     172                        fmt( os, "%lu", (uint64_t)val );
     173                } // if
     174        } // base10_128
     175
     176        static void base10_128( ostype & os, int128 val ) {
     177                if ( val < 0 ) {
     178                        fmt( os, "-" );                                                         // leading negative sign
     179                        val = -val;
     180                } // if
     181                base10_128( os, (unsigned int128)val );                 // print zero/positive value
     182        } // base10_128
     183
     184        ostype & ?|?( ostype & os, int128 llli ) {
     185                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
     186                base10_128( os, llli );
     187                return os;
     188        } // ?|?
     189        void & ?|?( ostype & os, int128 llli ) {
     190                (ostype &)(os | llli); ends( os );
     191        } // ?|?
     192
     193        ostype & ?|?( ostype & os, unsigned int128 ullli ) {
     194                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
     195                base10_128( os, ullli );
     196                return os;
     197        } // ?|?
     198        void & ?|?( ostype & os, unsigned int128 ullli ) {
     199                (ostype &)(os | ullli); ends( os );
     200        } // ?|?
     201#endif // __SIZEOF_INT128__
    161202
    162203        #define PrintWithDP( os, format, val, ... ) \
     
    175216
    176217        ostype & ?|?( ostype & os, float f ) {
    177                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     218                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    178219                PrintWithDP( os, "%g", f );
    179220                return os;
     
    184225
    185226        ostype & ?|?( ostype & os, double d ) {
    186                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     227                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    187228                PrintWithDP( os, "%.*lg", d, DBL_DIG );
    188229                return os;
     
    193234
    194235        ostype & ?|?( ostype & os, long double ld ) {
    195                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     236                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    196237                PrintWithDP( os, "%.*Lg", ld, LDBL_DIG );
    197238                return os;
     
    202243
    203244        ostype & ?|?( ostype & os, float _Complex fc ) {
    204                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     245                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    205246//              os | crealf( fc ) | nonl;
    206247                PrintWithDP( os, "%g", crealf( fc ) );
     
    214255
    215256        ostype & ?|?( ostype & os, double _Complex dc ) {
    216                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     257                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    217258//              os | creal( dc ) | nonl;
    218259                PrintWithDP( os, "%.*lg", creal( dc ), DBL_DIG );
     
    226267
    227268        ostype & ?|?( ostype & os, long double _Complex ldc ) {
    228                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     269                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    229270//              os | creall( ldc ) || nonl;
    230271                PrintWithDP( os, "%.*Lg", creall( ldc ), LDBL_DIG );
     
    237278        } // ?|?
    238279
    239         ostype & ?|?( ostype & os, const char * str ) {
     280        ostype & ?|?( ostype & os, const char str[] ) {
    240281                enum { Open = 1, Close, OpenClose };
    241282                static const unsigned char mask[256] @= {
     
    257298                // first character IS NOT spacing or closing punctuation => add left separator
    258299                unsigned char ch = str[0];                                              // must make unsigned
    259                 if ( sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {
    260                         fmt( os, "%s", sepGetCur( os ) );
     300                if ( $sepPrt( os ) && mask[ ch ] != Close && mask[ ch ] != OpenClose ) {
     301                        fmt( os, "%s", $sepGetCur( os ) );
    261302                } // if
    262303
    263304                // if string starts line, must reset to determine open state because separator is off
    264                 sepReset( os );                                                                 // reset separator
     305                $sepReset( os );                                                                // reset separator
    265306
    266307                // last character IS spacing or opening punctuation => turn off separator for next item
    267308                size_t len = strlen( str );
    268309                ch = str[len - 1];                                                              // must make unsigned
    269                 if ( sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
     310                if ( $sepPrt( os ) && mask[ ch ] != Open && mask[ ch ] != OpenClose ) {
    270311                        sepOn( os );
    271312                } else {
    272313                        sepOff( os );
    273314                } // if
    274                 if ( ch == '\n' ) setNL( os, true );                    // check *AFTER* sepPrt call above as it resets NL flag
     315                if ( ch == '\n' ) $setNL( os, true );                   // check *AFTER* $sepPrt call above as it resets NL flag
    275316                return write( os, str, len );
    276317        } // ?|?
    277         void ?|?( ostype & os, const char * str ) {
     318
     319        void ?|?( ostype & os, const char str[] ) {
    278320                (ostype &)(os | str); ends( os );
    279321        } // ?|?
    280322
    281323//      ostype & ?|?( ostype & os, const char16_t * str ) {
    282 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     324//              if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    283325//              fmt( os, "%ls", str );
    284326//              return os;
     
    287329// #if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
    288330//      ostype & ?|?( ostype & os, const char32_t * str ) {
    289 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     331//              if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    290332//              fmt( os, "%ls", str );
    291333//              return os;
     
    294336
    295337//      ostype & ?|?( ostype & os, const wchar_t * str ) {
    296 //              if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     338//              if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    297339//              fmt( os, "%ls", str );
    298340//              return os;
     
    300342
    301343        ostype & ?|?( ostype & os, const void * p ) {
    302                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     344                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    303345                fmt( os, "%p", p );
    304346                return os;
     
    315357        void ?|?( ostype & os, ostype & (* manip)( ostype & ) ) {
    316358                (ostype &)(manip( os ));
    317                 if ( getPrt( os ) ) ends( os );                                 // something printed ?
    318                 setPrt( os, false );                                                    // turn off
     359                if ( $getPrt( os ) ) ends( os );                                // something printed ?
     360                $setPrt( os, false );                                                   // turn off
    319361        } // ?|?
    320362
     
    329371        ostype & nl( ostype & os ) {
    330372                (ostype &)(os | '\n');
    331                 setPrt( os, false );                                                    // turn off
    332                 setNL( os, true );
     373                $setPrt( os, false );                                                   // turn off
     374                $setNL( os, true );
    333375                flush( os );
    334376                return sepOff( os );                                                    // prepare for next line
     
    336378
    337379        ostype & nonl( ostype & os ) {
    338                 setPrt( os, false );                                                    // turn off
     380                $setPrt( os, false );                                                   // turn off
    339381                return os;
    340382        } // nonl
     
    375417        ostype & ?|?( ostype & os, T arg, Params rest ) {
    376418                (ostype &)(os | arg);                                                   // print first argument
    377                 sepSetCur( os, sepGetTuple( os ) );                             // switch to tuple separator
     419                $sepSetCur( os, sepGetTuple( os ) );                    // switch to tuple separator
    378420                (ostype &)(os | rest);                                                  // print remaining arguments
    379                 sepSetCur( os, sepGet( os ) );                                  // switch to regular separator
     421                $sepSetCur( os, sepGet( os ) );                                 // switch to regular separator
    380422                return os;
    381423        } // ?|?
     
    383425                // (ostype &)(?|?( os, arg, rest )); ends( os );
    384426                (ostype &)(os | arg);                                                   // print first argument
    385                 sepSetCur( os, sepGetTuple( os ) );                             // switch to tuple separator
     427                $sepSetCur( os, sepGetTuple( os ) );                    // switch to tuple separator
    386428                (ostype &)(os | rest);                                                  // print remaining arguments
    387                 sepSetCur( os, sepGet( os ) );                                  // switch to regular separator
     429                $sepSetCur( os, sepGet( os ) );                                 // switch to regular separator
    388430                ends( os );
    389431        } // ?|?
     
    414456forall( dtype ostype | ostream( ostype ) ) { \
    415457        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    416                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); \
     458                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
    417459\
    418460                if ( f.base == 'b' || f.base == 'B' ) {                 /* bespoke binary format */ \
     
    463505\
    464506                if ( ! f.flags.pc ) {                                                   /* no precision */ \
    465                         /* printf( "%s\n", &fmtstr[star] ); */ \
    466507                        fmtstr[sizeof(IFMTNP)-2] = f.base;                      /* sizeof includes '\0' */ \
     508                        /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \
    467509                        fmt( os, &fmtstr[star], f.wd, f.val ); \
    468510                } else {                                                                                /* precision */ \
    469511                        fmtstr[sizeof(IFMTP)-2] = f.base;                       /* sizeof includes '\0' */ \
    470                         /* printf( "%s\n", &fmtstr[star] ); */ \
     512                        /* printf( "%s %c %c\n", &fmtstr[star], f.base, CODE ); */ \
    471513                        fmt( os, &fmtstr[star], f.wd, f.pc, f.val ); \
    472514                } /* if */ \
     
    486528IntegralFMTImpl( signed long long int, 'd', "%    *ll ", "%    *.*ll " )
    487529IntegralFMTImpl( unsigned long long int, 'u', "%    *ll ", "%    *.*ll " )
     530
     531
     532#if defined( __SIZEOF_INT128__ )
     533// Default prefix for non-decimal prints is 0b, 0, 0x.
     534#define IntegralFMTImpl128( T, SIGNED, CODE, IFMTNP, IFMTP ) \
     535forall( dtype ostype | ostream( ostype ) ) \
     536static void base10_128( ostype & os, _Ostream_Manip(T) fmt ) { \
     537        if ( fmt.val > UINT64_MAX ) { \
     538                fmt.val /= P10_UINT64; \
     539                base10_128( os, fmt ); /* recursive */ \
     540                _Ostream_Manip(unsigned long long int) fmt2 @= { (uint64_t)(fmt.val % P10_UINT64), 0, 19, 'u', { .all : 0 } }; \
     541                fmt2.flags.nobsdp = true; \
     542                printf( "fmt2 %c %lld %d\n", fmt2.base, fmt2.val, fmt2.all );   \
     543                sepOff( os ); \
     544                (ostype &)(os | fmt2); \
     545        } else { \
     546                printf( "fmt %c %lld %d\n", fmt.base, fmt.val, fmt.all ); \
     547                (ostype &)(os | fmt); \
     548        } /* if */ \
     549} /* base10_128 */                                                 \
     550forall( dtype ostype | ostream( ostype ) ) { \
     551        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
     552                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
     553\
     554                if ( f.base == 'b' | f.base == 'o' | f.base == 'x' | f.base == 'X' ) { \
     555                        unsigned long long int msig = (unsigned long long int)(f.val >> 64); \
     556                        unsigned long long int lsig = (unsigned long long int)(f.val); \
     557                        _Ostream_Manip(SIGNED long long int) fmt @= { msig, f.wd, f.pc, f.base, { .all : f.all } }; \
     558                        _Ostream_Manip(unsigned long long int) fmt2 @= { lsig, 0, 0, f.base, { .all : 0 } }; \
     559                        if ( msig == 0 ) { \
     560                                fmt.val = lsig; \
     561                                (ostype &)(os | fmt); \
     562                        } else { \
     563                                fmt2.flags.pad0 = fmt2.flags.nobsdp = true;     \
     564                                if ( f.base == 'b' ) { \
     565                                        if ( f.wd > 64 ) fmt.wd = f.wd - 64; \
     566                                        fmt2.wd = 64; \
     567                                        (ostype &)(os | fmt | "" | fmt2); \
     568                                } else if ( f.base == 'o' ) { \
     569                                        fmt.val = (unsigned long long int)fmt.val >> 2; \
     570                                        if ( f.wd > 21 ) fmt.wd = f.wd - 21; \
     571                                        fmt2.wd = 1; \
     572                                        fmt2.val = ((msig & 0x3) << 1) + 1; \
     573                                        (ostype &)(os | fmt | "" | fmt2); \
     574                                        sepOff( os ); \
     575                                        fmt2.wd = 21; \
     576                                        fmt2.val = lsig & 0x7fffffffffffffff; \
     577                                        (ostype &)(os | fmt2); \
     578                                } else { \
     579                                        if ( f.flags.left ) { \
     580                                                if ( f.wd > 16 ) fmt2.wd = f.wd - 16;   \
     581                                                fmt.wd = 16;                                                    \
     582                                        } else { \
     583                                                if ( f.wd > 16 ) fmt.wd = f.wd - 16;    \
     584                                                fmt2.wd = 16;                                                   \
     585                                        } /* if */ \
     586                                        (ostype &)(os | fmt | "" | fmt2); \
     587                                } /* if */ \
     588                        } /* if */ \
     589                } else { \
     590                        base10_128( os, f ); \
     591                } /* if */ \
     592                return os; \
     593        } /* ?|? */ \
     594        void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
     595} // distribution
     596
     597IntegralFMTImpl128( int128, signed, 'd', "%    *ll ", "%    *.*ll " )
     598IntegralFMTImpl128( unsigned int128, unsigned, 'u', "%    *ll ", "%    *.*ll " )
     599#endif // __SIZEOF_INT128__
    488600
    489601//*********************************** floating point ***********************************
     
    513625forall( dtype ostype | ostream( ostype ) ) { \
    514626        ostype & ?|?( ostype & os, _Ostream_Manip(T) f ) { \
    515                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); \
     627                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) ); \
    516628                char fmtstr[sizeof(DFMTP)];                                             /* sizeof includes '\0' */ \
    517629                if ( ! f.flags.pc ) memcpy( &fmtstr, DFMTNP, sizeof(DFMTNP) ); \
     
    536648                return os; \
    537649        } /* ?|? */ \
     650\
    538651        void ?|?( ostype & os, _Ostream_Manip(T) f ) { (ostype &)(os | f); ends( os ); } \
    539652} // distribution
     
    555668                } // if
    556669
    557                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     670                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    558671
    559672                #define CFMTNP "% * "
     
    571684                return os;
    572685        } // ?|?
     686
    573687        void ?|?( ostype & os, _Ostream_Manip(char) f ) { (ostype &)(os | f); ends( os ); }
    574688} // distribution
     
    592706                } // if
    593707
    594                 if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
     708                if ( $sepPrt( os ) ) fmt( os, "%s", $sepGetCur( os ) );
    595709
    596710                #define SFMTNP "% * "
     
    616730                return os;
    617731        } // ?|?
     732
    618733        void ?|?( ostype & os, _Ostream_Manip(const char *) f ) { (ostype &)(os | f); ends( os ); }
    619734} // distribution
     
    735850        } // ?|?
    736851
    737         // istype & ?|?( istype & is, const char * fmt ) {
     852        // istype & ?|?( istype & is, const char fmt[] ) {
    738853        //      fmt( is, fmt, "" );
    739854        //      return is;
  • libcfa/src/iostream.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 12 12:08:38 2019
    13 // Update Count     : 334
     12// Last Modified On : Thu Feb 20 15:30:56 2020
     13// Update Count     : 337
    1414//
    1515
     
    2424trait ostream( dtype ostype ) {
    2525        // private
    26         bool sepPrt( ostype & );                                                        // get separator state (on/off)
    27         void sepReset( ostype & );                                                      // set separator state to default state
    28         void sepReset( ostype &, bool );                                        // set separator and default state
    29         const char * sepGetCur( ostype & );                                     // get current separator string
    30         void sepSetCur( ostype &, const char * );                       // set current separator string
    31         bool getNL( ostype & );                                                         // check newline
    32         void setNL( ostype &, bool );                                           // saw newline
    33         bool getANL( ostype & );                                                        // get auto newline (on/off)
    34         bool getPrt( ostype & );                                                        // get fmt called in output cascade
    35         void setPrt( ostype &, bool );                                          // set fmt called in output cascade
     26        bool $sepPrt( ostype & );                                                       // get separator state (on/off)
     27        void $sepReset( ostype & );                                                     // set separator state to default state
     28        void $sepReset( ostype &, bool );                                       // set separator and default state
     29        const char * $sepGetCur( ostype & );                            // get current separator string
     30        void $sepSetCur( ostype &, const char [] );                     // set current separator string
     31        bool $getNL( ostype & );                                                        // check newline
     32        void $setNL( ostype &, bool );                                          // saw newline
     33        bool $getANL( ostype & );                                                       // get auto newline (on/off)
     34        bool $getPrt( ostype & );                                                       // get fmt called in output cascade
     35        void $setPrt( ostype &, bool );                                         // set fmt called in output cascade
    3636        // public
    3737        void sepOn( ostype & );                                                         // turn separator state on
     
    4343
    4444        const char * sepGet( ostype & );                                        // get separator string
    45         void sepSet( ostype &, const char * );                          // set separator to string (15 character maximum)
     45        void sepSet( ostype &, const char [] );                         // set separator to string (15 character maximum)
    4646        const char * sepGetTuple( ostype & );                           // get tuple separator string
    47         void sepSetTuple( ostype &, const char * );                     // set tuple separator to string (15 character maximum)
     47        void sepSetTuple( ostype &, const char [] );            // set tuple separator to string (15 character maximum)
    4848
    4949        void ends( ostype & os );                                                       // end of output statement
    5050        int fail( ostype & );
    5151        int flush( ostype & );
    52         void open( ostype & os, const char * name, const char * mode );
     52        void open( ostype & os, const char name[], const char mode[] );
    5353        void close( ostype & os );
    54         ostype & write( ostype &, const char *, size_t );
     54        ostype & write( ostype &, const char [], size_t );
    5555        int fmt( ostype &, const char format[], ... ) __attribute__(( format(printf, 2, 3) ));
    5656}; // ostream
     
    9898        ostype & ?|?( ostype &, unsigned long long int );
    9999        void ?|?( ostype &, unsigned long long int );
     100#if defined( __SIZEOF_INT128__ )
     101        ostype & ?|?( ostype &, int128 );
     102        void ?|?( ostype &, int128 );
     103        ostype & ?|?( ostype &, unsigned int128 );
     104        void ?|?( ostype &, unsigned int128 );
     105#endif // __SIZEOF_INT128__
    100106
    101107        ostype & ?|?( ostype &, float );
     
    113119        void ?|?( ostype &, long double _Complex );
    114120
    115         ostype & ?|?( ostype &, const char * );
    116         void ?|?( ostype &, const char * );
     121        ostype & ?|?( ostype &, const char [] );
     122        void ?|?( ostype &, const char [] );
    117123        // ostype & ?|?( ostype &, const char16_t * );
    118124#if ! ( __ARM_ARCH_ISA_ARM == 1 && __ARM_32BIT_STATE == 1 ) // char32_t == wchar_t => ambiguous
     
    206212IntegralFMTDecl( signed long long int, 'd' )
    207213IntegralFMTDecl( unsigned long long int, 'u' )
     214#if defined( __SIZEOF_INT128__ )
     215IntegralFMTDecl( int128, 'd' )
     216IntegralFMTDecl( unsigned int128, 'u' )
     217#endif
    208218
    209219//*********************************** floating point ***********************************
     
    256266
    257267static inline {
    258         _Ostream_Manip(const char *) bin( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; }
    259         _Ostream_Manip(const char *) oct( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; }
    260         _Ostream_Manip(const char *) hex( const char * s ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; }
    261         _Ostream_Manip(const char *) wd( unsigned int w, const char * s ) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; }
    262         _Ostream_Manip(const char *) wd( unsigned int w, unsigned char pc, const char * s ) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; }
     268        _Ostream_Manip(const char *) bin( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'b', { .all : 0 } }; }
     269        _Ostream_Manip(const char *) oct( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'o', { .all : 0 } }; }
     270        _Ostream_Manip(const char *) hex( const char s[] ) { return (_Ostream_Manip(const char *))@{ s, 1, 0, 'x', { .all : 0 } }; }
     271        _Ostream_Manip(const char *) wd( unsigned int w, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, 0, 's', { .all : 0 } }; }
     272        _Ostream_Manip(const char *) wd( unsigned int w, unsigned char pc, const char s[] ) { return (_Ostream_Manip(const char *))@{ s, w, pc, 's', { .flags.pc : true } }; }
    263273        _Ostream_Manip(const char *) & wd( unsigned int w, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; return fmt; }
    264274        _Ostream_Manip(const char *) & wd( unsigned int w, unsigned char pc, _Ostream_Manip(const char *) & fmt ) { fmt.wd = w; fmt.pc = pc; fmt.flags.pc = true; return fmt; }
     
    281291        int fail( istype & );
    282292        int eof( istype & );
    283         void open( istype & is, const char * name );
     293        void open( istype & is, const char name[] );
    284294        void close( istype & is );
    285295        istype & read( istype &, char *, size_t );
     
    316326        istype & ?|?( istype &, long double _Complex & );
    317327
    318 //      istype & ?|?( istype &, const char * );
     328//      istype & ?|?( istype &, const char [] );
    319329        istype & ?|?( istype &, char * );
    320330
     
    343353static inline {
    344354        _Istream_Cstr skip( unsigned int n ) { return (_Istream_Cstr){ 0p, 0p, n, { .all : 0 } }; }
    345         _Istream_Cstr skip( const char * scanset ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; }
    346         _Istream_Cstr incl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; }
    347         _Istream_Cstr & incl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
    348         _Istream_Cstr excl( const char * scanset, char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
    349         _Istream_Cstr & excl( const char * scanset, _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
    350         _Istream_Cstr ignore( const char * s ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
     355        _Istream_Cstr skip( const char scanset[] ) { return (_Istream_Cstr){ 0p, scanset, -1, { .all : 0 } }; }
     356        _Istream_Cstr incl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : false } }; }
     357        _Istream_Cstr & incl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = false; return fmt; }
     358        _Istream_Cstr excl( const char scanset[], char * s ) { return (_Istream_Cstr){ s, scanset, -1, { .flags.inex : true } }; }
     359        _Istream_Cstr & excl( const char scanset[], _Istream_Cstr & fmt ) { fmt.scanset = scanset; fmt.flags.inex = true; return fmt; }
     360        _Istream_Cstr ignore( const char s[] ) { return (_Istream_Cstr)@{ s, 0p, -1, { .flags.ignore : true } }; }
    351361        _Istream_Cstr & ignore( _Istream_Cstr & fmt ) { fmt.flags.ignore = true; return fmt; }
    352         _Istream_Cstr wdi( unsigned int w, char * s ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
     362        _Istream_Cstr wdi( unsigned int w, char s[] ) { return (_Istream_Cstr)@{ s, 0p, w, { .all : 0 } }; }
    353363        _Istream_Cstr & wdi( unsigned int w, _Istream_Cstr & fmt ) { fmt.wd = w; return fmt; }
    354364} // distribution
  • libcfa/src/math.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Apr 18 23:37:04 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 13 11:02:15 2018
    13 // Update Count     : 116
     12// Last Modified On : Tue Feb  4 10:27:11 2020
     13// Update Count     : 117
    1414//
    1515
     
    5151static inline long double fdim( long double x, long double y ) { return fdiml( x, y ); }
    5252
    53 static inline float nan( const char * tag ) { return nanf( tag ); }
    54 // extern "C" { double nan( const char * ); }
    55 static inline long double nan( const char * tag ) { return nanl( tag ); }
     53static inline float nan( const char tag[] ) { return nanf( tag ); }
     54// extern "C" { double nan( const char [] ); }
     55static inline long double nan( const char tag[] ) { return nanl( tag ); }
    5656
    5757//---------------------- Exponential ----------------------
  • libcfa/src/rational.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed Apr  6 17:54:28 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jul 12 18:12:08 2019
    13 // Update Count     : 184
     12// Last Modified On : Sat Feb  8 17:56:36 2020
     13// Update Count     : 187
    1414//
    1515
     
    5656        } // rational
    5757
     58        void ?{}( Rational(RationalImpl) & r, zero_t ) {
     59                r{ (RationalImpl){0}, (RationalImpl){1} };
     60        } // rational
     61
     62        void ?{}( Rational(RationalImpl) & r, one_t ) {
     63                r{ (RationalImpl){1}, (RationalImpl){1} };
     64        } // rational
    5865
    5966        // getter for numerator/denominator
  • libcfa/src/startup.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jul 24 16:21:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jul 25 16:42:01 2018
    13 // Update Count     : 11
     12// Last Modified On : Tue Feb  4 13:03:18 2020
     13// Update Count     : 30
    1414//
    1515
     16#include <time.h>                                                                               // tzset
    1617#include "startup.hfa"
    17 #include <unistd.h>
    18 
    1918
    2019extern "C" {
    21     static void __cfaabi_appready_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_APPREADY ) ));
     20    void __cfaabi_appready_startup( void ) __attribute__(( constructor( STARTUP_PRIORITY_APPREADY ) ));
    2221    void __cfaabi_appready_startup( void ) {
     22                tzset();                                                                                // initialize time global variables
    2323                #ifdef __CFA_DEBUG__
    2424                extern void heapAppStart();
     
    2727    } // __cfaabi_appready_startup
    2828
    29     static void __cfaabi_appready_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_APPREADY ) ));
     29    void __cfaabi_appready_shutdown( void ) __attribute__(( destructor( STARTUP_PRIORITY_APPREADY ) ));
    3030    void __cfaabi_appready_shutdown( void ) {
    3131                #ifdef __CFA_DEBUG__
     
    4141struct __spinlock_t;
    4242extern "C" {
    43         void __cfaabi_dbg_record(struct __spinlock_t & this, const char * prev_name) __attribute__(( weak )) {}
     43        void __cfaabi_dbg_record(struct __spinlock_t & this, const char prev_name[]) __attribute__(( weak )) {}
    4444}
    4545
  • libcfa/src/stdhdr/assert.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jul 31 23:09:32 2017
    13 // Update Count     : 13
     12// Last Modified On : Tue Feb  4 12:58:49 2020
     13// Update Count     : 15
    1414//
    1515
     
    2727        #define assertf( expr, fmt, ... ) ((expr) ? ((void)0) : __assert_fail_f(__VSTRINGIFY__(expr), __FILE__, __LINE__, __PRETTY_FUNCTION__, fmt, ## __VA_ARGS__ ))
    2828
    29         void __assert_fail_f( const char *assertion, const char *file, unsigned int line, const char *function, const char *fmt, ... ) __attribute__((noreturn, format( printf, 5, 6) ));
     29        void __assert_fail_f( const char assertion[], const char file[], unsigned int line, const char function[], const char fmt[], ... ) __attribute__((noreturn, format( printf, 5, 6) ));
    3030#endif
    3131
  • libcfa/src/stdhdr/bfdlink.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jul 18 07:26:04 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 22 13:49:30 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Feb  7 19:05:08 2020
     13// Update Count     : 6
    1414//
    1515
    1616// include file uses the CFA keyword "with".
    1717#if ! defined( with )                                                                   // nesting ?
    18 #define with `with`                                                                             // make keyword an identifier
     18#define with ``with                                                                             // make keyword an identifier
    1919#define __CFA_BFDLINK_H__
    2020#endif
  • libcfa/src/stdhdr/hwloc.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jul 18 07:45:00 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 22 13:49:58 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Feb  7 19:05:18 2020
     13// Update Count     : 6
    1414//
    1515
    1616// include file uses the CFA keyword "thread".
    1717#if ! defined( thread )                                                                 // nesting ?
    18 #define thread `thread`                                                                 // make keyword an identifier
     18#define thread ``thread                                                                 // make keyword an identifier
    1919#define __CFA_HWLOC_H__
    2020#endif
  • libcfa/src/stdhdr/krb5.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Jul 18 07:55:44 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 22 13:50:24 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Feb  7 19:05:35 2020
     13// Update Count     : 6
    1414//
    1515
    1616// include file uses the CFA keyword "enable".
    1717#if ! defined( enable )                                                                 // nesting ?
    18 #define enable `enable`                                                                 // make keyword an identifier
     18#define enable ``enable                                                                 // make keyword an identifier
    1919#define __CFA_KRB5_H__
    2020#endif
  • libcfa/src/stdhdr/math.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Mon Jul  4 23:25:26 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb 22 18:16:07 2018
    13 // Update Count     : 13
     12// Last Modified On : Fri Feb  7 19:05:27 2020
     13// Update Count     : 15
    1414//
    1515
    1616extern "C" {
    1717#if ! defined( exception )                                                              // nesting ?
    18 #define exception `exception`                                                   // make keyword an identifier
     18#define exception ``exception                                                   // make keyword an identifier
    1919#define __CFA_MATH_H__
    2020#endif
  • libcfa/src/stdhdr/sys/ucontext.h

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Feb  8 23:48:16 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Feb  8 23:50:44 2018
    13 // Update Count     : 4
     12// Last Modified On : Fri Feb  7 19:05:41 2020
     13// Update Count     : 6
    1414//
    1515
    1616#if ! defined( ftype )                                                                  // nesting ?
    17 #define ftype `ftype`                                                                   // make keyword an identifier
     17#define ftype ``ftype                                                                   // make keyword an identifier
    1818#define __CFA_UCONTEXT_H__
    1919#endif
  • libcfa/src/stdlib.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Jan 28 17:10:29 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun 24 17:34:44 2019
    13 // Update Count     : 462
     12// Last Modified On : Tue Feb  4 08:27:08 2020
     13// Update Count     : 486
    1414//
    1515
     
    2121#include <string.h>                                                                             // memcpy, memset
    2222#include <malloc.h>                                                                             // malloc_usable_size
    23 #include <math.h>                                                                               // fabsf, fabs, fabsl
     23//#include <math.h>                                                                             // fabsf, fabs, fabsl
    2424#include <complex.h>                                                                    // _Complex_I
    2525#include <assert.h>
     
    2727//---------------------------------------
    2828
    29 // resize, non-array types
    30 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill ) {
    31         size_t olen = malloc_usable_size( ptr );                        // current allocation
    32     char * nptr = (void *)realloc( (void *)ptr, dim * (size_t)sizeof(T) ); // C realloc
    33         size_t nlen = malloc_usable_size( nptr );                       // new allocation
    34         if ( nlen > olen ) {                                                            // larger ?
    35                 memset( nptr + olen, (int)fill, nlen - olen );  // initialize added storage
    36         } //
    37     return (T *)nptr;
    38 } // alloc
     29forall( dtype T | sized(T) ) {
     30        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
     31                size_t olen = malloc_usable_size( ptr );                // current allocation
     32                void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     33                size_t nlen = malloc_usable_size( nptr );               // new allocation
     34                if ( nlen > olen ) {                                                    // larger ?
     35                        memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     36                } // if
     37                return (T *)nptr;
     38        } // alloc_set
     39
     40        T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
     41                size_t olen = malloc_usable_size( ptr );                // current allocation
     42                void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
     43                // char * nptr = alloc_align( ptr, align );
     44                size_t nlen = malloc_usable_size( nptr );               // new allocation
     45                if ( nlen > olen ) {                                                    // larger ?
     46                        memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
     47                } // if
     48                return (T *)nptr;
     49        } // alloc_align_set
     50} // distribution
    3951
    4052// allocation/deallocation and constructor/destructor, non-array types
    4153forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } )
    4254T * new( Params p ) {
    43         return &(*malloc()){ p };                                                               // run constructor
     55        return &(*malloc()){ p };                                                       // run constructor
    4456} // new
    4557
     
    4759void delete( T * ptr ) {
    4860        if ( ptr ) {                                                                            // ignore null
    49                 ^(*ptr){};                                                                                      // run destructor
     61                ^(*ptr){};                                                                              // run destructor
    5062                free( ptr );
    5163        } // if
     
    5567void delete( T * ptr, Params rest ) {
    5668        if ( ptr ) {                                                                            // ignore null
    57                 ^(*ptr){};                                                                                      // run destructor
     69                ^(*ptr){};                                                                              // run destructor
    5870                free( ptr );
    5971        } // if
     
    95107//---------------------------------------
    96108
    97 float _Complex strto( const char * sptr, char ** eptr ) {
     109float _Complex strto( const char sptr[], char ** eptr ) {
    98110        float re, im;
    99111        char * eeptr;
     
    106118} // strto
    107119
    108 double _Complex strto( const char * sptr, char ** eptr ) {
     120double _Complex strto( const char sptr[], char ** eptr ) {
    109121        double re, im;
    110122        char * eeptr;
     
    117129} // strto
    118130
    119 long double _Complex strto( const char * sptr, char ** eptr ) {
     131long double _Complex strto( const char sptr[], char ** eptr ) {
    120132        long double re, im;
    121133        char * eeptr;
  • libcfa/src/stdlib.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Thu Jan 28 17:12:35 2016
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Jul 23 14:14:59 2019
    13 // Update Count     : 373
     12// Last Modified On : Tue Feb  4 08:27:01 2020
     13// Update Count     : 401
    1414//
    1515
     
    2525        void * memset( void * dest, int fill, size_t size ); // string.h
    2626        void * memcpy( void * dest, const void * src, size_t size ); // string.h
    27     void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA
     27    void * cmemalign( size_t alignment, size_t noOfElems, size_t elemSize ); // CFA heap
    2828} // extern "C"
     29
     30void * realloc( void * oaddr, size_t nalign, size_t size ); // CFA heap
    2931
    3032//---------------------------------------
     
    5052        } // calloc
    5153
    52         T * realloc( T * ptr, size_t size ) {
    53                 if ( unlikely( ptr == 0 ) ) return malloc();
    54                 return (T *)(void *)realloc( (void *)ptr, size );
     54        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
     55                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
    5556        } // realloc
    5657
    5758        T * memalign( size_t align ) {
    58                 return (T *)memalign( align, sizeof(T) );
     59                return (T *)memalign( align, sizeof(T) );               // C memalign
    5960        } // memalign
    6061
     62        T * cmemalign( size_t align, size_t dim  ) {
     63                return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign
     64        } // cmemalign
     65
    6166        T * aligned_alloc( size_t align ) {
    62                 return (T *)aligned_alloc( align, sizeof(T) );
     67                return (T *)aligned_alloc( align, sizeof(T) );  // C aligned_alloc
    6368        } // aligned_alloc
    6469
     
    6772        } // posix_memalign
    6873
    69 
    7074        // Cforall dynamic allocation
    7175
     
    7478        } // alloc
    7579
    76         T * alloc( char fill ) {
    77                 T * ptr;
    78                 if ( _Alignof(T) <= libAlign() ) ptr = (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    79                 else ptr = (T *)memalign( _Alignof(T), sizeof(T) );
    80                 return (T *)memset( ptr, (int)fill, sizeof(T) ); // initialize with fill value
    81         } // alloc
    82 
    8380        T * alloc( size_t dim ) {
    84                 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( dim * (size_t)sizeof(T) ); // C malloc
     81                if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( dim * (size_t)sizeof(T) );
    8582                else return (T *)memalign( _Alignof(T), dim * sizeof(T) );
    8683        } // alloc
    8784
    88         T * alloc( size_t dim, char fill ) {
     85        T * alloc( T ptr[], size_t dim ) {                                      // realloc
     86                return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     87        } // alloc
     88
     89        T * alloc_set( char fill ) {
     90                return (T *)memset( (T *)alloc(), (int)fill, sizeof(T) ); // initialize with fill value
     91        } // alloc
     92
     93        T * alloc_set( T fill ) {
     94                return (T *)memcpy( (T *)alloc(), &fill, sizeof(T) ); // initialize with fill value
     95        } // alloc
     96
     97        T * alloc_set( size_t dim, char fill ) {
    8998                return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
    9099        } // alloc
    91100
    92         T * alloc( T ptr[], size_t dim ) {
    93                 return realloc( ptr, dim * sizeof(T) );
    94         } // alloc
    95 } // distribution
    96 
    97 
    98 static inline forall( dtype T | sized(T) ) {
    99         T * align_alloc( size_t align ) {
     101        T * alloc_set( size_t dim, T fill ) {
     102                T * r = (T *)alloc( dim );
     103                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
     104                return r;
     105        } // alloc
     106
     107        T * alloc_set( size_t dim, const T fill[] ) {
     108                return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value
     109        } // alloc
     110} // distribution
     111
     112forall( dtype T | sized(T) ) {
     113        T * alloc_set( T ptr[], size_t dim, char fill );        // realloc array with fill
     114} // distribution
     115
     116static inline forall( dtype T | sized(T) ) {
     117        T * alloc_align( size_t align ) {
    100118                return (T *)memalign( align, sizeof(T) );
    101         } // align_alloc
    102 
    103         T * align_alloc( size_t align, char fill ) {
    104                 T * ptr = (T *)memalign( align, sizeof(T) );
    105                 return (T *)memset( ptr, (int)fill, sizeof(T) );
    106         } // align_alloc
    107 
    108         T * align_alloc( size_t align, size_t dim ) {
     119        } // alloc_align
     120
     121        T * alloc_align( size_t align, size_t dim ) {
    109122                return (T *)memalign( align, dim * sizeof(T) );
    110         } // align_alloc
    111 
    112         T * align_alloc( size_t align, size_t dim, char fill ) {
    113                 if ( fill == '\0' ) {
    114                         return (T *)cmemalign( align, dim, sizeof(T) );
    115                 } else {
    116                         return (T *)memset( (T *)memalign( align, dim * sizeof(T) ), (int)fill, dim * sizeof(T) );
    117                 } // if
    118         } // align_alloc
    119 } // distribution
    120 
    121 forall( dtype T | sized(T) ) T * alloc( T ptr[], size_t dim, char fill );
    122 
     123        } // alloc_align
     124
     125        T * alloc_align( T ptr[], size_t align ) {                      // aligned realloc array
     126                return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
     127        } // alloc_align
     128
     129        T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array
     130                return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc
     131        } // alloc_align
     132
     133        T * alloc_align_set( size_t align, char fill ) {
     134                return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value
     135        } // alloc_align
     136
     137        T * alloc_align_set( size_t align, T fill ) {
     138                return (T *)memcpy( (T *)alloc_align( align ), &fill, sizeof(T) ); // initialize with fill value
     139        } // alloc_align
     140
     141        T * alloc_align_set( size_t align, size_t dim, char fill ) {
     142                return (T *)memset( (T *)alloc_align( align, dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value
     143        } // alloc_align
     144
     145        T * alloc_align_set( size_t align, size_t dim, T fill ) {
     146                T * r = (T *)alloc_align( align, dim );
     147                for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value
     148                return r;
     149        } // alloc_align
     150
     151        T * alloc_align_set( size_t align, size_t dim, const T fill[] ) {
     152                return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) );
     153        } // alloc_align
     154} // distribution
     155
     156forall( dtype T | sized(T) ) {
     157        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill
     158} // distribution
    123159
    124160static inline forall( dtype T | sized(T) ) {
    125161        // data, non-array types
    126 
    127162        T * memset( T * dest, char fill ) {
    128163                return (T *)memset( dest, fill, sizeof(T) );
     
    136171static inline forall( dtype T | sized(T) ) {
    137172        // data, array types
    138 
    139173        T * amemset( T dest[], char fill, size_t dim ) {
    140174                return (T *)(void *)memset( dest, fill, dim * sizeof(T) ); // C memset
     
    159193
    160194static inline {
    161         int strto( const char * sptr, char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); }
    162         unsigned int strto( const char * sptr, char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); }
    163         long int strto( const char * sptr, char ** eptr, int base ) { return strtol( sptr, eptr, base ); }
    164         unsigned long int strto( const char * sptr, char ** eptr, int base ) { return strtoul( sptr, eptr, base ); }
    165         long long int strto( const char * sptr, char ** eptr, int base ) { return strtoll( sptr, eptr, base ); }
    166         unsigned long long int strto( const char * sptr, char ** eptr, int base ) { return strtoull( sptr, eptr, base ); }
    167 
    168         float strto( const char * sptr, char ** eptr ) { return strtof( sptr, eptr ); }
    169         double strto( const char * sptr, char ** eptr ) { return strtod( sptr, eptr ); }
    170         long double strto( const char * sptr, char ** eptr ) { return strtold( sptr, eptr ); }
    171 } // distribution
    172 
    173 float _Complex strto( const char * sptr, char ** eptr );
    174 double _Complex strto( const char * sptr, char ** eptr );
    175 long double _Complex strto( const char * sptr, char ** eptr );
     195        int strto( const char sptr[], char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); }
     196        unsigned int strto( const char sptr[], char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); }
     197        long int strto( const char sptr[], char ** eptr, int base ) { return strtol( sptr, eptr, base ); }
     198        unsigned long int strto( const char sptr[], char ** eptr, int base ) { return strtoul( sptr, eptr, base ); }
     199        long long int strto( const char sptr[], char ** eptr, int base ) { return strtoll( sptr, eptr, base ); }
     200        unsigned long long int strto( const char sptr[], char ** eptr, int base ) { return strtoull( sptr, eptr, base ); }
     201
     202        float strto( const char sptr[], char ** eptr ) { return strtof( sptr, eptr ); }
     203        double strto( const char sptr[], char ** eptr ) { return strtod( sptr, eptr ); }
     204        long double strto( const char sptr[], char ** eptr ) { return strtold( sptr, eptr ); }
     205} // distribution
     206
     207float _Complex strto( const char sptr[], char ** eptr );
     208double _Complex strto( const char sptr[], char ** eptr );
     209long double _Complex strto( const char sptr[], char ** eptr );
    176210
    177211static inline {
    178         int ato( const char * sptr ) { return (int)strtol( sptr, 0, 10 ); }
    179         unsigned int ato( const char * sptr ) { return (unsigned int)strtoul( sptr, 0, 10 ); }
    180         long int ato( const char * sptr ) { return strtol( sptr, 0, 10 ); }
    181         unsigned long int ato( const char * sptr ) { return strtoul( sptr, 0, 10 ); }
    182         long long int ato( const char * sptr ) { return strtoll( sptr, 0, 10 ); }
    183         unsigned long long int ato( const char * sptr ) { return strtoull( sptr, 0, 10 ); }
    184 
    185         float ato( const char * sptr ) { return strtof( sptr, 0 ); }
    186         double ato( const char * sptr ) { return strtod( sptr, 0 ); }
    187         long double ato( const char * sptr ) { return strtold( sptr, 0 ); }
    188 
    189         float _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
    190         double _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
    191         long double _Complex ato( const char * sptr ) { return strto( sptr, NULL ); }
     212        int ato( const char sptr[] ) { return (int)strtol( sptr, 0p, 10 ); }
     213        unsigned int ato( const char sptr[] ) { return (unsigned int)strtoul( sptr, 0p, 10 ); }
     214        long int ato( const char sptr[] ) { return strtol( sptr, 0p, 10 ); }
     215        unsigned long int ato( const char sptr[] ) { return strtoul( sptr, 0p, 10 ); }
     216        long long int ato( const char sptr[] ) { return strtoll( sptr, 0p, 10 ); }
     217        unsigned long long int ato( const char sptr[] ) { return strtoull( sptr, 0p, 10 ); }
     218
     219        float ato( const char sptr[] ) { return strtof( sptr, 0p ); }
     220        double ato( const char sptr[] ) { return strtod( sptr, 0p ); }
     221        long double ato( const char sptr[] ) { return strtold( sptr, 0p ); }
     222
     223        float _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); }
     224        double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); }
     225        long double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); }
    192226} // distribution
    193227
  • libcfa/src/time.cfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Mar 27 13:33:14 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 13 08:41:55 2019
    13 // Update Count     : 65
     12// Last Modified On : Tue Feb  4 08:24:18 2020
     13// Update Count     : 70
    1414//
    1515
     
    3333forall( dtype ostype | ostream( ostype ) ) {
    3434        ostype & ?|?( ostype & os, Duration dur ) with( dur ) {
    35                 (ostype &)(os | tv / TIMEGRAN);                                 // print seconds
    36                 long int ns = (tv < 0 ? -tv : tv) % TIMEGRAN;   // compute nanoseconds
     35                (ostype &)(os | tn / TIMEGRAN);                                 // print seconds
     36                long int ns = (tn < 0 ? -tn : tn) % TIMEGRAN;   // compute nanoseconds
    3737                if ( ns != 0 ) {                                                                // some ?
    3838                        char buf[16];
     
    5252
    5353#ifdef __CFA_DEBUG__
    54 static void tabort( int year, int month, int day, int hour, int min, int sec, int nsec ) {
     54static void tabort( int year, int month, int day, int hour, int min, int sec, int64_t nsec ) {
    5555        abort | "Attempt to create Time( year=" | year | "(>=1970), month=" | month | "(1-12), day=" | day | "(1-31), hour=" | hour | "(0-23), min=" | min | "(0-59), sec=" | sec
    56                   | "(0-60), nsec=" | nsec | "(0-999_999_999), which exceeds range 00:00:00 UTC, January 1, 1970 to 03:14:07 UTC, January 19, 2038.";
     56                  | "(0-60), nsec=" | nsec | "(0-999_999_999), which is not in the range 00:00:00 UTC, January 1, 1970 to 03:14:07 UTC, January 19, 2038, where month and day have 1 origin.";
    5757} // tabort
    5858#endif // __CFA_DEBUG__
    5959
    60 void ?{}( Time & time, int year, int month, int day, int hour, int min, int sec, int nsec ) with( time ) {
     60void ?{}( Time & time, int year, int month, int day, int hour, int min, int sec, int64_t nsec ) with( time ) {
    6161        tm tm;
    6262
    63         tm.tm_isdst = -1;                                                                       // let mktime determine if alternate timezone is in effect
     63        // Values can be in any range (+/-) but result must be in the epoch.
    6464        tm.tm_year = year - 1900;                                                       // mktime uses 1900 as its starting point
    65 #ifdef __CFA_DEBUG__
    66         if ( month < 1 || 12 < month ) {
    67                 tabort( year, month, day, hour, min, sec, nsec );
    68         } // if
    69 #endif // __CFA_DEBUG__
     65        // Make month in range 1-12 to match with day.
    7066        tm.tm_mon = month - 1;                                                          // mktime uses range 0-11
    71 #ifdef __CFA_DEBUG__
    72         if ( day < 1 || 31 < day ) {
    73                 tabort( year, month, day, hour, min, sec, nsec );
    74         } // if
    75 #endif // __CFA_DEBUG__
    7667        tm.tm_mday = day;                                                                       // mktime uses range 1-31
    7768        tm.tm_hour = hour;
    7869        tm.tm_min = min;
    7970        tm.tm_sec = sec;
     71        tm.tm_isdst = -1;                                                                       // let mktime determine if alternate timezone is in effect
    8072        time_t epochsec = mktime( &tm );
    8173#ifdef __CFA_DEBUG__
    82         if ( epochsec == (time_t)-1 ) {
     74        if ( epochsec <= (time_t)-1 ) {                                         // MUST BE LESS THAN OR EQUAL!
    8375                tabort( year, month, day, hour, min, sec, nsec );
    8476        } // if
    8577#endif // __CFA_DEBUG__
    86         tv = (int64_t)(epochsec) * TIMEGRAN + nsec;                     // convert to nanoseconds
     78        tn = (int64_t)(epochsec) * TIMEGRAN + nsec;                     // convert to nanoseconds
    8779#ifdef __CFA_DEBUG__
    88         if ( tv > 2147483647LL * TIMEGRAN ) {                           // between 00:00:00 UTC, January 1, 1970 and 03:14:07 UTC, January 19, 2038.
     80        if ( tn > 2147483647LL * TIMEGRAN ) {                           // between 00:00:00 UTC, January 1, 1970 and 03:14:07 UTC, January 19, 2038.
    8981                tabort( year, month, day, hour, min, sec, nsec );
    9082        } // if
     
    9385
    9486char * yy_mm_dd( Time time, char * buf ) with( time ) {
    95         time_t s = tv / TIMEGRAN;
     87        time_t s = tn / TIMEGRAN;
    9688        tm tm;
    9789        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     
    108100
    109101char * mm_dd_yy( Time time, char * buf ) with( time ) {
    110         time_t s = tv / TIMEGRAN;
     102        time_t s = tn / TIMEGRAN;
    111103        tm tm;
    112104        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     
    123115
    124116char * dd_mm_yy( Time time, char * buf ) with( time ) {
    125         time_t s = tv / TIMEGRAN;
     117        time_t s = tn / TIMEGRAN;
    126118        tm tm;
    127119        gmtime_r( &s, &tm );                                                            // tm_mon <= 11, tm_mday <= 31
     
    137129} // dd_mm_yy
    138130
    139 size_t strftime( char * buf, size_t size, const char * fmt, Time time ) with( time ) {
    140         time_t s = tv / TIMEGRAN;
     131size_t strftime( char buf[], size_t size, const char fmt[], Time time ) with( time ) {
     132        time_t s = tn / TIMEGRAN;
    141133        tm tm;
    142134        gmtime_r( &s, &tm );
     
    147139        ostype & ?|?( ostype & os, Time time ) with( time ) {
    148140                char buf[32];                                                                   // at least 26
    149                 time_t s = tv / TIMEGRAN;
     141                time_t s = tn / TIMEGRAN;
    150142                ctime_r( &s, (char *)&buf );                                    // 26 characters: "Wed Jun 30 21:49:08 1993\n"
    151143                buf[24] = '\0';                                                                 // remove trailing '\n'
    152                 long int ns = (tv < 0 ? -tv : tv) % TIMEGRAN;   // compute nanoseconds
     144                long int ns = (tn < 0 ? -tn : tn) % TIMEGRAN;   // compute nanoseconds
    153145                if ( ns == 0 ) {                                                                // none ?
    154146                        (ostype &)(os | buf);                                           // print date/time/year
  • libcfa/src/time.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Wed Mar 14 23:18:57 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Sep 22 12:25:34 2018
    13 // Update Count     : 643
     12// Last Modified On : Tue Feb  4 08:24:32 2020
     13// Update Count     : 654
    1414//
    1515
     
    3232        Duration ?=?( Duration & dur, __attribute__((unused)) zero_t ) { return dur{ 0 }; }
    3333
    34         Duration +?( Duration rhs ) with( rhs ) {       return (Duration)@{ +tv }; }
    35         Duration ?+?( Duration & lhs, Duration rhs ) { return (Duration)@{ lhs.tv + rhs.tv }; }
     34        Duration +?( Duration rhs ) with( rhs ) { return (Duration)@{ +tn }; }
     35        Duration ?+?( Duration & lhs, Duration rhs ) { return (Duration)@{ lhs.tn + rhs.tn }; }
    3636        Duration ?+=?( Duration & lhs, Duration rhs ) { lhs = lhs + rhs; return lhs; }
    3737
    38         Duration -?( Duration rhs ) with( rhs ) { return (Duration)@{ -tv }; }
    39         Duration ?-?( Duration & lhs, Duration rhs ) { return (Duration)@{ lhs.tv - rhs.tv }; }
     38        Duration -?( Duration rhs ) with( rhs ) { return (Duration)@{ -tn }; }
     39        Duration ?-?( Duration & lhs, Duration rhs ) { return (Duration)@{ lhs.tn - rhs.tn }; }
    4040        Duration ?-=?( Duration & lhs, Duration rhs ) { lhs = lhs - rhs; return lhs; }
    4141
    42         Duration ?*?( Duration lhs, int64_t rhs ) { return (Duration)@{ lhs.tv * rhs }; }
    43         Duration ?*?( int64_t lhs, Duration rhs ) { return (Duration)@{ lhs * rhs.tv }; }
     42        Duration ?*?( Duration lhs, int64_t rhs ) { return (Duration)@{ lhs.tn * rhs }; }
     43        Duration ?*?( int64_t lhs, Duration rhs ) { return (Duration)@{ lhs * rhs.tn }; }
    4444        Duration ?*=?( Duration & lhs, int64_t rhs ) { lhs = lhs * rhs; return lhs; }
    4545
    46         int64_t ?/?( Duration lhs, Duration rhs ) { return lhs.tv / rhs.tv; }
    47         Duration ?/?( Duration lhs, int64_t rhs ) { return (Duration)@{ lhs.tv / rhs }; }
     46        int64_t ?/?( Duration lhs, Duration rhs ) { return lhs.tn / rhs.tn; }
     47        Duration ?/?( Duration lhs, int64_t rhs ) { return (Duration)@{ lhs.tn / rhs }; }
    4848        Duration ?/=?( Duration & lhs, int64_t rhs ) { lhs = lhs / rhs; return lhs; }
    49         double div( Duration lhs, Duration rhs ) { return (double)lhs.tv / (double)rhs.tv; }
    50 
    51         Duration ?%?( Duration lhs, Duration rhs ) { return (Duration)@{ lhs.tv % rhs.tv }; }
     49        double div( Duration lhs, Duration rhs ) { return (double)lhs.tn / (double)rhs.tn; }
     50
     51        Duration ?%?( Duration lhs, Duration rhs ) { return (Duration)@{ lhs.tn % rhs.tn }; }
    5252        Duration ?%=?( Duration & lhs, Duration rhs ) { lhs = lhs % rhs; return lhs; }
    5353
    54         bool ?==?( Duration lhs, Duration rhs ) { return lhs.tv == rhs.tv; }
    55         bool ?!=?( Duration lhs, Duration rhs ) { return lhs.tv != rhs.tv; }
    56         bool ?<? ( Duration lhs, Duration rhs ) { return lhs.tv <  rhs.tv; }
    57         bool ?<=?( Duration lhs, Duration rhs ) { return lhs.tv <= rhs.tv; }
    58         bool ?>? ( Duration lhs, Duration rhs ) { return lhs.tv >  rhs.tv; }
    59         bool ?>=?( Duration lhs, Duration rhs ) { return lhs.tv >= rhs.tv; }
    60 
    61         bool ?==?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv == 0; }
    62         bool ?!=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv != 0; }
    63         bool ?<? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv <  0; }
    64         bool ?<=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv <= 0; }
    65         bool ?>? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv >  0; }
    66         bool ?>=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tv >= 0; }
    67 
    68         Duration abs( Duration rhs ) { return rhs.tv >= 0 ? rhs : -rhs; }
     54        bool ?==?( Duration lhs, Duration rhs ) { return lhs.tn == rhs.tn; }
     55        bool ?!=?( Duration lhs, Duration rhs ) { return lhs.tn != rhs.tn; }
     56        bool ?<? ( Duration lhs, Duration rhs ) { return lhs.tn <  rhs.tn; }
     57        bool ?<=?( Duration lhs, Duration rhs ) { return lhs.tn <= rhs.tn; }
     58        bool ?>? ( Duration lhs, Duration rhs ) { return lhs.tn >  rhs.tn; }
     59        bool ?>=?( Duration lhs, Duration rhs ) { return lhs.tn >= rhs.tn; }
     60
     61        bool ?==?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn == 0; }
     62        bool ?!=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn != 0; }
     63        bool ?<? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn <  0; }
     64        bool ?<=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn <= 0; }
     65        bool ?>? ( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn >  0; }
     66        bool ?>=?( Duration lhs, __attribute__((unused)) zero_t ) { return lhs.tn >= 0; }
     67
     68        Duration abs( Duration rhs ) { return rhs.tn >= 0 ? rhs : -rhs; }
    6969
    7070        Duration ?`ns( int64_t nsec ) { return (Duration)@{ nsec }; }
     
    8282        Duration ?`w( double weeks ) { return (Duration)@{ weeks * (7LL * 24LL * 60LL * 60LL * TIMEGRAN) }; }
    8383
    84         int64_t ?`ns( Duration dur ) { return dur.tv; }
    85         int64_t ?`us( Duration dur ) { return dur.tv / (TIMEGRAN / 1_000_000LL); }
    86         int64_t ?`ms( Duration dur ) { return dur.tv / (TIMEGRAN / 1_000LL); }
    87         int64_t ?`s( Duration dur ) { return dur.tv / TIMEGRAN; }
    88         int64_t ?`m( Duration dur ) { return dur.tv / (60LL * TIMEGRAN); }
    89         int64_t ?`h( Duration dur ) { return dur.tv / (60LL * 60LL * TIMEGRAN); }
    90         int64_t ?`d( Duration dur ) { return dur.tv / (24LL * 60LL * 60LL * TIMEGRAN); }
    91         int64_t ?`w( Duration dur ) { return dur.tv / (7LL * 24LL * 60LL * 60LL * TIMEGRAN); }
    92 
    93         Duration max( Duration lhs, Duration rhs ) { return  (lhs.tv < rhs.tv) ? rhs : lhs;}
    94         Duration min( Duration lhs, Duration rhs ) { return !(rhs.tv < lhs.tv) ? lhs : rhs;}
     84        int64_t ?`ns( Duration dur ) { return dur.tn; }
     85        int64_t ?`us( Duration dur ) { return dur.tn / (TIMEGRAN / 1_000_000LL); }
     86        int64_t ?`ms( Duration dur ) { return dur.tn / (TIMEGRAN / 1_000LL); }
     87        int64_t ?`s( Duration dur ) { return dur.tn / TIMEGRAN; }
     88        int64_t ?`m( Duration dur ) { return dur.tn / (60LL * TIMEGRAN); }
     89        int64_t ?`h( Duration dur ) { return dur.tn / (60LL * 60LL * TIMEGRAN); }
     90        int64_t ?`d( Duration dur ) { return dur.tn / (24LL * 60LL * 60LL * TIMEGRAN); }
     91        int64_t ?`w( Duration dur ) { return dur.tn / (7LL * 24LL * 60LL * 60LL * TIMEGRAN); }
     92
     93        Duration max( Duration lhs, Duration rhs ) { return  (lhs.tn < rhs.tn) ? rhs : lhs;}
     94        Duration min( Duration lhs, Duration rhs ) { return !(rhs.tn < lhs.tn) ? lhs : rhs;}
    9595} // distribution
    9696
     
    143143//######################### Time #########################
    144144
    145 void ?{}( Time & time, int year, int month = 0, int day = 0, int hour = 0, int min = 0, int sec = 0, int nsec = 0 );
     145void ?{}( Time & time, int year, int month = 1, int day = 1, int hour = 0, int min = 0, int sec = 0, int64_t nsec = 0 );
    146146static inline {
    147147        Time ?=?( Time & time, __attribute__((unused)) zero_t ) { return time{ 0 }; }
    148148
    149         void ?{}( Time & time, timeval t ) with( time ) { tv = (int64_t)t.tv_sec * TIMEGRAN + t.tv_usec * 1000; }
     149        void ?{}( Time & time, timeval t ) with( time ) { tn = (int64_t)t.tv_sec * TIMEGRAN + t.tv_usec * 1000; }
    150150        Time ?=?( Time & time, timeval t ) with( time ) {
    151                 tv = (int64_t)t.tv_sec * TIMEGRAN + t.tv_usec * (TIMEGRAN / 1_000_000LL);
     151                tn = (int64_t)t.tv_sec * TIMEGRAN + t.tv_usec * (TIMEGRAN / 1_000_000LL);
    152152                return time;
    153153        } // ?=?
    154154
    155         void ?{}( Time & time, timespec t ) with( time ) { tv = (int64_t)t.tv_sec * TIMEGRAN + t.tv_nsec; }
     155        void ?{}( Time & time, timespec t ) with( time ) { tn = (int64_t)t.tv_sec * TIMEGRAN + t.tv_nsec; }
    156156        Time ?=?( Time & time, timespec t ) with( time ) {
    157                 tv = (int64_t)t.tv_sec * TIMEGRAN + t.tv_nsec;
     157                tn = (int64_t)t.tv_sec * TIMEGRAN + t.tv_nsec;
    158158                return time;
    159159        } // ?=?
    160160
    161         Time ?+?( Time & lhs, Duration rhs ) { return (Time)@{ lhs.tv + rhs.tv }; }
     161        Time ?+?( Time & lhs, Duration rhs ) { return (Time)@{ lhs.tn + rhs.tn }; }
    162162        Time ?+?( Duration lhs, Time rhs ) { return rhs + lhs; }
    163163        Time ?+=?( Time & lhs, Duration rhs ) { lhs = lhs + rhs; return lhs; }
    164164
    165         Duration ?-?( Time lhs, Time rhs ) { return (Duration)@{ lhs.tv - rhs.tv }; }
    166         Time ?-?( Time lhs, Duration rhs ) { return (Time)@{ lhs.tv - rhs.tv }; }
     165        Duration ?-?( Time lhs, Time rhs ) { return (Duration)@{ lhs.tn - rhs.tn }; }
     166        Time ?-?( Time lhs, Duration rhs ) { return (Time)@{ lhs.tn - rhs.tn }; }
    167167        Time ?-=?( Time & lhs, Duration rhs ) { lhs = lhs - rhs; return lhs; }
    168         bool ?==?( Time lhs, Time rhs ) { return lhs.tv == rhs.tv; }
    169         bool ?!=?( Time lhs, Time rhs ) { return lhs.tv != rhs.tv; }
    170         bool ?<?( Time lhs, Time rhs ) { return lhs.tv < rhs.tv; }
    171         bool ?<=?( Time lhs, Time rhs ) { return lhs.tv <= rhs.tv; }
    172         bool ?>?( Time lhs, Time rhs ) { return lhs.tv > rhs.tv; }
    173         bool ?>=?( Time lhs, Time rhs ) { return lhs.tv >= rhs.tv; }
     168        bool ?==?( Time lhs, Time rhs ) { return lhs.tn == rhs.tn; }
     169        bool ?!=?( Time lhs, Time rhs ) { return lhs.tn != rhs.tn; }
     170        bool ?<?( Time lhs, Time rhs ) { return lhs.tn < rhs.tn; }
     171        bool ?<=?( Time lhs, Time rhs ) { return lhs.tn <= rhs.tn; }
     172        bool ?>?( Time lhs, Time rhs ) { return lhs.tn > rhs.tn; }
     173        bool ?>=?( Time lhs, Time rhs ) { return lhs.tn >= rhs.tn; }
     174
     175        int64_t ?`ns( Time t ) { return t.tn; }
    174176} // distribution
    175177
     
    189191} // dmy
    190192
    191 size_t strftime( char * buf, size_t size, const char * fmt, Time time );
     193size_t strftime( char buf[], size_t size, const char fmt[], Time time );
    192194
    193195//------------------------- timeval (cont) -------------------------
    194196
    195197static inline void ?{}( timeval & t, Time time ) with( t, time ) {
    196         tv_sec = tv / TIMEGRAN;                                                         // seconds
    197         tv_usec = tv % TIMEGRAN / (TIMEGRAN / 1_000_000LL);     // microseconds
     198        tv_sec = tn / TIMEGRAN;                                                         // seconds
     199        tv_usec = tn % TIMEGRAN / (TIMEGRAN / 1_000_000LL);     // microseconds
    198200} // ?{}
    199201
     
    201203
    202204static inline void ?{}( timespec & t, Time time ) with( t, time ) {
    203         tv_sec = tv / TIMEGRAN;                                                         // seconds
    204         tv_nsec = tv % TIMEGRAN;                                                        // nanoseconds
     205        tv_sec = tn / TIMEGRAN;                                                         // seconds
     206        tv_nsec = tn % TIMEGRAN;                                                        // nanoseconds
    205207} // ?{}
    206208
  • libcfa/src/time_t.hfa

    r9fb8f01 r3d5701e  
    1010// Created On       : Tue Apr 10 14:42:03 2018
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Apr 13 07:51:47 2018
    13 // Update Count     : 6
     12// Last Modified On : Sun Jan  5 08:22:46 2020
     13// Update Count     : 7
    1414//
    1515
     
    2020
    2121struct Duration {                                                                               // private
    22         int64_t tv;                                                                                     // nanoseconds
     22        int64_t tn;                                                                                     // nanoseconds
    2323}; // Duration
    2424
    25 static inline void ?{}( Duration & dur ) with( dur ) { tv = 0; }
    26 static inline void ?{}( Duration & dur, __attribute__((unused)) zero_t ) with( dur ) { tv = 0; }
     25static inline void ?{}( Duration & dur ) with( dur ) { tn = 0; }
     26static inline void ?{}( Duration & dur, __attribute__((unused)) zero_t ) with( dur ) { tn = 0; }
    2727
    2828
     
    3030
    3131struct Time {                                                                                   // private
    32         uint64_t tv;                                                                            // nanoseconds since UNIX epoch
     32        uint64_t tn;                                                                            // nanoseconds since UNIX epoch
    3333}; // Time
    3434
    35 static inline void ?{}( Time & time ) with( time ) { tv = 0; }
    36 static inline void ?{}( Time & time, __attribute__((unused)) zero_t ) with( time ) { tv = 0; }
     35static inline void ?{}( Time & time ) with( time ) { tn = 0; }
     36static inline void ?{}( Time & time, __attribute__((unused)) zero_t ) with( time ) { tn = 0; }
    3737
    3838// Local Variables: //
Note: See TracChangeset for help on using the changeset viewer.