Changeset 04b73b6


Ignore:
Timestamp:
Jul 23, 2020, 3:37:05 PM (3 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
f4ec4a90
Parents:
f0c3120 (diff), e262b5e (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:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
4 added
27 edited
1 moved

Legend:

Unmodified
Added
Removed
  • benchmark/io/http/filecache.cfa

    rf0c3120 r04b73b6  
    5656}
    5757
     58static inline [unsigned size, char unit] human_size( size_t size ) {
     59        int idx = 0;
     60        static char units [] = { ' ', 'K', 'M', 'G', 'T' };
     61        while( size >= 1024 ) {
     62                idx++;
     63                size /= 1024;
     64                if(idx >= 5) {
     65                        abort("File too large to print\n");
     66                }
     67        }
     68
     69        return [size, units[idx]];
     70}
    5871
    5972struct {
     
    6982
    7083[int fd, size_t size] get_file( * const char file, size_t len ) {
    71         uint32_t idx = murmur3_32( (const uint8_t *)file, len, options.hash_seed ) % file_cache.size;
     84        uint32_t idx = murmur3_32( (const uint8_t *)file, len, options.file_cache.hash_seed ) % file_cache.size;
    7285
    7386        for(int i = 0;; i++) {
     
    8699
    87100int put_file( cache_line & entry ) {
    88         uint32_t idx = murmur3_32( (const uint8_t *)entry.file, strlen(entry.file), options.hash_seed ) % file_cache.size;
     101        uint32_t idx = murmur3_32( (const uint8_t *)entry.file, strlen(entry.file), options.file_cache.hash_seed ) % file_cache.size;
    89102
    90103        int i = 0;
     
    101114void fill_cache( const char * path ) {
    102115        int ret;
     116        ret = chdir(path);
     117        if(ret < 0) {
     118                abort( "chdir error: (%d) %s\n", (int)errno, strerror(errno) );
     119        }
     120
    103121        size_t fcount = 0;
    104122        size_t fsize = 16;
     
    118136                raw[idx].file = strdup(fpath+2);
    119137                raw[idx].size = sb->st_size;
    120                 raw[idx].fd = open( fpath, options.open_flags );
    121                 if(raw[idx].fd < 0) {
    122                         abort( "open file error: (%d) %s\n", (int)errno, strerror(errno) );
     138                if( !options.file_cache.list ) {
     139                        raw[idx].fd = open( fpath, options.file_cache.open_flags );
     140                        if(raw[idx].fd < 0) {
     141                                abort( "open file error: (%d) %s\n", (int)errno, strerror(errno) );
     142                        }
    123143                }
    124144                return 0;
    125145        }
    126146
    127         ret = ftw(path, walk, 10);
     147        ret = ftw(".", walk, 10);
    128148        if(ret < 0) {
    129149                abort( "ftw error: (%d) %s\n", (int)errno, strerror(errno) );
     
    135155
    136156        // Step 2 create the cache
    137         file_cache.size = options.file_cache_size > 0 ? options.file_cache_size : fsize;
     157        file_cache.size = options.file_cache.size > 0 ? options.file_cache.size : fsize;
    138158        if( file_cache.size < fcount ) {
    139159                abort("File Cache too small\n");
    140160        }
    141161
    142         file_cache.entries = anew(fsize);
     162        file_cache.entries = anew(file_cache.size);
    143163
    144164        // Step 3 fill the cache
    145165        int conflicts = 0;
    146166        for(i; fcount) {
    147                 printf("Added file %s\n", raw[i].file);
    148167                conflicts += put_file( raw[i] );
    149168        }
    150169        printf("Filled cache from path \"%s\" with %zu files\n", path, fcount);
    151170        if( conflicts > 0 ) {
    152                 printf("Found %d conflicts (seed: %u)\n", conflicts, options.hash_seed);
     171                printf("Found %d conflicts (seed: %u)\n", conflicts, options.file_cache.hash_seed);
    153172                #if defined(REJECT_CONFLICTS)
    154173                        abort("Conflicts found in the cache");
     
    156175        }
    157176
     177        if(options.file_cache.list) {
     178                printf("Listing files and exiting\n");
     179                for(i; fcount) {
     180                        int s; char u;
     181                        [s, u] = human_size(raw[i].size);
     182                        printf("%4d%c - %s\n", s, u, raw[i].file);
     183                        free(raw[i].file);
     184                }
     185                free(raw);
     186                adelete(file_cache.size, file_cache.entries);
     187                exit(0);
     188        }
     189
    158190        // Step 4 clean up
    159191        free( raw );
    160192}
     193
     194[int *, int] filefds(int extra) {
     195        if(!file_cache.entries) {
     196                abort("File cache not filled!\n");
     197        }
     198
     199        return [aalloc(extra), 0];
     200}
     201
    161202
    162203void close_cache() {
  • benchmark/io/http/filecache.hfa

    rf0c3120 r04b73b6  
    1111[int fd, size_t size] get_file( * const char file, size_t len );
    1212void fill_cache( const char * path );
     13[int *, int] filefds( int extra );
    1314void close_cache();
  • benchmark/io/http/main.cfa

    rf0c3120 r04b73b6  
    1717#include "filecache.hfa"
    1818#include "options.hfa"
    19 #include "parseargs.hfa"
    2019#include "worker.hfa"
    2120
     
    2322// Globals
    2423//=============================================================================================
    25 Options options @= {
    26         0,
    27         42u,
    28         0,
    29         false,
    30         false,
    31         0
    32 };
    33 
    3424channel & wait_connect;
    3525
     
    3929
    4030void ?{}( ServerProc & this ) {
    41         /* paranoid */ assert( options.the_cluster != 0p );
    42         (this.self){ "Benchmark Processor", *options.the_cluster };
     31        /* paranoid */ assert( options.clopts.instance != 0p );
     32        (this.self){ "Benchmark Processor", *options.clopts.instance };
    4333
    4434        #if !defined(__CFA_NO_STATISTICS__)
    45                 if( options.procstats ) {
    46                         print_stats_at_exit( this.self, options.the_cluster->print_stats );
     35                if( options.clopts.procstats ) {
     36                        print_stats_at_exit( this.self, options.clopts.instance->print_stats );
    4737                }
    48                 if( options.viewhalts ) {
     38                if( options.clopts.viewhalts ) {
    4939                        print_halts( this.self );
    5040                }
     
    5646//============================================================================================='
    5747int main( int argc, char * argv[] ) {
    58         int port      = 8080;
    59         int backlog   = 10;
    60         int nprocs    = 1;
    61         int nworkers  = 1;
    62         int cl_flags  = 0;
    63         int chan_size = 10;
    64         const char * path = ".";
    6548        //===================
    6649        // Parse args
    67         static cfa_option opt[] = {
    68                 {'p', "port", "Port the server will listen on", port},
    69                 {'c', "cpus", "Number of processors to use", nprocs},
    70                 {'t', "threads", "Number of worker threads to use", nworkers},
    71                 {'b', "accept-backlog", "Maximum number of pending accepts", backlog},
    72                 {'B', "channel-size", "Maximum number of accepted connection pending", chan_size}
    73         };
    74         int opt_cnt = sizeof(opt) / sizeof(cfa_option);
    75 
    76         char **left;
    77       parse_args( argc, argv, opt, opt_cnt, "[OPTIONS] [PATH]  -- cforall http server", left );
    78 
     50        const char * path = parse_options(argc, argv);
    7951
    8052        //===================
     
    8557        //===================
    8658        // Open Socket
    87         printf("Listening on port %d\n", port);
     59        printf("Listening on port %d\n", options.socket.port);
    8860        int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    8961        if(server_fd < 0) {
     
    9769        address.sin_family = AF_INET;
    9870        address.sin_addr.s_addr = htonl(INADDR_ANY);
    99         address.sin_port = htons( port );
     71        address.sin_port = htons( options.socket.port );
    10072
    10173        ret = bind( server_fd, (struct sockaddr *)&address, sizeof(address) );
     
    10476        }
    10577
    106         ret = listen( server_fd, backlog );
     78        ret = listen( server_fd, options.socket.backlog );
    10779        if(ret < 0) {
    10880                abort( "listen error: (%d) %s\n", (int)errno, strerror(errno) );
     
    11284        // Run Server Cluster
    11385        {
    114                 cluster cl = { "Server Cluster", cl_flags };
     86                cluster cl = { "Server Cluster", options.clopts.flags };
    11587                #if !defined(__CFA_NO_STATISTICS__)
    11688                        print_stats_at_exit( cl, CFA_STATS_READY_Q | CFA_STATS_IO );
    11789                #endif
    118                 options.the_cluster = &cl;
     90                options.clopts.instance = &cl;
    11991
    120                 channel chan = { chan_size };
     92                channel chan = { options.clopts.chan_size };
    12193                &wait_connect = &chan;
    12294
     95                int pipe_cnt = options.clopts.nworkers * 2;
     96                int pipe_off;
     97                int * fds;
     98                [fds, pipe_off] = filefds( pipe_cnt );
     99                for(i; 0 ~ pipe_cnt ~ 2) {
     100                        int ret = pipe(&fds[pipe_off + i]);
     101                        if( ret < 0 ) { abort( "pipe error: (%d) %s\n", (int)errno, strerror(errno) ); }
     102                }
     103
    123104                {
    124                         ServerProc procs[nprocs];
     105                        ServerProc procs[options.clopts.nprocs];
    125106                        {
    126                                 Worker workers[nworkers];
    127                                 printf("%d workers started on %d processors\n", nworkers, nprocs);
     107                                Worker workers[options.clopts.nworkers];
     108                                for(i; options.clopts.nworkers) {
     109                                        if( options.file_cache.fixed_fds ) {
     110                                                workers[i].pipe[0] = pipe_off + (i * 2) + 0;
     111                                                workers[i].pipe[1] = pipe_off + (i * 2) + 1;
     112                                        }
     113                                        else {
     114                                                workers[i].pipe[0] = fds[pipe_off + (i * 2) + 0];
     115                                                workers[i].pipe[1] = fds[pipe_off + (i * 2) + 1];
     116                                        }
     117                                        unpark( workers[i] __cfaabi_dbg_ctx2 );
     118                                }
     119                                printf("%d workers started on %d processors\n", options.clopts.nworkers, options.clopts.nprocs);
    128120                                {
    129121                                        Acceptor acceptor = { server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen, 0 };
     122
     123                                        char buffer[128];
     124                                        while(!feof(stdin)) {
     125                                                fgets(buffer, 128, stdin);
     126                                        }
     127
     128                                        printf("Shutting Down\n");
    130129                                }
    131                                 printf("Shutting Down\n");
     130                                printf("Acceptor Closed\n");
    132131
    133132                                // Clean-up the workers
    134                                 for(nworkers) {
     133                                for(options.clopts.nworkers) {
    135134                                        put( wait_connect, -1 );
    136135                                }
    137136                        }
     137                        printf("Workers Closed\n");
    138138                }
     139
     140                for(i; pipe_cnt) {
     141                        ret = close( fds[pipe_off + i] );
     142                        if(ret < 0) {
     143                                abort( "close pipe error: (%d) %s\n", (int)errno, strerror(errno) );
     144                        }
     145                }
     146                free(fds);
    139147        }
    140148
  • benchmark/io/http/options.hfa

    rf0c3120 r04b73b6  
    66
    77struct Options {
    8         int open_flags;
    9         uint32_t hash_seed;
    10       size_t file_cache_size;
    11         bool procstats;
    12         bool viewhalts;
    13         cluster * the_cluster;
     8        struct {
     9                int open_flags;
     10                uint32_t hash_seed;
     11                size_t size;
     12                bool list;
     13                bool fixed_fds;
     14        } file_cache;
     15
     16        struct {
     17                int port;
     18                int backlog;
     19                int buflen;
     20        } socket;
     21
     22        struct {
     23                int nprocs;
     24                int nworkers;
     25                int flags;
     26                int chan_size;
     27                bool procstats;
     28                bool viewhalts;
     29                cluster * instance;
     30        } clopts;
    1431};
    1532
    1633extern Options options;
     34
     35const char * parse_options( int argc, char * argv[] );
  • benchmark/io/http/parseargs.cfa

    rf0c3120 r04b73b6  
    33// #include <stdio.h>
    44// #include <stdlib.h>
     5#include <errno.h>
    56#include <string.h>
     7#include <unistd.h>
    68extern "C" {
    79        #include <getopt.h>
     10        #include <sys/ioctl.h>
    811
    912        struct FILE;
     
    1114        extern FILE * stdout;
    1215
     16        extern int fileno(FILE *stream);
     17
    1318        extern int fprintf ( FILE * stream, const char * format, ... );
    14         extern long long int strtoll (const char* str, char** endptr, int base);
     19
     20        extern          long long int strtoll (const char* str, char** endptr, int base);
     21        extern unsigned long long int strtoull(const char* str, char** endptr, int base);
     22}
     23
     24#include <common.hfa>
     25#include <limits.hfa>
     26
     27void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) {
     28        int hwidth = max - (11 + width);
     29        if(hwidth <= 0) hwidth = max;
     30
     31        fprintf(out, "  -%c, --%-*s   %.*s\n", sn, width, ln, hwidth, help);
     32        for() {
     33                help += min(strlen(help), hwidth);
     34                if('\0' == *help) break;
     35                fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help);
     36        }
    1537}
    1638
     
    2547        struct option optarr[opt_count + 2];
    2648        int width = 0;
     49        int max_width = 1_000_000;
    2750        {
    2851                int idx = 0;
     
    93116        }
    94117
    95         USAGE:
    96         fprintf(out, "%s\n", usage);
     118        USAGE:;
     119        int outfd = fileno(out);
     120        if(isatty(outfd)) {
     121                struct winsize size;
     122                int ret = ioctl(outfd, TIOCGWINSZ, &size);
     123                if(ret < 0) abort( "ioctl error: (%d) %s\n", (int)errno, strerror(errno) );
     124                max_width = size.ws_col;
     125        }
     126
     127        fprintf(out, "Usage:\n  %s %s\n", argv[0], usage);
    97128
    98129        for(i; opt_count) {
    99                 fprintf(out, "  -%c, --%-*s   %s\n", options[i].short_name, width, options[i].long_name, options[i].help);
     130                printopt(out, width, max_width, options[i].short_name, options[i].long_name, options[i].help);
    100131        }
    101132        fprintf(out, "  -%c, --%-*s   %s\n", 'h', width, "help", "print this help message");
     
    132163}
    133164
     165bool parse(const char * arg, unsigned & value) {
     166        char * end;
     167        unsigned long long int r = strtoull(arg, &end, 10);
     168        if(*end != '\0') return false;
     169        if(r > (unsigned)MAX) return false;
     170
     171        value = r;
     172        return true;
     173}
     174
     175bool parse(const char * arg, size_t & value) {
     176        char * end;
     177        unsigned long long int r = strtoull(arg, &end, 10);
     178        if(*end != '\0') return false;
     179        if(r > (size_t)MAX) return false;
     180
     181        value = r;
     182        return true;
     183}
     184
    134185bool parse(const char * arg, int & value) {
    135186        char * end;
  • benchmark/io/http/parseargs.hfa

    rf0c3120 r04b73b6  
    3838
    3939bool parse(const char *, const char * & );
     40bool parse(const char *, unsigned & );
     41bool parse(const char *, size_t & );
    4042bool parse(const char *, int & );
  • benchmark/io/http/protocol.cfa

    rf0c3120 r04b73b6  
    2525};
    2626
    27 _Static_assert( KNOWN_CODES == (sizeof(http_msgs) / sizeof(http_msgs[0])));
     27_Static_assert( KNOWN_CODES == (sizeof(http_msgs ) / sizeof(http_msgs [0])));
     28
     29const int http_codes[] = {
     30        200,
     31        400,
     32        404,
     33        413,
     34        414,
     35};
     36
     37_Static_assert( KNOWN_CODES == (sizeof(http_codes) / sizeof(http_codes[0])));
     38
     39int code_val(HttpCode code) {
     40        return http_codes[code];
     41}
    2842
    2943static inline int answer( int fd, const char * it, int len) {
     
    6175        for() {
    6276                int ret = cfa_read(fd, it, count);
     77                if(ret == 0 ) return [OK200, true, 0p, 0];
    6378                if(ret < 0 ) {
    64                         if( errno ) return [OK200, true, 0p, 0];
    6579                        if( errno == EAGAIN || errno == EWOULDBLOCK) continue READ;
    6680                        abort( "read error: (%d) %s\n", (int)errno, strerror(errno) );
  • benchmark/io/http/protocol.hfa

    rf0c3120 r04b73b6  
    1010};
    1111
     12int code_val(HttpCode code);
     13
    1214int answer_error( int fd, HttpCode code );
    1315int answer_header( int fd, size_t size );
  • benchmark/io/http/worker.cfa

    rf0c3120 r04b73b6  
    1212#include "filecache.hfa"
    1313
    14 extern "C" {
    15 // extern ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
    16 extern ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
    17 }
    18 
    19 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) {
    20         return splice(in_fd, offset, out_fd, 0p, count, 0);
    21 }
    22 
    23 
    2414//=============================================================================================
    2515// Worker Thread
    2616//=============================================================================================
    2717void ?{}( Worker & this ) {
    28         ((thread&)this){ "Server Worker Thread", *options.the_cluster };
    29         int ret = pipe(this.pipe);
    30         if( ret < 0 ) { abort( "pipe error: (%d) %s\n", (int)errno, strerror(errno) ); }
     18        ((thread&)this){ "Server Worker Thread", *options.clopts.instance };
     19        this.pipe[0] = -1;
     20        this.pipe[1] = -1;
    3121}
    3222
    3323void main( Worker & this ) {
     24        park( __cfaabi_dbg_ctx );
     25        /* paranoid */ assert( this.pipe[0] != -1 );
     26        /* paranoid */ assert( this.pipe[1] != -1 );
     27
    3428        CONNECTION:
    35         while( int fd = take(wait_connect); fd >= 0) {
    36             printf("New connection, waiting for requests\n");
     29        for() {
     30                int fd = take(wait_connect);
     31                if (fd < 0) break;
     32
     33                printf("New connection %d, waiting for requests\n", fd);
    3734                REQUEST:
    3835                for() {
     
    4340
    4441                        // Read the http request
    45                         size_t len = 1024;
     42                        size_t len = options.socket.buflen;
    4643                        char buffer[len];
    4744                        printf("Reading request\n");
     
    5653                        // If this wasn't a request retrun 400
    5754                        if( code != OK200 ) {
    58                                 printf("Invalid Request\n");
     55                                printf("Invalid Request : %d\n", code_val(code));
    5956                                answer_error(fd, code);
    6057                                continue REQUEST;
    6158                        }
    6259
    63                         printf("Request for file %.*s\n", name_size, file);
     60                        printf("Request for file %.*s\n", (int)name_size, file);
    6461
    6562                        // Get the fd from the file cache
     
    9087//=============================================================================================
    9188void ?{}( Acceptor & this, int sockfd, struct sockaddr * addr, socklen_t * addrlen, int flags ) {
    92         ((thread&)this){ "Acceptor Thread", *options.the_cluster };
     89        ((thread&)this){ "Acceptor Thread", *options.clopts.instance };
    9390        this.sockfd  = sockfd;
    9491        this.addr    = addr;
     
    105102                }
    106103
    107             printf("New connection accepted\n");
     104                printf("New connection accepted\n");
    108105                put( wait_connect, ret );
    109       }
     106        }
    110107}
  • libcfa/configure

    rf0c3120 r04b73b6  
    20542054
    20552055} # ac_fn_c_check_header_mongrel
     2056
     2057# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
     2058# ---------------------------------------------
     2059# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
     2060# accordingly.
     2061ac_fn_c_check_decl ()
     2062{
     2063  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
     2064  as_decl_name=`echo $2|sed 's/ *(.*//'`
     2065  as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
     2066  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
     2067$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
     2068if eval \${$3+:} false; then :
     2069  $as_echo_n "(cached) " >&6
     2070else
     2071  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
     2072/* end confdefs.h.  */
     2073$4
     2074int
     2075main ()
     2076{
     2077#ifndef $as_decl_name
     2078#ifdef __cplusplus
     2079  (void) $as_decl_use;
     2080#else
     2081  (void) $as_decl_name;
     2082#endif
     2083#endif
     2084
     2085  ;
     2086  return 0;
     2087}
     2088_ACEOF
     2089if ac_fn_c_try_compile "$LINENO"; then :
     2090  eval "$3=yes"
     2091else
     2092  eval "$3=no"
     2093fi
     2094rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     2095fi
     2096eval ac_res=\$$3
     2097               { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
     2098$as_echo "$ac_res" >&6; }
     2099  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
     2100
     2101} # ac_fn_c_check_decl
    20562102cat >config.log <<_ACEOF
    20572103This file contains any messages produced by compilers while
     
    1696217008
    1696317009
     17010
     17011
     17012#io_uring 5.4 and earlier uses defines
     17013#io_uring 5.5 uses enum values
     17014#io_uring 5.6 and later uses probes
     17015
    1696417016for ac_header in linux/io_uring.h
    1696517017do :
     
    1696917021#define HAVE_LINUX_IO_URING_H 1
    1697017022_ACEOF
     17023
     17024        $as_echo "#define CFA_HAVE_LINUX_IO_URING_H 1" >>confdefs.h
     17025
     17026        # AC_CHECK_HEADER([liburing.h], [
     17027        #       AC_CHECK_LIB([uring], [io_uring_get_probe])
     17028        # ])
     17029
     17030                ac_fn_c_check_decl "$LINENO" "IORING_OP_NOP" "ac_cv_have_decl_IORING_OP_NOP" "#include <linux/io_uring.h>
     17031"
     17032if test "x$ac_cv_have_decl_IORING_OP_NOP" = xyes; then :
     17033  $as_echo "#define CFA_HAVE_IORING_OP_NOP 1" >>confdefs.h
     17034
     17035fi
     17036
     17037
     17038                ac_fn_c_check_decl "$LINENO" "IORING_OP_READV" "ac_cv_have_decl_IORING_OP_READV" "#include <linux/io_uring.h>
     17039"
     17040if test "x$ac_cv_have_decl_IORING_OP_READV" = xyes; then :
     17041  $as_echo "#define CFA_HAVE_IORING_OP_READV 1" >>confdefs.h
     17042
     17043fi
     17044
     17045
     17046                ac_fn_c_check_decl "$LINENO" "IORING_OP_WRITEV" "ac_cv_have_decl_IORING_OP_WRITEV" "#include <linux/io_uring.h>
     17047"
     17048if test "x$ac_cv_have_decl_IORING_OP_WRITEV" = xyes; then :
     17049  $as_echo "#define CFA_HAVE_IORING_OP_WRITEV 1" >>confdefs.h
     17050
     17051fi
     17052
     17053
     17054                ac_fn_c_check_decl "$LINENO" "IORING_OP_FSYNC" "ac_cv_have_decl_IORING_OP_FSYNC" "#include <linux/io_uring.h>
     17055"
     17056if test "x$ac_cv_have_decl_IORING_OP_FSYNC" = xyes; then :
     17057  $as_echo "#define CFA_HAVE_IORING_OP_FSYNC 1" >>confdefs.h
     17058
     17059fi
     17060
     17061
     17062                ac_fn_c_check_decl "$LINENO" "IORING_OP_READ_FIXED" "ac_cv_have_decl_IORING_OP_READ_FIXED" "#include <linux/io_uring.h>
     17063"
     17064if test "x$ac_cv_have_decl_IORING_OP_READ_FIXED" = xyes; then :
     17065  $as_echo "#define CFA_HAVE_IORING_OP_READ_FIXED 1" >>confdefs.h
     17066
     17067fi
     17068
     17069
     17070                ac_fn_c_check_decl "$LINENO" "IORING_OP_WRITE_FIXED" "ac_cv_have_decl_IORING_OP_WRITE_FIXED" "#include <linux/io_uring.h>
     17071"
     17072if test "x$ac_cv_have_decl_IORING_OP_WRITE_FIXED" = xyes; then :
     17073  $as_echo "#define CFA_HAVE_IORING_OP_WRITE_FIXED 1" >>confdefs.h
     17074
     17075fi
     17076
     17077
     17078                ac_fn_c_check_decl "$LINENO" "IORING_OP_POLL_ADD" "ac_cv_have_decl_IORING_OP_POLL_ADD" "#include <linux/io_uring.h>
     17079"
     17080if test "x$ac_cv_have_decl_IORING_OP_POLL_ADD" = xyes; then :
     17081  $as_echo "#define CFA_HAVE_IORING_OP_POLL_ADD 1" >>confdefs.h
     17082
     17083fi
     17084
     17085
     17086                ac_fn_c_check_decl "$LINENO" "IORING_OP_POLL_REMOVE" "ac_cv_have_decl_IORING_OP_POLL_REMOVE" "#include <linux/io_uring.h>
     17087"
     17088if test "x$ac_cv_have_decl_IORING_OP_POLL_REMOVE" = xyes; then :
     17089  $as_echo "#define CFA_HAVE_IORING_OP_POLL_REMOVE 1" >>confdefs.h
     17090
     17091fi
     17092
     17093
     17094                ac_fn_c_check_decl "$LINENO" "IORING_OP_SYNC_FILE_RANGE" "ac_cv_have_decl_IORING_OP_SYNC_FILE_RANGE" "#include <linux/io_uring.h>
     17095"
     17096if test "x$ac_cv_have_decl_IORING_OP_SYNC_FILE_RANGE" = xyes; then :
     17097  $as_echo "#define CFA_HAVE_IORING_OP_SYNC_FILE_RANGE 1" >>confdefs.h
     17098
     17099fi
     17100
     17101
     17102                ac_fn_c_check_decl "$LINENO" "IORING_OP_SENDMSG" "ac_cv_have_decl_IORING_OP_SENDMSG" "#include <linux/io_uring.h>
     17103"
     17104if test "x$ac_cv_have_decl_IORING_OP_SENDMSG" = xyes; then :
     17105  $as_echo "#define CFA_HAVE_IORING_OP_SENDMSG 1" >>confdefs.h
     17106
     17107fi
     17108
     17109
     17110                ac_fn_c_check_decl "$LINENO" "IORING_OP_RECVMSG" "ac_cv_have_decl_IORING_OP_RECVMSG" "#include <linux/io_uring.h>
     17111"
     17112if test "x$ac_cv_have_decl_IORING_OP_RECVMSG" = xyes; then :
     17113  $as_echo "#define CFA_HAVE_IORING_OP_RECVMSG 1" >>confdefs.h
     17114
     17115fi
     17116
     17117
     17118                ac_fn_c_check_decl "$LINENO" "IORING_OP_TIMEOUT" "ac_cv_have_decl_IORING_OP_TIMEOUT" "#include <linux/io_uring.h>
     17119"
     17120if test "x$ac_cv_have_decl_IORING_OP_TIMEOUT" = xyes; then :
     17121  $as_echo "#define CFA_HAVE_IORING_OP_TIMEOUT 1" >>confdefs.h
     17122
     17123fi
     17124
     17125
     17126                ac_fn_c_check_decl "$LINENO" "IORING_OP_TIMEOUT_REMOVE" "ac_cv_have_decl_IORING_OP_TIMEOUT_REMOVE" "#include <linux/io_uring.h>
     17127"
     17128if test "x$ac_cv_have_decl_IORING_OP_TIMEOUT_REMOVE" = xyes; then :
     17129  $as_echo "#define CFA_HAVE_IORING_OP_TIMEOUT_REMOVE 1" >>confdefs.h
     17130
     17131fi
     17132
     17133
     17134                ac_fn_c_check_decl "$LINENO" "IORING_OP_ACCEPT" "ac_cv_have_decl_IORING_OP_ACCEPT" "#include <linux/io_uring.h>
     17135"
     17136if test "x$ac_cv_have_decl_IORING_OP_ACCEPT" = xyes; then :
     17137  $as_echo "#define CFA_HAVE_IORING_OP_ACCEPT 1" >>confdefs.h
     17138
     17139fi
     17140
     17141
     17142                ac_fn_c_check_decl "$LINENO" "IORING_OP_ASYNC_CANCEL" "ac_cv_have_decl_IORING_OP_ASYNC_CANCEL" "#include <linux/io_uring.h>
     17143"
     17144if test "x$ac_cv_have_decl_IORING_OP_ASYNC_CANCEL" = xyes; then :
     17145  $as_echo "#define CFA_HAVE_IORING_OP_ASYNC_CANCEL 1" >>confdefs.h
     17146
     17147fi
     17148
     17149
     17150                ac_fn_c_check_decl "$LINENO" "IORING_OP_LINK_TIMEOUT" "ac_cv_have_decl_IORING_OP_LINK_TIMEOUT" "#include <linux/io_uring.h>
     17151"
     17152if test "x$ac_cv_have_decl_IORING_OP_LINK_TIMEOUT" = xyes; then :
     17153  $as_echo "#define CFA_HAVE_IORING_OP_LINK_TIMEOUT 1" >>confdefs.h
     17154
     17155fi
     17156
     17157
     17158                ac_fn_c_check_decl "$LINENO" "IORING_OP_CONNECT" "ac_cv_have_decl_IORING_OP_CONNECT" "#include <linux/io_uring.h>
     17159"
     17160if test "x$ac_cv_have_decl_IORING_OP_CONNECT" = xyes; then :
     17161  $as_echo "#define CFA_HAVE_IORING_OP_CONNECT 1" >>confdefs.h
     17162
     17163fi
     17164
     17165
     17166                ac_fn_c_check_decl "$LINENO" "IORING_OP_FALLOCATE" "ac_cv_have_decl_IORING_OP_FALLOCATE" "#include <linux/io_uring.h>
     17167"
     17168if test "x$ac_cv_have_decl_IORING_OP_FALLOCATE" = xyes; then :
     17169  $as_echo "#define CFA_HAVE_IORING_OP_FALLOCATE 1" >>confdefs.h
     17170
     17171fi
     17172
     17173
     17174                ac_fn_c_check_decl "$LINENO" "IORING_OP_OPENAT" "ac_cv_have_decl_IORING_OP_OPENAT" "#include <linux/io_uring.h>
     17175"
     17176if test "x$ac_cv_have_decl_IORING_OP_OPENAT" = xyes; then :
     17177  $as_echo "#define CFA_HAVE_IORING_OP_OPENAT 1" >>confdefs.h
     17178
     17179fi
     17180
     17181
     17182                ac_fn_c_check_decl "$LINENO" "IORING_OP_CLOSE" "ac_cv_have_decl_IORING_OP_CLOSE" "#include <linux/io_uring.h>
     17183"
     17184if test "x$ac_cv_have_decl_IORING_OP_CLOSE" = xyes; then :
     17185  $as_echo "#define CFA_HAVE_IORING_OP_CLOSE 1" >>confdefs.h
     17186
     17187fi
     17188
     17189
     17190                ac_fn_c_check_decl "$LINENO" "IORING_OP_FILES_UPDATE" "ac_cv_have_decl_IORING_OP_FILES_UPDATE" "#include <linux/io_uring.h>
     17191"
     17192if test "x$ac_cv_have_decl_IORING_OP_FILES_UPDATE" = xyes; then :
     17193  $as_echo "#define CFA_HAVE_IORING_OP_FILES_UPDATE 1" >>confdefs.h
     17194
     17195fi
     17196
     17197
     17198                ac_fn_c_check_decl "$LINENO" "IORING_OP_STATX" "ac_cv_have_decl_IORING_OP_STATX" "#include <linux/io_uring.h>
     17199"
     17200if test "x$ac_cv_have_decl_IORING_OP_STATX" = xyes; then :
     17201  $as_echo "#define CFA_HAVE_IORING_OP_STATX 1" >>confdefs.h
     17202
     17203fi
     17204
     17205
     17206                ac_fn_c_check_decl "$LINENO" "IORING_OP_READ" "ac_cv_have_decl_IORING_OP_READ" "#include <linux/io_uring.h>
     17207"
     17208if test "x$ac_cv_have_decl_IORING_OP_READ" = xyes; then :
     17209  $as_echo "#define CFA_HAVE_IORING_OP_READ 1" >>confdefs.h
     17210
     17211fi
     17212
     17213
     17214                ac_fn_c_check_decl "$LINENO" "IORING_OP_WRITE" "ac_cv_have_decl_IORING_OP_WRITE" "#include <linux/io_uring.h>
     17215"
     17216if test "x$ac_cv_have_decl_IORING_OP_WRITE" = xyes; then :
     17217  $as_echo "#define CFA_HAVE_IORING_OP_WRITE 1" >>confdefs.h
     17218
     17219fi
     17220
     17221
     17222                ac_fn_c_check_decl "$LINENO" "IORING_OP_FADVISE" "ac_cv_have_decl_IORING_OP_FADVISE" "#include <linux/io_uring.h>
     17223"
     17224if test "x$ac_cv_have_decl_IORING_OP_FADVISE" = xyes; then :
     17225  $as_echo "#define CFA_HAVE_IORING_OP_FADVISE 1" >>confdefs.h
     17226
     17227fi
     17228
     17229
     17230                ac_fn_c_check_decl "$LINENO" "IORING_OP_MADVISE" "ac_cv_have_decl_IORING_OP_MADVISE" "#include <linux/io_uring.h>
     17231"
     17232if test "x$ac_cv_have_decl_IORING_OP_MADVISE" = xyes; then :
     17233  $as_echo "#define CFA_HAVE_IORING_OP_MADVISE 1" >>confdefs.h
     17234
     17235fi
     17236
     17237
     17238                ac_fn_c_check_decl "$LINENO" "IORING_OP_SEND" "ac_cv_have_decl_IORING_OP_SEND" "#include <linux/io_uring.h>
     17239"
     17240if test "x$ac_cv_have_decl_IORING_OP_SEND" = xyes; then :
     17241  $as_echo "#define CFA_HAVE_IORING_OP_SEND 1" >>confdefs.h
     17242
     17243fi
     17244
     17245
     17246                ac_fn_c_check_decl "$LINENO" "IORING_OP_RECV" "ac_cv_have_decl_IORING_OP_RECV" "#include <linux/io_uring.h>
     17247"
     17248if test "x$ac_cv_have_decl_IORING_OP_RECV" = xyes; then :
     17249  $as_echo "#define CFA_HAVE_IORING_OP_RECV 1" >>confdefs.h
     17250
     17251fi
     17252
     17253
     17254                ac_fn_c_check_decl "$LINENO" "IORING_OP_OPENAT2" "ac_cv_have_decl_IORING_OP_OPENAT2" "#include <linux/io_uring.h>
     17255"
     17256if test "x$ac_cv_have_decl_IORING_OP_OPENAT2" = xyes; then :
     17257  $as_echo "#define CFA_HAVE_IORING_OP_OPENAT2 1" >>confdefs.h
     17258
     17259fi
     17260
     17261
     17262                ac_fn_c_check_decl "$LINENO" "IORING_OP_EPOLL_CTL" "ac_cv_have_decl_IORING_OP_EPOLL_CTL" "#include <linux/io_uring.h>
     17263"
     17264if test "x$ac_cv_have_decl_IORING_OP_EPOLL_CTL" = xyes; then :
     17265  $as_echo "#define CFA_HAVE_IORING_OP_EPOLL_CTL 1" >>confdefs.h
     17266
     17267fi
     17268
     17269
     17270                ac_fn_c_check_decl "$LINENO" "IORING_OP_SPLICE" "ac_cv_have_decl_IORING_OP_SPLICE" "#include <linux/io_uring.h>
     17271"
     17272if test "x$ac_cv_have_decl_IORING_OP_SPLICE" = xyes; then :
     17273  $as_echo "#define CFA_HAVE_IORING_OP_SPLICE 1" >>confdefs.h
     17274
     17275fi
     17276
     17277
     17278                ac_fn_c_check_decl "$LINENO" "IORING_OP_PROVIDE_BUFFERS" "ac_cv_have_decl_IORING_OP_PROVIDE_BUFFERS" "#include <linux/io_uring.h>
     17279"
     17280if test "x$ac_cv_have_decl_IORING_OP_PROVIDE_BUFFERS" = xyes; then :
     17281  $as_echo "#define CFA_HAVE_IORING_OP_PROVIDE_BUFFERS 1" >>confdefs.h
     17282
     17283fi
     17284
     17285
     17286                ac_fn_c_check_decl "$LINENO" "IORING_OP_REMOVE_BUFFER" "ac_cv_have_decl_IORING_OP_REMOVE_BUFFER" "#include <linux/io_uring.h>
     17287"
     17288if test "x$ac_cv_have_decl_IORING_OP_REMOVE_BUFFER" = xyes; then :
     17289  $as_echo "#define CFA_HAVE_IORING_OP_REMOVE_BUFFER 1" >>confdefs.h
     17290
     17291fi
     17292
     17293
    1697117294
    1697217295fi
  • libcfa/configure.ac

    rf0c3120 r04b73b6  
    123123AC_PROG_MAKE_SET
    124124
    125 AC_CHECK_HEADERS([linux/io_uring.h])
     125
     126
     127#io_uring 5.4 and earlier uses defines
     128#io_uring 5.5 uses enum values
     129#io_uring 5.6 and later uses probes
     130
     131AC_CHECK_HEADERS([linux/io_uring.h], [
     132        AC_DEFINE(CFA_HAVE_LINUX_IO_URING_H)
     133        # AC_CHECK_HEADER([liburing.h], [
     134        #       AC_CHECK_LIB([uring], [io_uring_get_probe])
     135        # ])
     136        m4_foreach([op], [IORING_OP_NOP,IORING_OP_READV,IORING_OP_WRITEV,IORING_OP_FSYNC,IORING_OP_READ_FIXED,IORING_OP_WRITE_FIXED,IORING_OP_POLL_ADD,IORING_OP_POLL_REMOVE,IORING_OP_SYNC_FILE_RANGE,IORING_OP_SENDMSG,IORING_OP_RECVMSG,IORING_OP_TIMEOUT,IORING_OP_TIMEOUT_REMOVE,IORING_OP_ACCEPT,IORING_OP_ASYNC_CANCEL,IORING_OP_LINK_TIMEOUT,IORING_OP_CONNECT,IORING_OP_FALLOCATE,IORING_OP_OPENAT,IORING_OP_CLOSE,IORING_OP_FILES_UPDATE,IORING_OP_STATX,IORING_OP_READ,IORING_OP_WRITE,IORING_OP_FADVISE,IORING_OP_MADVISE,IORING_OP_SEND,IORING_OP_RECV,IORING_OP_OPENAT2,IORING_OP_EPOLL_CTL,IORING_OP_SPLICE,IORING_OP_PROVIDE_BUFFERS,IORING_OP_REMOVE_BUFFER], [
     137                AC_CHECK_DECL(op, [AC_DEFINE([CFA_HAVE_]op)], [], [[#include <linux/io_uring.h>]])
     138        ])
     139])
    126140AC_CHECK_FUNCS([preadv2 pwritev2])
    127141
  • libcfa/prelude/defines.hfa.in

    rf0c3120 r04b73b6  
    1414//
    1515
    16 #undef HAVE_LINUX_IO_URING_H
     16#undef CFA_HAVE_LINUX_IO_URING_H
     17
     18#undef CFA_HAVE_IORING_OP_NOP
     19#undef CFA_HAVE_IORING_OP_READV
     20#undef CFA_HAVE_IORING_OP_WRITEV
     21#undef CFA_HAVE_IORING_OP_FSYNC
     22#undef CFA_HAVE_IORING_OP_READ_FIXED
     23#undef CFA_HAVE_IORING_OP_WRITE_FIXED
     24#undef CFA_HAVE_IORING_OP_POLL_ADD
     25#undef CFA_HAVE_IORING_OP_POLL_REMOVE
     26#undef CFA_HAVE_IORING_OP_SYNC_FILE_RANGE
     27#undef CFA_HAVE_IORING_OP_SENDMSG
     28#undef CFA_HAVE_IORING_OP_RECVMSG
     29#undef CFA_HAVE_IORING_OP_TIMEOUT
     30#undef CFA_HAVE_IORING_OP_TIMEOUT_REMOVE
     31#undef CFA_HAVE_IORING_OP_ACCEPT
     32#undef CFA_HAVE_IORING_OP_ASYNC_CANCEL
     33#undef CFA_HAVE_IORING_OP_LINK_TIMEOUT
     34#undef CFA_HAVE_IORING_OP_CONNECT
     35#undef CFA_HAVE_IORING_OP_FALLOCATE
     36#undef CFA_HAVE_IORING_OP_OPENAT
     37#undef CFA_HAVE_IORING_OP_CLOSE
     38#undef CFA_HAVE_IORING_OP_FILES_UPDATE
     39#undef CFA_HAVE_IORING_OP_STATX
     40#undef CFA_HAVE_IORING_OP_READ
     41#undef CFA_HAVE_IORING_OP_WRITE
     42#undef CFA_HAVE_IORING_OP_FADVISE
     43#undef CFA_HAVE_IORING_OP_MADVISE
     44#undef CFA_HAVE_IORING_OP_SEND
     45#undef CFA_HAVE_IORING_OP_RECV
     46#undef CFA_HAVE_IORING_OP_OPENAT2
     47#undef CFA_HAVE_IORING_OP_EPOLL_CTL
     48#undef CFA_HAVE_IORING_OP_SPLICE
     49#undef CFA_HAVE_IORING_OP_PROVIDE_BUFFERS
     50#undef CFA_HAVE_IORING_OP_REMOVE_BUFFER
    1751
    1852#undef HAVE_PREADV2
  • libcfa/src/concurrency/io.cfa

    rf0c3120 r04b73b6  
    1616#if defined(__CFA_DEBUG__)
    1717        // #define __CFA_DEBUG_PRINT_IO__
    18         #define __CFA_DEBUG_PRINT_IO_CORE__
     18        // #define __CFA_DEBUG_PRINT_IO_CORE__
    1919#endif
    2020
     
    2222#include "bitmanip.hfa"
    2323
    24 #if !defined(HAVE_LINUX_IO_URING_H)
     24#if !defined(CFA_HAVE_LINUX_IO_URING_H)
    2525        void __kernel_io_startup( cluster &, unsigned, bool ) {
    2626                // Nothing to do without io_uring
     
    490490        static uint32_t __release_consumed_submission( struct __io_data & ring );
    491491
     492        static inline void process(struct io_uring_cqe & cqe, struct __processor_id_t * id ) {
     493                struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data;
     494                __cfadbg_print_safe( io, "Kernel I/O : Syscall completed : cqe %p, result %d for %p\n", data, cqe.res, data->thrd );
     495
     496                data->result = cqe.res;
     497                if(!id) { unpark(     data->thrd __cfaabi_dbg_ctx2 ); }
     498                else  { __unpark( id, data->thrd __cfaabi_dbg_ctx2 ); }
     499        }
     500
    492501        // Process a single completion message from the io_uring
    493502        // This is NOT thread-safe
     
    538547                        /* paranoid */ verify(&cqe);
    539548
    540                         struct __io_user_data_t * data = (struct __io_user_data_t *)(uintptr_t)cqe.user_data;
    541                         __cfadbg_print_safe( io, "Kernel I/O : Performed reading io cqe %p, result %d for %p\n", data, cqe.res, data->thrd );
    542 
    543                         data->result = cqe.res;
    544                         if(!mask) { unpark( data->thrd __cfaabi_dbg_ctx2 ); }
    545                         else      { __unpark( &ring.poller.slow.id, data->thrd __cfaabi_dbg_ctx2 ); }
     549                        process( cqe, !mask ? (struct __processor_id_t *)0p : &ring.poller.slow.id );
    546550                }
    547551
  • libcfa/src/concurrency/iocall.cfa

    rf0c3120 r04b73b6  
    2020//=============================================================================================
    2121
    22 #if defined(HAVE_LINUX_IO_URING_H)
     22#if defined(CFA_HAVE_LINUX_IO_URING_H)
    2323        #include <stdint.h>
    2424        #include <linux/io_uring.h>
     
    122122#if defined(HAVE_PREADV2)
    123123        ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {
    124                 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READV)
     124                #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_READV)
    125125                        return preadv2(fd, iov, iovcnt, offset, flags);
    126126                #else
     
    134134
    135135        ssize_t cfa_preadv2_fixed(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {
    136                 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READV)
     136                #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_READV)
    137137                        return preadv2(fd, iov, iovcnt, offset, flags);
    138138                #else
     
    149149#if defined(HAVE_PWRITEV2)
    150150        ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {
    151                 #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITEV)
     151                #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_WRITEV)
    152152                        return pwritev2(fd, iov, iovcnt, offset, flags);
    153153                #else
     
    162162
    163163int cfa_fsync(int fd) {
    164         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FSYNC)
     164        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_FSYNC)
    165165                return fsync(fd);
    166166        #else
     
    174174
    175175int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags) {
    176         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SYNC_FILE_RANGE)
     176        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SYNC_FILE_RANGE)
    177177                return sync_file_range(fd, offset, nbytes, flags);
    178178        #else
     
    190190
    191191ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags) {
    192         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SENDMSG)
     192        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SENDMSG)
    193193                return sendmsg(sockfd, msg, flags);
    194194        #else
     
    203203
    204204ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags) {
    205         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECVMSG)
     205        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_RECVMSG)
    206206                return recvmsg(sockfd, msg, flags);
    207207        #else
     
    216216
    217217ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags) {
    218         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SEND)
     218        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SEND)
    219219                return send( sockfd, buf, len, flags );
    220220        #else
     
    231231
    232232ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags) {
    233         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECV)
     233        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_RECV)
    234234                return recv( sockfd, buf, len, flags );
    235235        #else
     
    246246
    247247int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
    248         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_ACCEPT)
     248        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_ACCEPT)
    249249                return accept4( sockfd, addr, addrlen, flags );
    250250        #else
     
    261261
    262262int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
    263         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CONNECT)
     263        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_CONNECT)
    264264                return connect( sockfd, addr, addrlen );
    265265        #else
     
    275275
    276276int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len) {
    277         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FALLOCATE)
     277        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_FALLOCATE)
    278278                return fallocate( fd, mode, offset, len );
    279279        #else
     
    290290
    291291int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
    292         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FADVISE)
     292        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_FADVISE)
    293293                return posix_fadvise( fd, offset, len, advice );
    294294        #else
     
    305305
    306306int cfa_madvise(void *addr, size_t length, int advice) {
    307         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_MADVISE)
     307        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_MADVISE)
    308308                return madvise( addr, length, advice );
    309309        #else
     
    320320
    321321int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode) {
    322         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_OPENAT)
     322        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_OPENAT)
    323323                return openat( dirfd, pathname, flags, mode );
    324324        #else
     
    335335
    336336int cfa_close(int fd) {
    337         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CLOSE)
     337        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_CLOSE)
    338338                return close( fd );
    339339        #else
     
    349349struct statx;
    350350int cfa_statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf) {
    351         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_STATX)
     351        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_STATX)
    352352                #if defined(__NR_statx)
    353353                        return syscall( __NR_statx, dirfd, pathname, flags, mask, statxbuf );
     
    367367
    368368ssize_t cfa_read(int fd, void *buf, size_t count) {
    369         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READ)
     369        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_READ)
    370370                return read( fd, buf, count );
    371371        #else
     
    379379
    380380ssize_t cfa_write(int fd, void *buf, size_t count) {
    381         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITE)
     381        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_WRITE)
    382382                return read( fd, buf, count );
    383383        #else
     
    391391
    392392ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) {
    393         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SPLICE)
     393        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SPLICE)
    394394                return splice( fd_in, off_in, fd_out, off_out, len, flags );
    395395        #else
     
    405405}
    406406
     407ssize_t cfa_splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags, int in_flags, int out_flags) {
     408        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SPLICE)
     409                return splice( fd_in, off_in, fd_out, off_out, len, flags );
     410        #else
     411                __submit_prelude
     412
     413                (*sqe){ IORING_OP_SPLICE, fd_out, 0p, len, off_out };
     414                sqe->splice_fd_in  = fd_in;
     415                sqe->splice_off_in = off_in;
     416                sqe->splice_flags  = flags | out_flags;
     417                sqe->flags = in_flags;
     418
     419                __submit_wait
     420        #endif
     421}
     422
    407423ssize_t cfa_tee(int fd_in, int fd_out, size_t len, unsigned int flags) {
    408         #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_TEE)
     424        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_TEE)
    409425                return tee( fd_in, fd_out, len, flags );
    410426        #else
     
    429445
    430446bool has_user_level_blocking( fptr_t func ) {
    431         #if defined(HAVE_LINUX_IO_URING_H)
     447        #if defined(CFA_HAVE_LINUX_IO_URING_H)
    432448                #if defined(HAVE_PREADV2)
    433449                        if( /*func == (fptr_t)preadv2 || */
    434450                                func == (fptr_t)cfa_preadv2 )
    435                                 #define _CFA_IO_FEATURE_IORING_OP_READV ,
    436                                 return IS_DEFINED(IORING_OP_READV);
     451                                #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_READV ,
     452                                return IS_DEFINED(CFA_HAVE_IORING_OP_READV);
    437453                #endif
    438454
     
    440456                        if( /*func == (fptr_t)pwritev2 || */
    441457                                func == (fptr_t)cfa_pwritev2 )
    442                                 #define _CFA_IO_FEATURE_IORING_OP_WRITEV ,
    443                                 return IS_DEFINED(IORING_OP_WRITEV);
     458                                #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_WRITEV ,
     459                                return IS_DEFINED(CFA_HAVE_IORING_OP_WRITEV);
    444460                #endif
    445461
    446462                if( /*func == (fptr_t)fsync || */
    447463                        func == (fptr_t)cfa_fsync )
    448                         #define _CFA_IO_FEATURE_IORING_OP_FSYNC ,
    449                         return IS_DEFINED(IORING_OP_FSYNC);
     464                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_FSYNC ,
     465                        return IS_DEFINED(CFA_HAVE_IORING_OP_FSYNC);
    450466
    451467                if( /*func == (fptr_t)ync_file_range || */
    452468                        func == (fptr_t)cfa_sync_file_range )
    453                         #define _CFA_IO_FEATURE_IORING_OP_SYNC_FILE_RANGE ,
    454                         return IS_DEFINED(IORING_OP_SYNC_FILE_RANGE);
     469                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_SYNC_FILE_RANGE ,
     470                        return IS_DEFINED(CFA_HAVE_IORING_OP_SYNC_FILE_RANGE);
    455471
    456472                if( /*func == (fptr_t)sendmsg || */
    457473                        func == (fptr_t)cfa_sendmsg )
    458                         #define _CFA_IO_FEATURE_IORING_OP_SENDMSG ,
    459                         return IS_DEFINED(IORING_OP_SENDMSG);
     474                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_SENDMSG ,
     475                        return IS_DEFINED(CFA_HAVE_IORING_OP_SENDMSG);
    460476
    461477                if( /*func == (fptr_t)recvmsg || */
    462478                        func == (fptr_t)cfa_recvmsg )
    463                         #define _CFA_IO_FEATURE_IORING_OP_RECVMSG ,
    464                         return IS_DEFINED(IORING_OP_RECVMSG);
     479                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_RECVMSG ,
     480                        return IS_DEFINED(CFA_HAVE_IORING_OP_RECVMSG);
    465481
    466482                if( /*func == (fptr_t)send || */
    467483                        func == (fptr_t)cfa_send )
    468                         #define _CFA_IO_FEATURE_IORING_OP_SEND ,
    469                         return IS_DEFINED(IORING_OP_SEND);
     484                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_SEND ,
     485                        return IS_DEFINED(CFA_HAVE_IORING_OP_SEND);
    470486
    471487                if( /*func == (fptr_t)recv || */
    472488                        func == (fptr_t)cfa_recv )
    473                         #define _CFA_IO_FEATURE_IORING_OP_RECV ,
    474                         return IS_DEFINED(IORING_OP_RECV);
     489                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_RECV ,
     490                        return IS_DEFINED(CFA_HAVE_IORING_OP_RECV);
    475491
    476492                if( /*func == (fptr_t)accept4 || */
    477493                        func == (fptr_t)cfa_accept4 )
    478                         #define _CFA_IO_FEATURE_IORING_OP_ACCEPT ,
    479                         return IS_DEFINED(IORING_OP_ACCEPT);
     494                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_ACCEPT ,
     495                        return IS_DEFINED(CFA_HAVE_IORING_OP_ACCEPT);
    480496
    481497                if( /*func == (fptr_t)connect || */
    482498                        func == (fptr_t)cfa_connect )
    483                         #define _CFA_IO_FEATURE_IORING_OP_CONNECT ,
    484                         return IS_DEFINED(IORING_OP_CONNECT);
     499                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_CONNECT ,
     500                        return IS_DEFINED(CFA_HAVE_IORING_OP_CONNECT);
    485501
    486502                if( /*func == (fptr_t)fallocate || */
    487503                        func == (fptr_t)cfa_fallocate )
    488                         #define _CFA_IO_FEATURE_IORING_OP_FALLOCATE ,
    489                         return IS_DEFINED(IORING_OP_FALLOCATE);
     504                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_FALLOCATE ,
     505                        return IS_DEFINED(CFA_HAVE_IORING_OP_FALLOCATE);
    490506
    491507                if( /*func == (fptr_t)posix_fadvise || */
    492508                        func == (fptr_t)cfa_fadvise )
    493                         #define _CFA_IO_FEATURE_IORING_OP_FADVISE ,
    494                         return IS_DEFINED(IORING_OP_FADVISE);
     509                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_FADVISE ,
     510                        return IS_DEFINED(CFA_HAVE_IORING_OP_FADVISE);
    495511
    496512                if( /*func == (fptr_t)madvise || */
    497513                        func == (fptr_t)cfa_madvise )
    498                         #define _CFA_IO_FEATURE_IORING_OP_MADVISE ,
    499                         return IS_DEFINED(IORING_OP_MADVISE);
     514                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_MADVISE ,
     515                        return IS_DEFINED(CFA_HAVE_IORING_OP_MADVISE);
    500516
    501517                if( /*func == (fptr_t)openat || */
    502518                        func == (fptr_t)cfa_openat )
    503                         #define _CFA_IO_FEATURE_IORING_OP_OPENAT ,
    504                         return IS_DEFINED(IORING_OP_OPENAT);
     519                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_OPENAT ,
     520                        return IS_DEFINED(CFA_HAVE_IORING_OP_OPENAT);
    505521
    506522                if( /*func == (fptr_t)close || */
    507523                        func == (fptr_t)cfa_close )
    508                         #define _CFA_IO_FEATURE_IORING_OP_CLOSE ,
    509                         return IS_DEFINED(IORING_OP_CLOSE);
     524                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_CLOSE ,
     525                        return IS_DEFINED(CFA_HAVE_IORING_OP_CLOSE);
    510526
    511527                if( /*func == (fptr_t)read || */
    512528                        func == (fptr_t)cfa_read )
    513                         #define _CFA_IO_FEATURE_IORING_OP_READ ,
    514                         return IS_DEFINED(IORING_OP_READ);
     529                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_READ ,
     530                        return IS_DEFINED(CFA_HAVE_IORING_OP_READ);
    515531
    516532                if( /*func == (fptr_t)write || */
    517533                        func == (fptr_t)cfa_write )
    518                         #define _CFA_IO_FEATURE_IORING_OP_WRITE ,
    519                         return IS_DEFINED(IORING_OP_WRITE);
     534                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_WRITE ,
     535                        return IS_DEFINED(CFA_HAVE_IORING_OP_WRITE);
    520536
    521537                if( /*func == (fptr_t)splice || */
    522                         func == (fptr_t)cfa_splice )
    523                         #define _CFA_IO_FEATURE_IORING_OP_SPLICE ,
    524                         return IS_DEFINED(IORING_OP_SPLICE);
     538                        func == (fptr_t)(ssize_t (*)(int, loff_t *, int, loff_t *, size_t, unsigned int))cfa_splice,
     539                        func == (fptr_t)(ssize_t (*)(int, loff_t *, int, loff_t *, size_t, unsigned int, int, int))cfa_splice )
     540                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_SPLICE ,
     541                        return IS_DEFINED(CFA_HAVE_IORING_OP_SPLICE);
    525542
    526543                if( /*func == (fptr_t)tee || */
    527544                        func == (fptr_t)cfa_tee )
    528                         #define _CFA_IO_FEATURE_IORING_OP_TEE ,
    529                         return IS_DEFINED(IORING_OP_TEE);
     545                        #define _CFA_IO_FEATURE_CFA_HAVE_IORING_OP_TEE ,
     546                        return IS_DEFINED(CFA_HAVE_IORING_OP_TEE);
    530547        #endif
    531548
  • libcfa/src/concurrency/kernel.cfa

    rf0c3120 r04b73b6  
    228228static void * __invoke_processor(void * arg);
    229229
    230 void ?{}(processor & this, const char name[], cluster & _cltr) with( this ) {
     230static init(processor & this, const char name[], cluster & _cltr) with( this ) {
    231231        this.name = name;
    232232        this.cltr = &_cltr;
    233233        id = -1u;
    234         terminated{ 0 };
    235234        destroyer = 0p;
    236235        do_terminate = false;
    237236        preemption_alarm = 0p;
    238237        pending_preemption = false;
    239         runner.proc = &this;
    240238
    241239        #if !defined(__CFA_NO_STATISTICS__)
     
    244242        #endif
    245243
    246         idle{};
     244        __atomic_fetch_add( &cltr->nprocessors, 1u, __ATOMIC_SEQ_CST );
     245
     246        id = doregister((__processor_id_t*)&this);
     247
     248        // Lock the RWlock so no-one pushes/pops while we are changing the queue
     249        uint_fast32_t last_size = ready_mutate_lock();
     250
     251                // Adjust the ready queue size
     252                ready_queue_grow( cltr );
     253
     254        // Unlock the RWlock
     255        ready_mutate_unlock( last_size );
     256
     257        __cfadbg_print_safe(runtime_core, "Kernel : core %p created\n", &this);
     258}
     259
     260// Not a ctor, it just preps the destruction but should not destroy members
     261void deinit(processor & this) {
     262        // Lock the RWlock so no-one pushes/pops while we are changing the queue
     263        uint_fast32_t last_size = ready_mutate_lock();
     264
     265                // Adjust the ready queue size
     266                ready_queue_shrink( this.cltr );
     267
     268                // Make sure we aren't on the idle queue
     269                unsafe_remove( this.cltr->idles, &this );
     270
     271        // Unlock the RWlock
     272        ready_mutate_unlock( last_size );
     273
     274        // Finally we don't need the read_lock any more
     275        unregister((__processor_id_t*)&this);
     276}
     277
     278void ?{}(processor & this, const char name[], cluster & _cltr) {
     279        ( this.idle ){};
     280        ( this.terminated ){ 0 };
     281        ( this.runner ){};
     282        init( this, name, _cltr );
    247283
    248284        __cfadbg_print_safe(runtime_core, "Kernel : Starting core %p\n", &this);
    249285
    250286        this.stack = __create_pthread( &this.kernel_thread, __invoke_processor, (void *)&this );
    251         __atomic_fetch_add( &cltr->nprocessors, 1u, __ATOMIC_SEQ_CST );
    252 
    253         __cfadbg_print_safe(runtime_core, "Kernel : core %p created\n", &this);
     287
    254288}
    255289
     
    269303
    270304        free( this.stack );
     305
     306        deinit( this );
    271307
    272308        __atomic_fetch_sub( &cltr->nprocessors, 1u, __ATOMIC_SEQ_CST );
     
    318354
    319355        __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this);
    320 
    321         // register the processor unless it's the main thread which is handled in the boot sequence
    322         if(this != mainProcessor) {
    323                 this->id = doregister((__processor_id_t*)this);
    324                 #if !defined(__CFA_NO_STATISTICS__)
    325                         if( this->print_halts ) {
    326                                 __cfaabi_bits_print_safe( STDOUT_FILENO, "Processor : %d - %s (%p)\n", this->id, this->name, (void*)this);
    327                         }
    328                 #endif
    329 
    330                 // Lock the RWlock so no-one pushes/pops while we are changing the queue
    331                 uint_fast32_t last_size = ready_mutate_lock();
    332 
    333                         // Adjust the ready queue size
    334                         ready_queue_grow( this->cltr );
    335 
    336                 // Unlock the RWlock
    337                 ready_mutate_unlock( last_size );
    338         }
     356        #if !defined(__CFA_NO_STATISTICS__)
     357                if( this->print_halts ) {
     358                        __cfaabi_bits_print_safe( STDOUT_FILENO, "Processor : %d - %s (%p)\n", this->id, this->name, (void*)this);
     359                }
     360        #endif
    339361
    340362        {
     
    375397        V( this->terminated );
    376398
    377         // unregister the processor unless it's the main thread which is handled in the boot sequence
    378         if(this != mainProcessor) {
    379                 // Lock the RWlock so no-one pushes/pops while we are changing the queue
    380                 uint_fast32_t last_size = ready_mutate_lock();
    381 
    382                         // Adjust the ready queue size
    383                         ready_queue_shrink( this->cltr );
    384 
    385                         // Make sure we aren't on the idle queue
    386                         #if !defined(__CFA_NO_STATISTICS__)
    387                                 bool removed =
    388                         #endif
    389                         unsafe_remove( this->cltr->idles, this );
    390 
    391                         #if !defined(__CFA_NO_STATISTICS__)
    392                                 if(removed) __tls_stats()->ready.sleep.exits++;
    393                         #endif
    394 
    395                 // Unlock the RWlock
    396                 ready_mutate_unlock( last_size );
    397 
    398                 // Finally we don't need the read_lock any more
    399                 unregister((__processor_id_t*)this);
    400         }
    401         else {
     399        if(this == mainProcessor) {
    402400                // HACK : the coroutine context switch expects this_thread to be set
    403401                // and it make sense for it to be set in all other cases except here
     
    859857
    860858        void ?{}(processor & this) with( this ) {
    861                 name = "Main Processor";
    862                 cltr = mainCluster;
    863                 terminated{ 0 };
    864                 do_terminate = false;
    865                 preemption_alarm = 0p;
    866                 pending_preemption = false;
     859                ( this.idle ){};
     860                ( this.terminated ){ 0 };
     861                ( this.runner ){};
     862                init( this, "Main Processor", *mainCluster );
    867863                kernel_thread = pthread_self();
    868                 id = -1u;
    869 
    870                 #if !defined(__CFA_NO_STATISTICS__)
    871                         print_stats = false;
    872                         print_halts = false;
    873                 #endif
    874864
    875865                runner{ &this };
    876866                __cfadbg_print_safe(runtime_core, "Kernel : constructed main processor context %p\n", &runner);
    877 
    878                 __atomic_fetch_add( &cltr->nprocessors, 1u, __ATOMIC_SEQ_CST );
    879867        }
    880868
     
    883871        mainProcessor = (processor *)&storage_mainProcessor;
    884872        (*mainProcessor){};
    885 
    886         mainProcessor->id = doregister( (__processor_id_t*)mainProcessor);
    887873
    888874        //initialize the global state variables
     
    944930        kernel_stop_preemption();
    945931
    946         unregister((__processor_id_t*)mainProcessor);
    947 
    948932        // Destroy the main processor and its context in reverse order of construction
    949933        // These were manually constructed so we need manually destroy them
    950934        void ^?{}(processor & this) with( this ){
     935                deinit( this );
     936
    951937                /* paranoid */ verify( this.do_terminate == true );
    952938                __atomic_fetch_sub( &cltr->nprocessors, 1u, __ATOMIC_SEQ_CST );
  • libcfa/src/concurrency/ready_queue.cfa

    rf0c3120 r04b73b6  
    186186//=======================================================================
    187187void ?{}(__ready_queue_t & this) with (this) {
    188 
    189         lanes.data = alloc(4);
    190         for( i; 4 ) {
    191                 (lanes.data[i]){};
    192         }
    193         lanes.count = 4;
    194         snzi{ log2( lanes.count / 8 ) };
     188        lanes.data  = 0p;
     189        lanes.count = 0;
    195190}
    196191
    197192void ^?{}(__ready_queue_t & this) with (this) {
    198         verify( 4  == lanes.count );
     193        verify( 0  == lanes.count );
    199194        verify( !query( snzi ) );
    200 
    201         ^(snzi){};
    202 
    203         for( i; 4 ) {
    204                 ^(lanes.data[i]){};
    205         }
    206195        free(lanes.data);
    207196}
     
    495484}
    496485
     486#warning remove when alloc is fixed
     487forall( dtype T | sized(T) )
     488static inline T * correct_alloc( T ptr[], size_t dim ) {
     489        if( dim == 0 ) {
     490                free(ptr);
     491                return 0p;
     492        }
     493        T * temp = alloc( dim );
     494        if(ptr) {
     495                memcpy( temp, ptr, dim * sizeof(T));
     496                free(ptr);
     497        }
     498        return temp;
     499}
     500
    497501// Grow the ready queue
    498502void ready_queue_grow  (struct cluster * cltr) {
     
    513517
    514518                // Allocate new array (uses realloc and memcpies the data)
    515                 lanes.data = alloc(lanes.data, ncount);
     519                lanes.data = correct_alloc(lanes.data, ncount);
    516520
    517521                // Fix the moved data
     
    558562                size_t ocount = lanes.count;
    559563                // Check that we have some space left
    560                 if(ocount < 8) abort("Program attempted to destroy more Ready Queues than were created");
     564                if(ocount < 4) abort("Program attempted to destroy more Ready Queues than were created");
    561565
    562566                // reduce the actual count so push doesn't use the old queues
     
    600604
    601605                // Allocate new array (uses realloc and memcpies the data)
    602                 lanes.data = alloc(lanes.data, lanes.count);
     606                lanes.data = correct_alloc(lanes.data, lanes.count);
    603607
    604608                // Fix the moved data
  • libcfa/src/concurrency/snzi.hfa

    rf0c3120 r04b73b6  
    120120//--------------------------------------------------
    121121// SNZI object
     122void  ?{}( __snzi_t & this ) {
     123        this.mask = 0;
     124        this.root = 0;
     125        this.nodes = 0p;
     126}
     127
    122128void  ?{}( __snzi_t & this, unsigned depth ) with( this ) {
    123129        mask = (1 << depth) - 1;
  • libcfa/src/concurrency/stats.cfa

    rf0c3120 r04b73b6  
    2424                stats->ready.sleep.exits   = 0;
    2525
    26                 #if defined(HAVE_LINUX_IO_URING_H)
     26                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    2727                        stats->io.submit_q.submit_avg.rdy = 0;
    2828                        stats->io.submit_q.submit_avg.csm = 0;
     
    5959                __atomic_fetch_add( &cltr->ready.sleep.exits  , proc->ready.sleep.exits  , __ATOMIC_SEQ_CST );
    6060
    61                 #if defined(HAVE_LINUX_IO_URING_H)
     61                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    6262                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.rdy          , proc->io.submit_q.submit_avg.rdy          , __ATOMIC_SEQ_CST );
    6363                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.csm          , proc->io.submit_q.submit_avg.csm          , __ATOMIC_SEQ_CST );
     
    121121                }
    122122
    123                 #if defined(HAVE_LINUX_IO_URING_H)
     123                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    124124                        if( flags & CFA_STATS_IO ) {
    125125                                double avgrdy = ((double)io.submit_q.submit_avg.rdy) / io.submit_q.submit_avg.cnt;
  • libcfa/src/concurrency/stats.hfa

    rf0c3120 r04b73b6  
    1111        enum {
    1212                CFA_STATS_READY_Q  = 0x01,
    13                 #if defined(HAVE_LINUX_IO_URING_H)
     13                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    1414                        CFA_STATS_IO = 0x02,
    1515                #endif
     
    6464        };
    6565
    66         #if defined(HAVE_LINUX_IO_URING_H)
     66        #if defined(CFA_HAVE_LINUX_IO_URING_H)
    6767                struct __attribute__((aligned(64))) __stats_io_t{
    6868                        struct {
     
    9999        struct __attribute__((aligned(128))) __stats_t {
    100100                __stats_readQ_t ready;
    101                 #if defined(HAVE_LINUX_IO_URING_H)
     101                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    102102                        __stats_io_t    io;
    103103                #endif
  • libcfa/src/heap.cfa

    rf0c3120 r04b73b6  
    1010// Created On       : Tue Dec 19 21:58:35 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jun 13 22:42:15 2020
    13 // Update Count     : 805
     12// Last Modified On : Mon Jul 20 23:00:32 2020
     13// Update Count     : 808
    1414//
    1515
     
    901901          if ( oalign == 0 && size <= odsize && odsize <= size * 2 ) { // allow 50% wasted storage for smaller size
    902902                        header->kind.real.blockSize &= -2;                      // no alignment and turn off 0 fill
     903                        if ( size != odsize ) header->kind.real.size = size; // reset allocation size
    903904                        return oaddr;
    904905                } // if
     
    929930
    930931                size_t odsize = dataStorage( bsize, oaddr, header ); // data storage available in bucket
    931           if ( size <= odsize && odsize <= size * 2 ) { // allow up to 50% wasted storage in smaller size
    932                         // Do not know size of original allocation => cannot do 0 fill for any additional space because do not know
    933                         // where to start filling, i.e., do not overwrite existing values in space.
     932          if ( size <= odsize && odsize <= size * 2 ) {         // allow up to 50% wasted storage in smaller size
     933                        if ( size != odsize ) header->kind.real.size = size; // reset allocation size
    934934                        return oaddr;
    935935                } // if
     
    10981098        // Returns original total allocation size (not bucket size) => array size is dimension * sizeif(T).
    10991099        size_t malloc_size( void * addr ) {
    1100           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     1100          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has zero size
    11011101                HeapManager.Storage.Header * header = headerAddr( addr );
    11021102                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    11081108        // Set allocation size and return previous size.
    11091109        size_t $malloc_size_set( void * addr, size_t size ) {
    1110           if ( unlikely( addr == 0p ) ) return false;           // null allocation is not zero fill
     1110          if ( unlikely( addr == 0p ) ) return 0;                       // null allocation has 0 size
    11111111                HeapManager.Storage.Header * header = headerAddr( addr );
    11121112                if ( (header->kind.fake.alignment & 1) == 1 ) { // fake header ?
     
    12271227                if ( size <= odsize && odsize <= size * 2 ) {   // allow 50% wasted storage for smaller size
    12281228                        header->kind.real.blockSize &= -2;                      // turn off 0 fill
     1229                        if ( size != odsize ) header->kind.real.size = size; // reset allocation size
    12291230                        return oaddr;
    12301231                } // if
  • libcfa/src/heap.hfa

    rf0c3120 r04b73b6  
    1010// Created On       : Tue May 26 11:23:55 2020
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jun  1 21:19:00 2020
    13 // Update Count     : 10
     12// Last Modified On : Mon Jul 20 18:52:31 2020
     13// Update Count     : 11
    1414//
    1515
     
    3535        void * resize( void * oaddr, size_t size );
    3636        void * amemalign( size_t align, size_t dim, size_t elemSize );
    37         void * cmemalign( size_t align, size_t noOfElems, size_t elemSize );
     37        void * cmemalign( size_t align, size_t dim, size_t elemSize );
    3838        size_t malloc_alignment( void * addr );
    3939        bool malloc_zero_fill( void * addr );
  • libcfa/src/iostream.cfa

    rf0c3120 r04b73b6  
    1010// Created On       : Wed May 27 17:56:53 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Thu Jul 16 07:43:31 2020
    13 // Update Count     : 1102
     12// Last Modified On : Mon Jul 20 15:00:37 2020
     13// Update Count     : 1124
    1414//
    1515
     
    167167        #define P10_UINT64 10_000_000_000_000_000_000_ULL       // 19 zeroes
    168168
    169         static void base10_128( ostype & os, unsigned int128 val ) {
     169        static inline void base10_128( ostype & os, unsigned int128 val ) {
     170#if defined(__GNUC__) && __GNUC_PREREQ(7,0)                             // gcc version >= 7
    170171                if ( val > P10_UINT64 ) {
     172#else
     173                if ( (uint64_t)(val >> 64) != 0 || (uint64_t)val > P10_UINT64 ) { // patch gcc 5 & 6 -O3 bug
     174#endif // __GNUC_PREREQ(7,0)
    171175                        base10_128( os, val / P10_UINT64 );                     // recursive
    172176                        fmt( os, "%.19lu", (uint64_t)(val % P10_UINT64) );
     
    176180        } // base10_128
    177181
    178         static void base10_128( ostype & os, int128 val ) {
     182        static inline void base10_128( ostype & os, int128 val ) {
    179183                if ( val < 0 ) {
    180184                        fmt( os, "-" );                                                         // leading negative sign
  • libcfa/src/stdlib.cfa

    rf0c3120 r04b73b6  
    99// Author           : Peter A. Buhr
    1010// Created On       : Thu Jan 28 17:10:29 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun  2 16:46:00 2020
    13 // Update Count     : 500
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Sun Jul 19 15:05:28 2020
     13// Update Count     : 501
    1414//
    1515
     
    2525
    2626//---------------------------------------
    27 
    28 forall( dtype T | sized(T) ) {
    29         T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
    30                 size_t olen = malloc_usable_size( ptr );                // current allocation
    31                 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    32                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    33                 if ( nlen > olen ) {                                                    // larger ?
    34                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    35                 } // if
    36                 return (T *)nptr;
    37         } // alloc_set
    38 
    39         T * alloc_set( T ptr[], size_t dim, T fill ) {          // realloc array with fill
    40                 size_t olen = malloc_usable_size( ptr );                // current allocation
    41                 void * nptr = (void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
    42                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    43                 if ( nlen > olen ) {                                                    // larger ?
    44                         for ( i; malloc_size( ptr ) / sizeof(T) ~ dim ) {
    45                                 memcpy( &ptr[i], &fill, sizeof(T) );    // initialize with fill value
    46                         } // for
    47                 } // if
    48                 return (T *)nptr;
    49         } // alloc_align_set
    50 
    51         T * alloc_align_set( T ptr[], size_t align, char fill ) { // aligned realloc with fill
    52                 size_t olen = malloc_usable_size( ptr );                // current allocation
    53                 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    54                 // char * nptr = alloc_align( ptr, align );
    55                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    56                 if ( nlen > olen ) {                                                    // larger ?
    57                         memset( (char *)nptr + olen, (int)fill, nlen - olen ); // initialize added storage
    58                 } // if
    59                 return (T *)nptr;
    60         } // alloc_align_set
    61 
    62         T * alloc_align_set( T ptr[], size_t align, size_t dim, T fill ) { // aligned realloc with fill
    63                 size_t olen = malloc_usable_size( ptr );                // current allocation
    64                 void * nptr = (void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc
    65                 // char * nptr = alloc_align( ptr, align );
    66                 size_t nlen = malloc_usable_size( nptr );               // new allocation
    67                 if ( nlen > olen ) {                                                    // larger ?
    68                         for ( i; dim ) { memcpy( &ptr[i], &fill, sizeof(T) ); } // initialize with fill value
    69                 } // if
    70                 return (T *)nptr;
    71         } // alloc_align_set
    72 } // distribution
    7327
    7428// allocation/deallocation and constructor/destructor, non-array types
  • libcfa/src/stdlib.hfa

    rf0c3120 r04b73b6  
    99// Author           : Peter A. Buhr
    1010// Created On       : Thu Jan 28 17:12:35 2016
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun  2 16:47:00 2020
    13 // Update Count     : 451
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Tue Jul 21 07:58:05 2020
     13// Update Count     : 475
    1414//
    1515
     
    3939//---------------------------------------
    4040
     41// Macro because of returns
     42#define $VAR_ALLOC( allocation, alignment ) \
     43        if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( (size_t)sizeof(T) ); /* C allocation */ \
     44        else return (T *)alignment( _Alignof(T), sizeof(T) )
     45
     46#define $ARRAY_ALLOC( allocation, alignment, dim ) \
     47        if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( dim, (size_t)sizeof(T) ); /* C allocation */ \
     48        else return (T *)alignment( _Alignof(T), dim, sizeof(T) )
     49
     50#define $RE_SPECIALS( ptr, size, allocation, alignment ) \
     51        if ( unlikely( size == 0 ) || unlikely( ptr == 0p ) ) { \
     52                if ( unlikely( size == 0 ) ) free( ptr ); \
     53                $VAR_ALLOC( malloc, memalign ); \
     54        } /* if */
     55
    4156static inline forall( dtype T | sized(T) ) {
    4257        // Cforall safe equivalents, i.e., implicit size specification
    4358
    4459        T * malloc( void ) {
    45                 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)malloc( (size_t)sizeof(T) ); // C malloc
    46                 else return (T *)memalign( _Alignof(T), sizeof(T) );
     60                $VAR_ALLOC( malloc, memalign );
    4761        } // malloc
    4862
    4963        T * aalloc( size_t dim ) {
    50                 if ( _Alignof(T) <= libAlign() ) return (T *)(void *)aalloc( dim, (size_t)sizeof(T) ); // CFA aalloc
    51                 else return (T *)amemalign( _Alignof(T), dim, sizeof(T) );
     64                $ARRAY_ALLOC( aalloc, amemalign, dim );
    5265        } // aalloc
    5366
    5467        T * calloc( size_t dim ) {
    55                 if ( _Alignof(T) <= libAlign() )return (T *)(void *)calloc( dim, sizeof(T) ); // C calloc
    56                 else return (T *)cmemalign( _Alignof(T), dim, sizeof(T) );
     68                $ARRAY_ALLOC( calloc, cmemalign, dim );
    5769        } // calloc
    5870
    59         T * resize( T * ptr, size_t size ) {                            // CFA realloc, eliminate return-type cast
    60                 return (T *)(void *)resize( (void *)ptr, size ); // C realloc
     71        T * resize( T * ptr, size_t size ) {                            // CFA resize, eliminate return-type cast
     72                $RE_SPECIALS( ptr, size, malloc, memalign );
     73                return (T *)(void *)resize( (void *)ptr, size ); // CFA resize
    6174        } // resize
    6275
    6376        T * realloc( T * ptr, size_t size ) {                           // CFA realloc, eliminate return-type cast
     77                $RE_SPECIALS( ptr, size, malloc, memalign );
    6478                return (T *)(void *)realloc( (void *)ptr, size ); // C realloc
    6579        } // realloc
     
    118132
    119133        T * alloc( T ptr[], size_t dim, bool copy = true ) {
    120                 if ( copy ) {                                                                   // realloc
    121                         return (T *)(void *)realloc( (void *)ptr, dim * sizeof(T) ); // C realloc
     134                if ( copy ) {
     135                        return realloc( ptr, dim * sizeof(T) );         // CFA realloc
    122136                } else {
    123                         return resize( ptr, dim * sizeof(T) );          // resize
     137                        return resize( ptr, dim * sizeof(T) );          // CFA resize
    124138                } // if
    125139        } // alloc
     
    146160                return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value
    147161        } // alloc
    148 } // distribution
    149 
    150 forall( dtype T | sized(T) ) {
    151         T * alloc_set( T ptr[], size_t dim, char fill );        // realloc array with fill
    152         T * alloc_set( T ptr[], size_t dim, T fill );           // realloc array with fill
     162
     163        T * alloc_set( T ptr[], size_t dim, char fill ) {       // realloc array with fill
     164                size_t osize = malloc_size( ptr );                              // current allocation
     165                size_t nsize = dim * sizeof(T);                                 // new allocation
     166                T * nptr = realloc( ptr, nsize );                               // CFA realloc
     167                if ( nsize > osize ) {                                                  // larger ?
     168                        memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage
     169                } // if
     170                return (T *)nptr;
     171        } // alloc_set
     172
     173        T * alloc_set( T ptr[], size_t dim, T & fill ) {        // realloc array with fill
     174                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
     175                size_t nsize = dim * sizeof(T);                                 // new allocation
     176                size_t ndim = nsize / sizeof(T);                                // new dimension
     177                T * nptr = realloc( ptr, nsize );                               // CFA realloc
     178                if ( ndim > odim ) {                                                    // larger ?
     179                        for ( i; odim ~ ndim ) {
     180                                memcpy( &nptr[i], &fill, sizeof(T) );   // initialize with fill value
     181                        } // for
     182                } // if
     183                return (T *)nptr;
     184        } // alloc_align_set
    153185} // distribution
    154186
     
    196228                return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) );
    197229        } // alloc_align
    198 } // distribution
    199 
    200 forall( dtype T | sized(T) ) {
    201         T * alloc_align_set( T ptr[], size_t align, char fill ); // aligned realloc with fill
    202         T * alloc_align_set( T ptr[], size_t align, T fill ); // aligned realloc with fill
    203         T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ); // aligned realloc array with fill
    204         T * alloc_align_set( T ptr[], size_t align, size_t dim, T fill ); // aligned realloc array with fill
     230
     231        T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) {
     232                size_t osize = malloc_size( ptr );                              // current allocation
     233                size_t nsize = dim * sizeof(T);                                 // new allocation
     234                T * nptr = realloc( ptr, align, nsize );                // CFA realloc
     235                if ( nsize > osize ) {                                                  // larger ?
     236                        memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage
     237                } // if
     238                return (T *)nptr;
     239        } // alloc_align_set
     240
     241        T * alloc_align_set( T ptr[], size_t align, size_t dim, T & fill ) {
     242                size_t odim = malloc_size( ptr ) / sizeof(T);   // current dimension
     243                size_t nsize = dim * sizeof(T);                                 // new allocation
     244                size_t ndim = nsize / sizeof(T);                                // new dimension
     245                T * nptr = realloc( ptr, align, nsize );                // CFA realloc
     246                if ( ndim > odim ) {                                                    // larger ?
     247                        for ( i; odim ~ ndim ) {
     248                                memcpy( &nptr[i], &fill, sizeof(T) );   // initialize with fill value
     249                        } // for
     250                } // if
     251                return (T *)nptr;
     252        } // alloc_align_set
    205253} // distribution
    206254
  • src/Common/PassVisitor.proto.h

    rf0c3120 r04b73b6  
    3838        };
    3939
    40         std::stack< cleanup_t > cleanups;
     40        std::stack< cleanup_t, std::vector< cleanup_t > > cleanups;
    4141};
    4242
  • src/Virtual/ExpandCasts.cc

    rf0c3120 r04b73b6  
    1010// Created On       : Mon Jul 24 13:59:00 2017
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue May 26 14:37:00 2020
    13 // Update Count     : 2
     12// Last Modified On : Tue Jul 22 10:04:00 2020
     13// Update Count     : 3
    1414//
    1515
     
    2424#include "Common/PassVisitor.h"    // for PassVisitor
    2525#include "Common/SemanticError.h"  // for SemanticError
     26#include "SymTab/Mangler.h"        // for mangleType
    2627#include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    2728#include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
     
    3132
    3233namespace Virtual {
     34
     35        // Indented until the new ast code gets added.
     36
     37        /// Maps virtual table types the instance for that type.
     38        class VirtualTableMap final {
     39                std::unordered_map<std::string, ObjectDecl *> vtable_instances;
     40        public:
     41                ObjectDecl * insert( ObjectDecl * vtableDecl ) {
     42                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
     43                        ObjectDecl *& value = vtable_instances[ mangledName ];
     44                        if ( value ) {
     45                                if ( vtableDecl->storageClasses.is_extern ) {
     46                                        return nullptr;
     47                                } else if ( ! value->storageClasses.is_extern ) {
     48                                        return value;
     49                                }
     50                        }
     51                        value = vtableDecl;
     52                        return nullptr;
     53                }
     54
     55                ObjectDecl * lookup( const Type * vtableType ) {
     56                        std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
     57                        const auto it = vtable_instances.find( mangledName );
     58                        return ( vtable_instances.end() == it ) ? nullptr : it->second;
     59                }
     60        };
    3361
    3462        /* Currently virtual depends on the rather brittle name matching between
     
    3967         */
    4068
     69        namespace {
     70
    4171        std::string get_vtable_name( std::string const & name ) {
    4272                return name + "_vtable";
     
    5383        std::string get_vtable_inst_name_root( std::string const & name ) {
    5484                return get_vtable_name_root( name.substr(1, name.size() - 10 ) );
    55         }
    56 
    57         bool is_vtable_name( std::string const & name ) {
    58                 return (name.substr( name.size() - 7 ) == "_vtable" );
    5985        }
    6086
     
    6490        }
    6591
     92        } // namespace
     93
    6694        class VirtualCastCore {
    67         std::map<std::string, ObjectDecl *> vtable_instances;
    68         FunctionDecl *vcast_decl;
    69         StructDecl *pvt_decl;
     95                VirtualTableMap vtable_instances;
     96                FunctionDecl *vcast_decl;
     97                StructDecl *pvt_decl;
    7098
    7199                Type * pointer_to_pvt(int level_of_indirection) {
     
    107135        void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    108136                if ( is_vtable_inst_name( objectDecl->get_name() ) ) {
    109                         vtable_instances[objectDecl->get_name()] = objectDecl;
    110                 }
    111         }
    112 
    113         // Better error locations for generated casts.
    114         static CodeLocation castLocation( VirtualCastExpr * castExpr ) {
     137                        if ( ObjectDecl * existing = vtable_instances.insert( objectDecl ) ) {
     138                                std::string msg = "Repeated instance of virtual table, original found at: ";
     139                                msg += existing->location.filename;
     140                                msg += ":" + toString( existing->location.first_line );
     141                                SemanticError( objectDecl->location, msg );
     142                        }
     143                }
     144        }
     145
     146        namespace {
     147
     148        /// Better error locations for generated casts.
     149        CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
    115150                if ( castExpr->location.isSet() ) {
    116151                        return castExpr->location;
     
    124159        }
    125160
     161        [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
     162                SemanticError( castLocation( castExpr ), message );
     163        }
     164
     165        /// Get the virtual table type used in a virtual cast.
     166        Type * getVirtualTableType( const VirtualCastExpr * castExpr ) {
     167                const Type * objectType;
     168                if ( auto target = dynamic_cast<const PointerType *>( castExpr->result ) ) {
     169                        objectType = target->base;
     170                } else if ( auto target = dynamic_cast<const ReferenceType *>( castExpr->result ) ) {
     171                        objectType = target->base;
     172                } else {
     173                        castError( castExpr, "Virtual cast type must be a pointer or reference type." );
     174                }
     175                assert( objectType );
     176
     177                const StructInstType * structType = dynamic_cast<const StructInstType *>( objectType );
     178                if ( nullptr == structType ) {
     179                        castError( castExpr, "Virtual cast type must refer to a structure type." );
     180                }
     181                const StructDecl * structDecl = structType->baseStruct;
     182                assert( structDecl );
     183
     184                const ObjectDecl * fieldDecl = nullptr;
     185                if ( 0 < structDecl->members.size() ) {
     186                        const Declaration * memberDecl = structDecl->members.front();
     187                        assert( memberDecl );
     188                        fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
     189                        if ( fieldDecl && fieldDecl->name != "virtual_table" ) {
     190                                fieldDecl = nullptr;
     191                        }
     192                }
     193                if ( nullptr == fieldDecl ) {
     194                        castError( castExpr, "Virtual cast type must have a leading virtual_table field." );
     195                }
     196                const PointerType * fieldType = dynamic_cast<const PointerType *>( fieldDecl->type );
     197                if ( nullptr == fieldType ) {
     198                        castError( castExpr, "Virtual cast type virtual_table field is not a pointer." );
     199                }
     200                assert( fieldType->base );
     201                auto virtualStructType = dynamic_cast<const StructInstType *>( fieldType->base );
     202                assert( virtualStructType );
     203
     204                // Here is the type, but if it is polymorphic it will have lost information.
     205                // (Always a clone so that it may always be deleted.)
     206                StructInstType * virtualType = virtualStructType->clone();
     207                if ( ! structType->parameters.empty() ) {
     208                        deleteAll( virtualType->parameters );
     209                        virtualType->parameters.clear();
     210                        cloneAll( structType->parameters, virtualType->parameters );
     211                }
     212                return virtualType;
     213        }
     214
     215        } // namespace
     216
    126217        Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    127                 assertf( castExpr->get_result(), "Virtual Cast target not found before expansion." );
     218                assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    128219
    129220                assert( vcast_decl );
    130221                assert( pvt_decl );
    131222
    132                 // Get the base type of the pointer/reference.
    133                 Type * base;
    134                 Type * result_type = castExpr->result;
    135                 if ( PointerType * target = dynamic_cast<PointerType *>( result_type ) ) {
    136                         base = target->base;
    137                 } else if ( ReferenceType * target = dynamic_cast<ReferenceType *>( result_type ) ) {
    138                         base = target->base;
    139                 } else {
     223                const Type * vtable_type = getVirtualTableType( castExpr );
     224                ObjectDecl * table = vtable_instances.lookup( vtable_type );
     225                if ( nullptr == table ) {
    140226                        SemanticError( castLocation( castExpr ),
    141                                 "Virtual cast type must be a pointer or reference type." );
    142                 }
    143 
    144                 StructInstType * target_struct = dynamic_cast<StructInstType *>( base );
    145                 if ( nullptr == target_struct ) {
    146                         SemanticError( castLocation( castExpr ),
    147                                 "Virtual cast type must refer to a structure type." );
    148                 }
    149                 StructDecl * target_decl = target_struct->get_baseStruct();
    150 
    151                 std::map<std::string, ObjectDecl *>::iterator found =
    152                         vtable_instances.find( get_vtable_inst_name( target_decl->get_name() ) );
    153                 if ( vtable_instances.end() == found ) {
    154                         SemanticError( castLocation( castExpr ),
    155                                 "Virtual cast type does not have a virtual table instance." );
    156                 }
    157                 ObjectDecl * table = found->second;
     227                                "Could not find virtual table instance." );
     228                }
    158229
    159230                Expression * result = new CastExpr(
     
    174245                castExpr->set_result( nullptr );
    175246                delete castExpr;
     247                delete vtable_type;
    176248                return result;
    177249        }
  • tests/.expect/alloc.txt

    rf0c3120 r04b73b6  
    30300xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    3131CFA realloc array alloc, fill
    32 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
     320xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
    3333CFA realloc array alloc, fill
    34340xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef
    3535CFA realloc array alloc, fill
    36 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0x1010101 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
     360xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdeadbeef 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede 0xdededede
    3737
    3838C   memalign 42 42.5
Note: See TracChangeset for help on using the changeset viewer.