Changes in / [762fbc1:7f51b9d]
- Files:
-
- 11 deleted
- 15 edited
-
benchmark/benchcltr.hfa (modified) (5 diffs)
-
benchmark/io/readv-posix.c (deleted)
-
benchmark/io/readv.cfa (modified) (2 diffs)
-
benchmark/readyQ/yield.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/coroutine.cfa (modified) (1 diff)
-
libcfa/src/concurrency/invoke.c (modified) (2 diffs)
-
libcfa/src/concurrency/invoke.h (modified) (1 diff)
-
libcfa/src/concurrency/io.cfa (modified) (2 diffs)
-
libcfa/src/concurrency/io/setup.cfa (modified) (1 diff)
-
libcfa/src/concurrency/iocall.cfa (modified) (3 diffs)
-
libcfa/src/exception.c (modified) (1 diff)
-
libcfa/src/parseargs.cfa (modified) (12 diffs)
-
libcfa/src/parseargs.hfa (modified) (2 diffs)
-
tests/Makefile.am (modified) (1 diff)
-
tests/exceptions/.expect/conditional-threads.txt (deleted)
-
tests/exceptions/.expect/defaults-threads.txt (deleted)
-
tests/exceptions/.expect/finally-threads.txt (deleted)
-
tests/exceptions/.expect/resume-threads.txt (deleted)
-
tests/exceptions/.expect/terminate-threads.txt (deleted)
-
tests/exceptions/terminate.cfa (modified) (1 diff)
-
tests/exceptions/with-threads.hfa (deleted)
-
tests/linking/.expect/exception-nothreads.txt (deleted)
-
tests/linking/.expect/exception-withthreads.txt (deleted)
-
tests/linking/exception-nothreads.cfa (deleted)
-
tests/linking/exception-withthreads.cfa (deleted)
-
tests/linking/withthreads.cfa (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
benchmark/benchcltr.hfa
r762fbc1 r7f51b9d 1 1 #pragma once 2 2 3 #include <assert.h> 3 #include <stdint.h> 4 5 #ifdef __cforall 6 #include <kernel.hfa> 7 #include <thread.hfa> 8 #include <stats.hfa> 9 #else 10 #include <time.h> // timespec 11 #include <sys/time.h> // timeval 12 13 enum { TIMEGRAN = 1000000000LL }; // nanosecond granularity, except for timeval 14 #endif 4 #include <kernel.hfa> 5 #include <thread.hfa> 6 #include <stats.hfa> 15 7 16 8 #define BENCH_OPT_SHORT "d:p:t:SPV" … … 22 14 {"procstat", no_argument , 0, 'P'}, \ 23 15 {"viewhalts", no_argument , 0, 'V'}, 16 17 #define BENCH_DECL \ 18 double duration = 5; \ 19 int nprocs = 1; \ 20 int nthreads = 1; 24 21 25 22 #define BENCH_OPT_CASE \ … … 55 52 break; 56 53 57 double duration = 5;58 int nprocs = 1;59 int nthreads = 1;60 54 bool silent = false; 61 bool continuous = false;62 55 bool procstats = false; 63 56 bool viewhalts = false; 64 65 #define BENCH_OPT_CFA \66 {'d', "duration", "Duration of the experiments in seconds", duration }, \67 {'t', "nthreads", "Number of threads to use", nthreads }, \68 {'p', "nprocs", "Number of processors to use", nprocs }, \69 {'S', "nostats", "Don't print statistics", silent, parse_settrue }, \70 {'C', "constats", "Regularly print statistics", continuous, parse_settrue }, \71 {'P', "procstat", "Print statistics for each processors", procstats, parse_settrue }, \72 {'V', "viewhalts", "Visualize halts, prints timestamp and Processor id for each halt.", viewhalts, parse_settrue },73 74 #ifdef __cforall75 #include <parseargs.hfa>76 77 57 struct cluster * the_benchmark_cluster = 0p; 78 58 struct BenchCluster { … … 80 60 }; 81 61 82 void ?{}( BenchCluster & this, int num_io, const io_context_params & io_params, int stats ) {83 (this.self){ "Benchmark Cluster", num_io, io_params };62 void ?{}( BenchCluster & this, int flags, int stats ) { 63 (this.self){ "Benchmark Cluster", flags }; 84 64 85 65 assert( the_benchmark_cluster == 0p ); … … 125 105 } 126 106 } 127 #else128 uint64_t getTimeNsec() {129 timespec curr;130 clock_gettime( CLOCK_REALTIME, &curr );131 return (int64_t)curr.tv_sec * TIMEGRAN + curr.tv_nsec;132 }133 134 uint64_t to_miliseconds( uint64_t durtn ) { return durtn / (TIMEGRAN / 1000LL); }135 double to_fseconds(uint64_t durtn ) { return durtn / (double)TIMEGRAN; }136 uint64_t from_fseconds(double sec) { return sec * TIMEGRAN; }137 138 139 void wait_duration(double duration, uint64_t & start, uint64_t & end, bool is_tty) {140 for(;;) {141 usleep(100000);142 end = getTimeNsec();143 uint64_t delta = end - start;144 /*if(is_tty)*/ {145 printf(" %.1f\r", to_fseconds(delta));146 fflush(stdout);147 }148 if( delta >= from_fseconds(duration) ) {149 break;150 }151 }152 }153 #endif154 155 107 156 108 void bench_usage( char * argv [] ) { -
benchmark/io/readv.cfa
r762fbc1 r7f51b9d 40 40 int do_read(int fd, struct iovec * iov) { 41 41 // extern ssize_t cfa_preadv2(int, const struct iovec *, int, off_t, int, int = 0, Duration = -1`s, io_cancellation * = 0p, io_context * = 0p); 42 int sflags = 0 43 #if defined(CFA_HAVE_IOSQE_ASYNC) 44 | CFA_IO_ASYNC 45 #else 46 #warning no CFA_IO_ASYNC support 47 #endif 48 ; 42 int sflags = 0; 49 43 if(fixed_file) { 50 44 sflags |= CFA_IO_FIXED_FD1; … … 69 63 70 64 int main(int argc, char * argv[]) { 65 BENCH_DECL 66 unsigned num_io = 1; 67 io_context_params params; 71 68 int file_flags = 0; 72 unsigned num_io = 1;73 69 unsigned sublen = 16; 74 unsigned nentries = 0;75 70 76 bool subthrd = false; 77 bool subeagr = false; 78 bool odirect = false; 79 bool kpollsb = false; 80 bool kpollcp = false; 71 arg_loop: 72 for(;;) { 73 static struct option options[] = { 74 BENCH_OPT_LONG 75 {"bufsize", required_argument, 0, 'b'}, 76 {"submitthread", no_argument , 0, 's'}, 77 {"eagersubmit", no_argument , 0, 'e'}, 78 {"kpollsubmit", no_argument , 0, 'k'}, 79 {"kpollcomplete", no_argument , 0, 'i'}, 80 {"fixed-files", no_argument , 0, 'f'}, 81 {"open-direct", no_argument , 0, 'o'}, 82 {"submitlength", required_argument, 0, 'l'}, 83 {0, 0, 0, 0} 84 }; 81 85 82 cfa_option opt[] = { 83 BENCH_OPT_CFA 84 {'b', "bufsize", "Number of bytes to read per request", buflen}, 85 {'s', "submitthread", "If set, cluster uses polling thread to submit I/O", subthrd, parse_settrue}, 86 {'e', "eagersubmit", "If set, cluster submits I/O eagerly but still aggregates submits", subeagr, parse_settrue}, 87 {'f', "fixed-files", "Pre-register files with the io_contexts", fixed_file, parse_settrue}, 88 {'o', "open-direct", "Open files with O_DIRECT flag, bypassing the file cache", odirect, parse_settrue}, 89 {'k', "kpollsubmit", "If set, cluster uses an in kernel thread to poll submission, implies -f, requires elevated permissions", kpollsb, parse_settrue}, 90 {'i', "kpollcomplete", "If set, cluster polls fds for completions instead of relying on interrupts to get notifications, implies -o", kpollcp, parse_settrue}, 91 {'l', "submitlength", "Size of the buffer that stores ready submissions", sublen}, 92 {'r', "numentries", "Number of entries each of the io_context have", nentries}, 93 {'n', "numcontexts", "Number of io_contexts to the cluster", num_io}, 94 }; 95 int opt_cnt = sizeof(opt) / sizeof(cfa_option); 86 int idx = 0; 87 int opt = getopt_long(argc, argv, BENCH_OPT_SHORT "b:sekil:", options, &idx); 96 88 97 char **left; 98 parse_args( opt, opt_cnt, "[OPTIONS]...\ncforall yield benchmark", left ); 99 100 if(kpollcp || odirect) { 101 if( (buflen % 512) != 0 ) { 102 fprintf(stderr, "Buffer length must be a multiple of 512 when using O_DIRECT, was %lu\n\n", buflen); 103 print_args_usage(opt, opt_cnt, "[OPTIONS]...\ncforall yield benchmark", true); 89 const char * arg = optarg ? optarg : ""; 90 char * end; 91 switch(opt) { 92 // Exit Case 93 case -1: 94 break arg_loop; 95 BENCH_OPT_CASE 96 case 'b': 97 buflen = strtoul(arg, &end, 10); 98 if(*end != '\0' && buflen < 10) { 99 fprintf(stderr, "Buffer size must be at least 10, was %s\n", arg); 100 goto usage; 101 } 102 break; 103 case 's': 104 params.poller_submits = true; 105 break; 106 case 'e': 107 params.eager_submits = true; 108 break; 109 case 'k': 110 params.poll_submit = true; 111 case 'f': 112 fixed_file = true; 113 break; 114 case 'i': 115 params.poll_complete = true; 116 case 'o': 117 file_flags |= O_DIRECT; 118 break; 119 case 'l': 120 sublen = strtoul(arg, &end, 10); 121 if(*end != '\0' && sublen < 16) { 122 fprintf(stderr, "Submit length must be at least 16, was %s\n", arg); 123 goto usage; 124 } 125 // flags |= (sublen << CFA_CLUSTER_IO_BUFFLEN_OFFSET); 126 break; 127 default: /* ? */ 128 fprintf(stderr, "%d\n", opt); 129 usage: 130 bench_usage( argv ); 131 fprintf( stderr, " -b, --buflen=SIZE Number of bytes to read per request\n" ); 132 fprintf( stderr, " -u, --userthread If set, cluster uses user-thread to poll I/O\n" ); 133 fprintf( stderr, " -s, --submitthread If set, cluster uses polling thread to submit I/O\n" ); 134 fprintf( stderr, " -e, --eagersubmit If set, cluster submits I/O eagerly but still aggregates submits\n" ); 135 fprintf( stderr, " -k, --kpollsubmit If set, cluster uses IORING_SETUP_SQPOLL\n" ); 136 fprintf( stderr, " -i, --kpollcomplete If set, cluster uses IORING_SETUP_IOPOLL\n" ); 137 fprintf( stderr, " -l, --submitlength=LEN Max number of submitions that can be submitted together\n" ); 138 exit(EXIT_FAILURE); 104 139 } 105 140 } 106 107 io_context_params params;108 109 if( subthrd ) params.poller_submits = true;110 if( subeagr ) params.eager_submits = true;111 if( kpollsb ) params.poll_submit = true;112 if( kpollcp ) params.poll_complete = true;113 114 if(params.poll_submit ) fixed_file = true;115 if(params.poll_complete) odirect = true;116 117 params.num_ready = sublen;118 params.num_entries = nentries;119 120 if(odirect) file_flags |= O_DIRECT;121 141 122 142 int lfd = open(__FILE__, file_flags); -
benchmark/readyQ/yield.cfa
r762fbc1 r7f51b9d 43 43 44 44 int main(int argc, char * argv[]) { 45 unsigned num_io = 1; 46 io_context_params params; 45 BENCH_DECL 47 46 48 cfa_option opt[] = { 49 BENCH_OPT_CFA 50 }; 51 int opt_cnt = sizeof(opt) / sizeof(cfa_option); 47 for(;;) { 48 static struct option options[] = { 49 BENCH_OPT_LONG 50 {0, 0, 0, 0} 51 }; 52 52 53 char **left; 54 parse_args( argc, argv, opt, opt_cnt, "[OPTIONS]...\ncforall yield benchmark", left ); 53 int idx = 0; 54 int opt = getopt_long(argc, argv, BENCH_OPT_SHORT, options, &idx); 55 56 const char * arg = optarg ? optarg : ""; 57 char * end; 58 switch(opt) { 59 case -1: 60 goto run; 61 BENCH_OPT_CASE 62 default: /* ? */ 63 fprintf( stderr, "Unkown option '%c'\n", opt); 64 usage: 65 bench_usage( argv ); 66 exit(1); 67 } 68 } 69 run: 55 70 56 71 { … … 58 73 59 74 Time start, end; 60 BenchCluster cl = { num_io, params, CFA_STATS_READY_Q };75 BenchCluster cl = { 0, CFA_STATS_READY_Q }; 61 76 { 62 77 BenchProc procs[nprocs]; -
libcfa/src/concurrency/coroutine.cfa
r762fbc1 r7f51b9d 215 215 return cor; 216 216 } 217 218 struct $coroutine * __cfactx_cor_active(void) {219 return active_coroutine();220 }221 217 } 222 218 -
libcfa/src/concurrency/invoke.c
r762fbc1 r7f51b9d 29 29 // Called from the kernel when starting a coroutine or task so must switch back to user mode. 30 30 31 extern struct $coroutine * __cfactx_cor_active(void);32 31 extern struct $coroutine * __cfactx_cor_finish(void); 33 32 extern void __cfactx_cor_leave ( struct $coroutine * ); … … 36 35 extern void disable_interrupts() OPTIONAL_THREAD; 37 36 extern void enable_interrupts( __cfaabi_dbg_ctx_param ); 38 39 struct exception_context_t * this_exception_context() {40 return &__get_stack( __cfactx_cor_active() )->exception_context;41 }42 37 43 38 void __cfactx_invoke_coroutine( -
libcfa/src/concurrency/invoke.h
r762fbc1 r7f51b9d 98 98 } 99 99 100 struct exception_context_t * this_exception_context();101 102 100 // struct which calls the monitor is accepting 103 101 struct __waitfor_mask_t { -
libcfa/src/concurrency/io.cfa
r762fbc1 r7f51b9d 359 359 360 360 // We got the lock 361 // Collect the submissions362 361 unsigned to_submit = __collect_submitions( ring ); 363 364 // Actually submit365 362 int ret = __io_uring_enter( ring, to_submit, false ); 366 367 unlock(ring.submit_q.lock); 368 if( ret < 0 ) return; 363 if( ret < 0 ) { 364 unlock(ring.submit_q.lock); 365 return; 366 } 367 368 /* paranoid */ verify( ret > 0 || to_submit == 0 || (ring.ring_flags & IORING_SETUP_SQPOLL) ); 369 369 370 370 // Release the consumed SQEs … … 372 372 373 373 // update statistics 374 __STATS__( false,374 __STATS__( true, 375 375 io.submit_q.submit_avg.rdy += to_submit; 376 376 io.submit_q.submit_avg.csm += ret; 377 377 io.submit_q.submit_avg.cnt += 1; 378 378 ) 379 380 unlock(ring.submit_q.lock); 379 381 } 380 382 else { -
libcfa/src/concurrency/io/setup.cfa
r762fbc1 r7f51b9d 298 298 if( params_in.poll_complete ) params.flags |= IORING_SETUP_IOPOLL; 299 299 300 uint32_t nentries = params_in.num_entries != 0 ? params_in.num_entries : 256; 301 if( !is_pow2(nentries) ) { 302 abort("ERROR: I/O setup 'num_entries' must be a power of 2\n"); 303 } 304 if( params_in.poller_submits && params_in.eager_submits ) { 305 abort("ERROR: I/O setup 'poller_submits' and 'eager_submits' cannot be used together\n"); 306 } 300 uint32_t nentries = params_in.num_entries; 307 301 308 302 int fd = syscall(__NR_io_uring_setup, nentries, ¶ms ); -
libcfa/src/concurrency/iocall.cfa
r762fbc1 r7f51b9d 101 101 #endif 102 102 103 103 104 #define __submit_prelude \ 104 105 if( 0 != (submit_flags & LINK_FLAGS) ) { errno = ENOTSUP; return -1; } \ … … 109 110 struct io_uring_sqe * sqe; \ 110 111 uint32_t idx; \ 111 uint8_t sflags = REGULAR_FLAGS & submit_flags; \112 112 [sqe, idx] = __submit_alloc( ring, (uint64_t)(uintptr_t)&data ); \ 113 sqe->flags = sflags;113 sqe->flags = REGULAR_FLAGS & submit_flags; 114 114 115 115 #define __submit_wait \ … … 186 186 __submit_prelude 187 187 188 sqe->opcode = IORING_OP_READV; 189 sqe->ioprio = 0; 190 sqe->fd = fd; 191 sqe->off = offset; 192 sqe->addr = (uint64_t)(uintptr_t)iov; 193 sqe->len = iovcnt; 194 sqe->rw_flags = 0; 195 sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0; 188 (*sqe){ IORING_OP_READV, fd, iov, iovcnt, offset }; 196 189 197 190 __submit_wait -
libcfa/src/exception.c
r762fbc1 r7f51b9d 59 59 60 60 61 // Temperary global exception context. Does not work with concurency. 62 static struct exception_context_t shared_stack = {NULL, NULL}; 63 61 64 // Get the current exception context. 62 65 // There can be a single global until multithreading occurs, then each stack 63 // needs its own. We get this from libcfathreads (no weak attribute). 64 __attribute__((weak)) struct exception_context_t * this_exception_context() { 65 static struct exception_context_t shared_stack = {NULL, NULL}; 66 // needs its own. It will have to be updated to handle that. 67 struct exception_context_t * this_exception_context() { 66 68 return &shared_stack; 67 69 } -
libcfa/src/parseargs.cfa
r762fbc1 r7f51b9d 19 19 extern long long int strtoll (const char* str, char** endptr, int base); 20 20 extern unsigned long long int strtoull(const char* str, char** endptr, int base); 21 extern double strtod (const char* str, char** endptr);22 21 } 23 22 … … 29 28 extern char ** cfa_args_envp; 30 29 31 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * usage, FILE * out) __attribute__ ((noreturn)); 30 void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) { 31 int hwidth = max - (11 + width); 32 if(hwidth <= 0) hwidth = max; 33 34 fprintf(out, " -%c, --%-*s %.*s\n", sn, width, ln, hwidth, help); 35 for() { 36 help += min(strlen(help), hwidth); 37 if('\0' == *help) break; 38 fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help); 39 } 40 } 32 41 33 42 void parse_args( cfa_option options[], size_t opt_count, const char * usage, char ** & left ) { … … 35 44 } 36 45 37 //-----------------------------------------------------------------------------38 // getopt_long wrapping39 46 void parse_args( 40 47 int argc, … … 46 53 ) { 47 54 struct option optarr[opt_count + 2]; 55 int width = 0; 56 int max_width = 1_000_000; 48 57 { 49 58 int idx = 0; … … 60 69 } 61 70 idx++; 71 72 int w = strlen(options[i].long_name); 73 if(w > width) width = w; 62 74 } 63 75 } … … 94 106 out = stdout; 95 107 case '?': 96 usage(argv[0], options, opt_count, usage, out);108 goto USAGE; 97 109 default: 98 110 for(i; opt_count) { … … 103 115 104 116 fprintf(out, "Argument '%s' for option %c could not be parsed\n\n", arg, (char)opt); 105 usage(argv[0], options, opt_count, usage, out);117 goto USAGE; 106 118 } 107 119 } … … 110 122 111 123 } 112 } 113 114 //----------------------------------------------------------------------------- 115 // Print usage 116 static void printopt(FILE * out, int width, int max, char sn, const char * ln, const char * help) { 117 int hwidth = max - (11 + width); 118 if(hwidth <= 0) hwidth = max; 119 120 fprintf(out, " -%c, --%-*s %.*s\n", sn, width, ln, hwidth, help); 121 for() { 122 help += min(strlen(help), hwidth); 123 if('\0' == *help) break; 124 fprintf(out, "%*s%.*s\n", width + 11, "", hwidth, help); 125 } 126 } 127 128 void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) { 129 usage(cfa_args_argv[0], options, opt_count, usage, error ? stderr : stdout); 130 } 131 132 void print_args_usage(int , char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn)) { 133 usage(argv[0], options, opt_count, usage, error ? stderr : stdout); 134 } 135 136 static void usage(char * cmd, cfa_option options[], size_t opt_count, const char * help, FILE * out) __attribute__((noreturn)) { 137 int width = 0; 138 { 139 int idx = 0; 140 for(i; opt_count) { 141 if(options[i].long_name) { 142 int w = strlen(options[i].long_name); 143 if(w > width) width = w; 144 } 145 } 146 } 147 148 int max_width = 1_000_000; 124 125 USAGE:; 149 126 int outfd = fileno(out); 150 127 if(isatty(outfd)) { … … 155 132 } 156 133 157 fprintf(out, "Usage:\n %s %s\n", cmd, help);134 fprintf(out, "Usage:\n %s %s\n", argv[0], usage); 158 135 159 136 for(i; opt_count) { … … 164 141 } 165 142 166 //-----------------------------------------------------------------------------167 // Typed argument parsing168 143 bool parse_yesno(const char * arg, bool & value ) { 169 144 if(strcmp(arg, "yes") == 0) { … … 192 167 bool parse(const char * arg, const char * & value ) { 193 168 value = arg; 194 return true;195 }196 197 bool parse(const char * arg, int & value) {198 char * end;199 int r = strtoll(arg, &end, 10);200 if(*end != '\0') return false;201 202 value = r;203 169 return true; 204 170 } … … 234 200 } 235 201 236 bool parse(const char * arg, double& value) {202 bool parse(const char * arg, int & value) { 237 203 char * end; 238 double r = strtod(arg, &end);204 int r = strtoll(arg, &end, 10); 239 205 if(*end != '\0') return false; 240 206 -
libcfa/src/parseargs.hfa
r762fbc1 r7f51b9d 34 34 void parse_args( int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, char ** & left ); 35 35 36 void print_args_usage(cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn));37 void print_args_usage(int argc, char * argv[], cfa_option options[], size_t opt_count, const char * usage, bool error) __attribute__ ((noreturn));38 39 36 bool parse_yesno (const char *, bool & ); 40 37 bool parse_settrue (const char *, bool & ); … … 42 39 43 40 bool parse(const char *, const char * & ); 44 bool parse(const char *, int & );45 41 bool parse(const char *, unsigned & ); 46 42 bool parse(const char *, unsigned long & ); 47 43 bool parse(const char *, unsigned long long & ); 48 bool parse(const char *, double& );44 bool parse(const char *, int & ); -
tests/Makefile.am
r762fbc1 r7f51b9d 163 163 $(CFACOMPILETEST) -DERR2 -c -fsyntax-only -o $(abspath ${@}) 164 164 165 # Exception Tests166 # Test with libcfathread; it changes how storage works.167 168 exceptions/%-threads : exceptions/%.cfa $(CFACCBIN)169 $(CFACOMPILETEST) -include exceptions/with-threads.hfa -c -o $(abspath ${@}).o170 $(CFACCLOCAL) $($(shell echo "${@}_FLAGSLD" | sed 's/-\|\//_/g')) $(abspath ${@}).o -o $(abspath ${@})171 172 165 #------------------------------------------------------------------------------ 173 166 # Other targets -
tests/exceptions/terminate.cfa
r762fbc1 r7f51b9d 142 142 } 143 143 } 144 -
tests/linking/withthreads.cfa
r762fbc1 r7f51b9d 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // withthreads.cfa --7 // nothreads.cfa -- 8 8 // 9 9 // Author : Thierry Delisle
Note:
See TracChangeset
for help on using the changeset viewer.