Changeset 295dd61
- Timestamp:
- Dec 6, 2021, 5:06:14 PM (4 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 75873cf
- Parents:
- 813dfd86 (diff), a83012bf (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. - Files:
-
- 11 added
- 22 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/Makefile.am
r813dfd86 r295dd61 84 84 time.hfa \ 85 85 bits/weakso_locks.hfa \ 86 algorithms/range_iterator.hfa \ 86 87 containers/maybe.hfa \ 87 88 containers/pair.hfa \ -
libcfa/src/concurrency/io.cfa
r813dfd86 r295dd61 33 33 #include <sys/syscall.h> 34 34 #include <sys/eventfd.h> 35 #include <sys/uio.h> 35 36 36 37 #include <linux/io_uring.h> … … 133 134 } 134 135 135 void __cfa_io_flush( processor * proc) {136 bool __cfa_io_flush( processor * proc, int min_comp ) { 136 137 /* paranoid */ verify( ! __preemption_enabled() ); 137 138 /* paranoid */ verify( proc ); … … 141 142 $io_context & ctx = *proc->io.ctx; 142 143 143 // for(i; 2) {144 // unsigned idx = proc->rdq.id + i;145 // cltr->ready_queue.lanes.tscs[idx].tv = -1ull;146 // }147 148 144 __ioarbiter_flush( ctx ); 149 145 150 146 __STATS__( true, io.calls.flush++; ) 151 int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, 0,0, (sigset_t *)0p, _NSIG / 8);147 int ret = syscall( __NR_io_uring_enter, ctx.fd, ctx.sq.to_submit, min_comp, min_comp > 0 ? IORING_ENTER_GETEVENTS : 0, (sigset_t *)0p, _NSIG / 8); 152 148 if( ret < 0 ) { 153 149 switch((int)errno) { … … 157 153 // Update statistics 158 154 __STATS__( false, io.calls.errors.busy ++; ) 159 // for(i; 2) { 160 // unsigned idx = proc->rdq.id + i; 161 // cltr->ready_queue.lanes.tscs[idx].tv = rdtscl(); 162 // } 163 return; 155 return false; 164 156 default: 165 157 abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) ); … … 182 174 183 175 ctx.proc->io.pending = false; 184 185 __cfa_io_drain( proc ); 186 // for(i; 2) { 187 // unsigned idx = proc->rdq.id + i; 188 // cltr->ready_queue.lanes.tscs[idx].tv = rdtscl(); 189 // } 176 ready_schedule_lock(); 177 bool ret = __cfa_io_drain( proc ); 178 ready_schedule_unlock(); 179 return ret; 190 180 } 191 181 … … 291 281 } 292 282 293 294 283 //============================================================================================= 295 284 // submission … … 314 303 ctx->proc->io.dirty = true; 315 304 if(sq.to_submit > 30 || !lazy) { 316 ready_schedule_lock(); 317 __cfa_io_flush( ctx->proc ); 318 ready_schedule_unlock(); 305 __cfa_io_flush( ctx->proc, 0 ); 319 306 } 320 307 } … … 515 502 } 516 503 } 504 505 #if defined(CFA_WITH_IO_URING_IDLE) 506 bool __kernel_read(processor * proc, io_future_t & future, iovec & iov, int fd) { 507 $io_context * ctx = proc->io.ctx; 508 /* paranoid */ verify( ! __preemption_enabled() ); 509 /* paranoid */ verify( proc == __cfaabi_tls.this_processor ); 510 /* paranoid */ verify( ctx ); 511 512 __u32 idx; 513 struct io_uring_sqe * sqe; 514 515 // We can proceed to the fast path 516 if( !__alloc(ctx, &idx, 1) ) return false; 517 518 // Allocation was successful 519 __fill( &sqe, 1, &idx, ctx ); 520 521 sqe->user_data = (uintptr_t)&future; 522 sqe->flags = 0; 523 sqe->fd = fd; 524 sqe->off = 0; 525 sqe->ioprio = 0; 526 sqe->fsync_flags = 0; 527 sqe->__pad2[0] = 0; 528 sqe->__pad2[1] = 0; 529 sqe->__pad2[2] = 0; 530 531 #if defined(CFA_HAVE_IORING_OP_READ) 532 sqe->opcode = IORING_OP_READ; 533 sqe->addr = (uint64_t)iov.iov_base; 534 sqe->len = iov.iov_len; 535 #elif defined(CFA_HAVE_READV) && defined(CFA_HAVE_IORING_OP_READV) 536 sqe->opcode = IORING_OP_READV; 537 sqe->addr = (uintptr_t)&iov; 538 sqe->len = 1; 539 #else 540 #error CFA_WITH_IO_URING_IDLE but none of CFA_HAVE_READV, CFA_HAVE_IORING_OP_READV or CFA_HAVE_IORING_OP_READ defined 541 #endif 542 543 asm volatile("": : :"memory"); 544 545 /* paranoid */ verify( sqe->user_data == (uintptr_t)&future ); 546 __submit( ctx, &idx, 1, true ); 547 548 /* paranoid */ verify( proc == __cfaabi_tls.this_processor ); 549 /* paranoid */ verify( ! __preemption_enabled() ); 550 } 551 #endif 517 552 #endif -
libcfa/src/concurrency/io/setup.cfa
r813dfd86 r295dd61 32 32 33 33 void __cfa_io_start( processor * proc ) {} 34 void __cfa_io_flush( processor * proc) {}34 bool __cfa_io_flush( processor * proc, int ) {} 35 35 void __cfa_io_stop ( processor * proc ) {} 36 36 … … 111 111 this.ext_sq.empty = true; 112 112 (this.ext_sq.queue){}; 113 __io_uring_setup( this, cl.io.params, proc->idle );113 __io_uring_setup( this, cl.io.params, proc->idle_fd ); 114 114 __cfadbg_print_safe(io_core, "Kernel I/O : Created ring for io_context %u (%p)\n", this.fd, &this); 115 115 } … … 220 220 cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes); 221 221 222 // Step 4 : eventfd 223 // io_uring_register is so f*cking slow on some machine that it 224 // will never succeed if preemption isn't hard blocked 225 __cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd); 226 227 __disable_interrupts_hard(); 228 229 int ret = syscall( __NR_io_uring_register, fd, IORING_REGISTER_EVENTFD, &procfd, 1); 230 if (ret < 0) { 231 abort("KERNEL ERROR: IO_URING EVENTFD REGISTER - %s\n", strerror(errno)); 232 } 233 234 __enable_interrupts_hard(); 235 236 __cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd); 222 #if !defined(CFA_WITH_IO_URING_IDLE) 223 // Step 4 : eventfd 224 // io_uring_register is so f*cking slow on some machine that it 225 // will never succeed if preemption isn't hard blocked 226 __cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd); 227 228 __disable_interrupts_hard(); 229 230 int ret = syscall( __NR_io_uring_register, fd, IORING_REGISTER_EVENTFD, &procfd, 1); 231 if (ret < 0) { 232 abort("KERNEL ERROR: IO_URING EVENTFD REGISTER - %s\n", strerror(errno)); 233 } 234 235 __enable_interrupts_hard(); 236 237 __cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd); 238 #endif 237 239 238 240 // some paranoid checks -
libcfa/src/concurrency/io/types.hfa
r813dfd86 r295dd61 185 185 186 186 // Wait for the future to be fulfilled 187 bool wait( io_future_t & this ) { 188 return wait(this.self); 189 } 190 191 void reset( io_future_t & this ) { 192 return reset(this.self); 193 } 187 bool wait ( io_future_t & this ) { return wait (this.self); } 188 void reset ( io_future_t & this ) { return reset (this.self); } 189 bool available( io_future_t & this ) { return available(this.self); } 194 190 } -
libcfa/src/concurrency/kernel.cfa
r813dfd86 r295dd61 27 27 extern "C" { 28 28 #include <sys/eventfd.h> 29 #include <sys/uio.h> 29 30 } 30 31 … … 34 35 #include "strstream.hfa" 35 36 #include "device/cpu.hfa" 37 #include "io/types.hfa" 36 38 37 39 //Private includes … … 124 126 static void __wake_one(cluster * cltr); 125 127 128 static void idle_sleep(processor * proc, io_future_t & future, iovec & iov); 126 129 static bool mark_idle (__cluster_proc_list & idles, processor & proc); 127 130 static void mark_awake(__cluster_proc_list & idles, processor & proc); … … 129 132 extern void __cfa_io_start( processor * ); 130 133 extern bool __cfa_io_drain( processor * ); 131 extern void __cfa_io_flush( processor *);134 extern bool __cfa_io_flush( processor *, int min_comp ); 132 135 extern void __cfa_io_stop ( processor * ); 133 136 static inline bool __maybe_io_drain( processor * ); 137 138 #if defined(CFA_WITH_IO_URING_IDLE) 139 extern bool __kernel_read(processor * proc, io_future_t & future, iovec &, int fd); 140 #endif 134 141 135 142 extern void __disable_interrupts_hard(); … … 147 154 /* paranoid */ verify( __preemption_enabled() ); 148 155 } 156 149 157 150 158 //============================================================================================= … … 162 170 verify(this); 163 171 172 io_future_t future; // used for idle sleep when io_uring is present 173 future.self.ptr = 1p; // mark it as already fulfilled so we know if there is a pending request or not 174 eventfd_t idle_val; 175 iovec idle_iovec = { &idle_val, sizeof(idle_val) }; 176 164 177 __cfa_io_start( this ); 165 178 … … 195 208 196 209 if( !readyThread ) { 197 ready_schedule_lock(); 198 __cfa_io_flush( this ); 199 ready_schedule_unlock(); 210 __cfa_io_flush( this, 0 ); 200 211 201 212 readyThread = __next_thread_slow( this->cltr ); … … 228 239 } 229 240 230 #if !defined(__CFA_NO_STATISTICS__) 231 if(this->print_halts) { 232 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); 241 idle_sleep( this, future, idle_iovec ); 242 243 // We were woken up, remove self from idle 244 mark_awake(this->cltr->procs, * this); 245 246 // DON'T just proceed, start looking again 247 continue MAIN_LOOP; 248 } 249 250 /* paranoid */ verify( readyThread ); 251 252 // Reset io dirty bit 253 this->io.dirty = false; 254 255 // We found a thread run it 256 __run_thread(this, readyThread); 257 258 // Are we done? 259 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP; 260 261 if(this->io.pending && !this->io.dirty) { 262 __cfa_io_flush( this, 0 ); 263 } 264 265 #else 266 #warning new kernel loop 267 SEARCH: { 268 /* paranoid */ verify( ! __preemption_enabled() ); 269 270 // First, lock the scheduler since we are searching for a thread 271 ready_schedule_lock(); 272 273 // Try to get the next thread 274 readyThread = pop_fast( this->cltr ); 275 if(readyThread) { ready_schedule_unlock(); break SEARCH; } 276 277 // If we can't find a thread, might as well flush any outstanding I/O 278 if(this->io.pending) { __cfa_io_flush( this, 0 ); } 279 280 // Spin a little on I/O, just in case 281 for(5) { 282 __maybe_io_drain( this ); 283 readyThread = pop_fast( this->cltr ); 284 if(readyThread) { ready_schedule_unlock(); break SEARCH; } 285 } 286 287 // no luck, try stealing a few times 288 for(5) { 289 if( __maybe_io_drain( this ) ) { 290 readyThread = pop_fast( this->cltr ); 291 } else { 292 readyThread = pop_slow( this->cltr ); 233 293 } 234 #endif 235 236 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle); 294 if(readyThread) { ready_schedule_unlock(); break SEARCH; } 295 } 296 297 // still no luck, search for a thread 298 readyThread = pop_search( this->cltr ); 299 if(readyThread) { ready_schedule_unlock(); break SEARCH; } 300 301 // Don't block if we are done 302 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) { 303 ready_schedule_unlock(); 304 break MAIN_LOOP; 305 } 306 307 __STATS( __tls_stats()->ready.sleep.halts++; ) 308 309 // Push self to idle stack 310 ready_schedule_unlock(); 311 if(!mark_idle(this->cltr->procs, * this)) goto SEARCH; 312 ready_schedule_lock(); 313 314 // Confirm the ready-queue is empty 315 __maybe_io_drain( this ); 316 readyThread = pop_search( this->cltr ); 317 ready_schedule_unlock(); 318 319 if( readyThread ) { 320 // A thread was found, cancel the halt 321 mark_awake(this->cltr->procs, * this); 322 323 __STATS( __tls_stats()->ready.sleep.cancels++; ) 324 325 // continue the main loop 326 break SEARCH; 327 } 328 329 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); ) 330 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd); 237 331 238 332 { 239 333 eventfd_t val; 240 ssize_t ret = read( this->idle , &val, sizeof(val) );334 ssize_t ret = read( this->idle_fd, &val, sizeof(val) ); 241 335 if(ret < 0) { 242 336 switch((int)errno) { … … 254 348 } 255 349 256 #if !defined(__CFA_NO_STATISTICS__) 257 if(this->print_halts) { 258 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); 259 } 260 #endif 350 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); ) 261 351 262 352 // We were woken up, remove self from idle … … 267 357 } 268 358 269 /* paranoid */ verify( readyThread );270 271 // Reset io dirty bit272 this->io.dirty = false;273 274 // We found a thread run it275 __run_thread(this, readyThread);276 277 // Are we done?278 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) break MAIN_LOOP;279 280 if(this->io.pending && !this->io.dirty) {281 ready_schedule_lock();282 __cfa_io_flush( this );283 ready_schedule_unlock();284 }285 286 #else287 #warning new kernel loop288 SEARCH: {289 /* paranoid */ verify( ! __preemption_enabled() );290 291 // First, lock the scheduler since we are searching for a thread292 ready_schedule_lock();293 294 // Try to get the next thread295 readyThread = pop_fast( this->cltr );296 if(readyThread) { ready_schedule_unlock(); break SEARCH; }297 298 // If we can't find a thread, might as well flush any outstanding I/O299 if(this->io.pending) { __cfa_io_flush( this ); }300 301 // Spin a little on I/O, just in case302 for(5) {303 __maybe_io_drain( this );304 readyThread = pop_fast( this->cltr );305 if(readyThread) { ready_schedule_unlock(); break SEARCH; }306 }307 308 // no luck, try stealing a few times309 for(5) {310 if( __maybe_io_drain( this ) ) {311 readyThread = pop_fast( this->cltr );312 } else {313 readyThread = pop_slow( this->cltr );314 }315 if(readyThread) { ready_schedule_unlock(); break SEARCH; }316 }317 318 // still no luck, search for a thread319 readyThread = pop_search( this->cltr );320 if(readyThread) { ready_schedule_unlock(); break SEARCH; }321 322 // Don't block if we are done323 if( __atomic_load_n(&this->do_terminate, __ATOMIC_SEQ_CST) ) {324 ready_schedule_unlock();325 break MAIN_LOOP;326 }327 328 __STATS( __tls_stats()->ready.sleep.halts++; )329 330 // Push self to idle stack331 ready_schedule_unlock();332 if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;333 ready_schedule_lock();334 335 // Confirm the ready-queue is empty336 __maybe_io_drain( this );337 readyThread = pop_search( this->cltr );338 ready_schedule_unlock();339 340 if( readyThread ) {341 // A thread was found, cancel the halt342 mark_awake(this->cltr->procs, * this);343 344 __STATS( __tls_stats()->ready.sleep.cancels++; )345 346 // continue the main loop347 break SEARCH;348 }349 350 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); )351 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle);352 353 {354 eventfd_t val;355 ssize_t ret = read( this->idle, &val, sizeof(val) );356 if(ret < 0) {357 switch((int)errno) {358 case EAGAIN:359 #if EAGAIN != EWOULDBLOCK360 case EWOULDBLOCK:361 #endif362 case EINTR:363 // No need to do anything special here, just assume it's a legitimate wake-up364 break;365 default:366 abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) );367 }368 }369 }370 371 __STATS( if(this->print_halts) __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); )372 373 // We were woken up, remove self from idle374 mark_awake(this->cltr->procs, * this);375 376 // DON'T just proceed, start looking again377 continue MAIN_LOOP;378 }379 380 359 RUN_THREAD: 381 360 /* paranoid */ verify( ! __preemption_enabled() ); … … 392 371 393 372 if(this->io.pending && !this->io.dirty) { 394 __cfa_io_flush( this );373 __cfa_io_flush( this, 0 ); 395 374 } 396 375 … … 402 381 403 382 __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this); 383 } 384 385 for(int i = 0; !available(future); i++) { 386 if(i > 1000) __cfaabi_dbg_write( "ERROR: kernel has bin spinning on a flush after exit loop.\n", 60); 387 __cfa_io_flush( this, 1 ); 404 388 } 405 389 … … 798 782 eventfd_t val; 799 783 val = 1; 800 eventfd_write( this->idle , val );784 eventfd_write( this->idle_fd, val ); 801 785 __enable_interrupts_checked(); 786 } 787 788 static void idle_sleep(processor * this, io_future_t & future, iovec & iov) { 789 #if !defined(CFA_WITH_IO_URING_IDLE) 790 #if !defined(__CFA_NO_STATISTICS__) 791 if(this->print_halts) { 792 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 0\n", this->unique_id, rdtscl()); 793 } 794 #endif 795 796 __cfadbg_print_safe(runtime_core, "Kernel : core %p waiting on eventfd %d\n", this, this->idle_fd); 797 798 { 799 eventfd_t val; 800 ssize_t ret = read( this->idle_fd, &val, sizeof(val) ); 801 if(ret < 0) { 802 switch((int)errno) { 803 case EAGAIN: 804 #if EAGAIN != EWOULDBLOCK 805 case EWOULDBLOCK: 806 #endif 807 case EINTR: 808 // No need to do anything special here, just assume it's a legitimate wake-up 809 break; 810 default: 811 abort( "KERNEL : internal error, read failure on idle eventfd, error(%d) %s.", (int)errno, strerror( (int)errno ) ); 812 } 813 } 814 } 815 816 #if !defined(__CFA_NO_STATISTICS__) 817 if(this->print_halts) { 818 __cfaabi_bits_print_safe( STDOUT_FILENO, "PH:%d - %lld 1\n", this->unique_id, rdtscl()); 819 } 820 #endif 821 #else 822 // Do we already have a pending read 823 if(available(future)) { 824 // There is no pending read, we need to add one 825 reset(future); 826 827 __kernel_read(this, future, iov, this->idle_fd ); 828 } 829 830 __cfa_io_flush( this, 1 ); 831 #endif 802 832 } 803 833 … … 810 840 insert_first(this.idles, proc); 811 841 812 __atomic_store_n(&this.fd, proc.idle , __ATOMIC_SEQ_CST);842 __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST); 813 843 unlock( this ); 814 844 /* paranoid */ verify( ! __preemption_enabled() ); … … 827 857 { 828 858 int fd = 0; 829 if(!this.idles`isEmpty) fd = this.idles`first.idle ;859 if(!this.idles`isEmpty) fd = this.idles`first.idle_fd; 830 860 __atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST); 831 861 } -
libcfa/src/concurrency/kernel.hfa
r813dfd86 r295dd61 100 100 101 101 // Idle lock (kernel semaphore) 102 int idle ;102 int idle_fd; 103 103 104 104 // Termination synchronisation (user semaphore) -
libcfa/src/concurrency/kernel/startup.cfa
r813dfd86 r295dd61 527 527 this.local_data = 0p; 528 528 529 this.idle = eventfd(0, 0);530 if (idle < 0) {529 this.idle_fd = eventfd(0, 0); 530 if (idle_fd < 0) { 531 531 abort("KERNEL ERROR: PROCESSOR EVENTFD - %s\n", strerror(errno)); 532 532 } … … 542 542 // Not a ctor, it just preps the destruction but should not destroy members 543 543 static void deinit(processor & this) { 544 close(this.idle );544 close(this.idle_fd); 545 545 } 546 546 -
libcfa/src/concurrency/kernel_private.hfa
r813dfd86 r295dd61 39 39 } 40 40 41 // Defines whether or not we *want* to use io_uring_enter as the idle_sleep blocking call 42 #define CFA_WANT_IO_URING_IDLE 43 44 // Defines whether or not we *can* use io_uring_enter as the idle_sleep blocking call 45 #if defined(CFA_WANT_IO_URING_IDLE) && defined(CFA_HAVE_LINUX_IO_URING_H) 46 #if defined(CFA_HAVE_IORING_OP_READ) || (defined(CFA_HAVE_READV) && defined(CFA_HAVE_IORING_OP_READV)) 47 #define CFA_WITH_IO_URING_IDLE 48 #endif 49 #endif 50 41 51 //----------------------------------------------------------------------------- 42 52 // Scheduler … … 149 159 __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE); 150 160 } 151 152 153 154 155 161 156 162 //----------------------------------------------------------------------- -
libcfa/src/device/cpu.cfa
r813dfd86 r295dd61 135 135 count++; 136 136 } 137 iterate_dir(path, lambda); 137 int ret = iterate_dir(path, lambda); 138 if(ret == ENOTDIR) return 0; 138 139 139 140 /* paranoid */ verifyf(count == max + 1, "Inconsistent %s count, counted %d, but max %s was %d", prefix, count, prefix, (int)max); … … 159 160 160 161 const char * _; 161 int cnt = read_width(buff, r - 1, &_); 162 /* paranoid */ verify(cnt == count_prefix_dirs("/sys/devices/system/cpu", "cpu")); 163 return cnt; 162 return read_width(buff, r - 1, &_);; 164 163 } 165 164 … … 226 225 227 226 struct raw_cache_instance { 228 idx_range_t range; 229 unsigned width; 230 unsigned char level; 227 idx_range_t range; // A text description of the cpus covered 228 unsigned width; // The number of cpus covered 229 unsigned char level; // the cache level 231 230 // FIXME add at least size and type 232 231 }; … … 235 234 static void ^?{}(raw_cache_instance & this) { free(this.range);} 236 235 236 // Returns a 2D array of instances of size [cpu count][cache levels] 237 // where cache level doesn't include instruction caches 237 238 raw_cache_instance ** build_raw_cache_table(unsigned cpus, unsigned idxs, unsigned cache_levels) 238 239 { 239 240 raw_cache_instance ** raw = alloc(cpus); 241 242 // TODO: this loop is broken, it only works if the present cpu start at 0 and are contiguous which is not guaranteed. 240 243 for(i; cpus) { 241 raw[i] = alloc(cache_levels); 242 void addcache(unsigned fidx, unsigned char level, idx_range_t range, size_t len) { 243 /* paranoid */ verifyf(level <= cache_levels, "Unexpected cache level %d on cpu %u index %u", (int)level, i, fidx); 244 245 unsigned idx = cache_levels - level; 246 raw_cache_instance & r = raw[i][idx]; 247 r.range = strndup(range, len); 248 r.level = level; 249 const char * end; 250 r.width = read_width(range, len, &end); 251 } 252 foreach_cacheidx(i, idxs, addcache); 244 if (cache_levels > 0) { 245 raw[i] = alloc(cache_levels); 246 void addcache(unsigned fidx, unsigned char level, idx_range_t range, size_t len) { 247 /* paranoid */ verifyf(level <= cache_levels, "Unexpected cache level %d on cpu %u index %u", (int)level, i, fidx); 248 249 unsigned idx = cache_levels - level; 250 raw_cache_instance & r = raw[i][idx]; 251 r.range = strndup(range, len); 252 r.level = level; 253 const char * end; 254 r.width = read_width(range, len, &end); 255 } 256 foreach_cacheidx(i, idxs, addcache); 257 } 258 else { 259 char buf[128]; 260 snprintf(buf, 128, "0-%u", cpus); 261 raw[i] = alloc(); 262 raw[i]->range = strndup(buf, 128); 263 raw[i]->level = 0; 264 raw[i]->width = cpus; 265 } 253 266 } 254 267 … … 333 346 unsigned cache_levels = 0; 334 347 unsigned llc = 0; 335 {348 if (idxs != 0) { 336 349 unsigned char prev = -1u; 337 350 void first(unsigned idx, unsigned char level, const char * map, size_t len) { … … 416 429 cpu_info.llc_map = entries; 417 430 cpu_info.hthrd_count = cpus; 431 cpu_info.llc_count = map_cnt; 418 432 } 419 433 -
libcfa/src/device/cpu.hfa
r813dfd86 r295dd61 23 23 24 24 struct cpu_info_t { 25 // array of size [hthrd_count]25 // Array of size [hthrd_count] 26 26 const cpu_map_entry_t * llc_map; 27 27 28 28 // Number of _hardware_ threads present in the system 29 29 size_t hthrd_count; 30 31 // Number of distinct last level caches 32 size_t llc_count; 30 33 }; 31 34 -
src/AST/Decl.hpp
r813dfd86 r295dd61 270 270 : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {} 271 271 272 bool is_coroutine() { return kind == Coroutine; }273 bool is_generator() { return kind == Generator; }274 bool is_monitor () { return kind == Monitor ; }275 bool is_thread () { return kind == Thread ; }272 bool is_coroutine() const { return kind == Coroutine; } 273 bool is_generator() const { return kind == Generator; } 274 bool is_monitor () const { return kind == Monitor ; } 275 bool is_thread () const { return kind == Thread ; } 276 276 277 277 const Decl * accept( Visitor & v ) const override { return v.visit( this ); } -
src/AST/Expr.cpp
r813dfd86 r295dd61 9 9 // Author : Aaron B. Moss 10 10 // Created On : Wed May 15 17:00:00 2019 11 // Last Modified By : Peter A. Buhr12 // Created On : T hr Jun 13 13:38:00 201913 // Update Count : 611 // Last Modified By : Andrew Beach 12 // Created On : Tue Nov 30 14:23:00 2021 13 // Update Count : 7 14 14 // 15 15 … … 141 141 /// The type of the address of a type. 142 142 /// Caller is responsible for managing returned memory 143 Type * addrType( const Type *type ) {144 if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * >( type) ) {145 return new ReferenceType { addrType( refType->base ), refType->qualifiers };143 Type * addrType( const ptr<Type> & type ) { 144 if ( auto refType = type.as< ReferenceType >() ) { 145 return new ReferenceType( addrType( refType->base ), refType->qualifiers ); 146 146 } else { 147 return new PointerType { type };147 return new PointerType( type ); 148 148 } 149 149 } 150 } 151 152 AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : Expr( loc ), arg( a ) { 153 if ( arg->result ) { 154 if ( arg->get_lvalue() ) { 155 // lvalue, retains all levels of reference, and gains a pointer inside the references 156 Type * res = addrType( arg->result ); 157 result = res; 150 151 /// The type of the address of an expression. 152 /// Caller is responsible for managing returned memory 153 Type * addrExprType( const CodeLocation & loc, const Expr * arg ) { 154 assert( arg ); 155 // If the expression's type is unknown, the address type is unknown. 156 if ( nullptr == arg->result ) { 157 return nullptr; 158 // An lvalue is transformed directly. 159 } else if ( arg->get_lvalue() ) { 160 return addrType( arg->result ); 161 // Strip a layer of reference to "create" an lvalue expression. 162 } else if ( auto refType = arg->result.as< ReferenceType >() ) { 163 return addrType( refType->base ); 158 164 } else { 159 // taking address of non-lvalue, must be a reference, loses one layer of reference 160 if ( const ReferenceType * refType = 161 dynamic_cast< const ReferenceType * >( arg->result.get() ) ) { 162 Type * res = addrType( refType->base ); 163 result = res; 164 } else { 165 SemanticError( loc, arg->result.get(), 166 "Attempt to take address of non-lvalue expression: " ); 167 } 165 SemanticError( loc, arg->result.get(), 166 "Attempt to take address of non-lvalue expression: " ); 168 167 } 169 168 } 170 169 } 170 171 AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) : 172 Expr( loc, addrExprType( loc, a ) ), arg( a ) 173 {} 171 174 172 175 // --- LabelAddressExpr -
src/AST/Print.cpp
r813dfd86 r295dd61 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Print.cpp -- 7 // Print.cpp -- Print an AST (or sub-tree) to a stream. 8 8 // 9 9 // Author : Thierry Delisle -
src/AST/Print.hpp
r813dfd86 r295dd61 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Print.hpp -- 7 // Print.hpp -- Print an AST (or sub-tree) to a stream. 8 8 // 9 9 // Author : Thierry Delisle … … 35 35 template< typename Coll > 36 36 void printAll( std::ostream & os, const Coll & c, Indenter indent = {} ) { 37 38 39 40 41 42 43 37 for ( const auto & i : c ) { 38 if ( ! i ) continue; 39 40 os << indent; 41 print( os, i, indent ); 42 os << std::endl; 43 } 44 44 } 45 45 -
src/Concurrency/Keywords.cc
r813dfd86 r295dd61 979 979 // If this is the destructor for a monitor it must be mutex 980 980 if(isDtor) { 981 // This reflects MutexKeyword::validate, except does not produce an error. 981 982 Type* ty = decl->get_functionType()->get_parameters().front()->get_type(); 982 983 -
src/Concurrency/Keywords.h
r813dfd86 r295dd61 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Keywords.h -- 7 // Keywords.h -- Implement concurrency constructs from their keywords. 8 8 // 9 9 // Author : Thierry Delisle … … 19 19 20 20 class Declaration; 21 namespace ast { 22 class TranslationUnit; 23 } 21 24 22 25 namespace Concurrency { … … 24 27 void implementMutexFuncs( std::list< Declaration * > & translationUnit ); 25 28 void implementThreadStarter( std::list< Declaration * > & translationUnit ); 29 30 /// Implement the sue-like keywords and the suspend keyword. 31 void implementKeywords( ast::TranslationUnit & translationUnit ); 32 /// Implement the mutex parameters and mutex statement. 33 void implementMutex( ast::TranslationUnit & translationUnit ); 34 /// Add the thread starter code to constructors. 35 void implementThreadStarter( ast::TranslationUnit & translationUnit ); 26 36 }; 27 37 -
src/Concurrency/module.mk
r813dfd86 r295dd61 15 15 ############################################################################### 16 16 17 SRC += Concurrency/Keywords.cc Concurrency/Keywords.h Concurrency/Waitfor.cc Concurrency/Waitfor.h 18 SRCDEMANGLE += Concurrency/Keywords.cc 17 SRC_CONCURRENCY = \ 18 Concurrency/KeywordsNew.cpp \ 19 Concurrency/Keywords.cc 19 20 21 SRC += $(SRC_CONCURRENCY) \ 22 Concurrency/Keywords.h \ 23 Concurrency/Waitfor.cc \ 24 Concurrency/Waitfor.h 25 26 SRCDEMANGLE += $(SRC_CONCURRENCY) 27 -
src/InitTweak/InitTweak.cc
r813dfd86 r295dd61 9 9 // Author : Rob Schluntz 10 10 // Created On : Fri May 13 11:26:36 2016 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Wed Jun 16 20:57:22202113 // Update Count : 1 811 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Nov 19 19:22:00 2021 13 // Update Count : 19 14 14 // 15 15 … … 540 540 } 541 541 542 const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) { 543 assertf( ftype, "getTypeofThis: nullptr ftype" ); 544 const std::vector<ast::ptr<ast::Type>> & params = ftype->params; 545 assertf( !params.empty(), "getTypeofThis: ftype with 0 parameters: %s", 546 toString( ftype ).c_str() ); 547 const ast::ReferenceType * refType = 548 params.front().strict_as<ast::ReferenceType>(); 549 return refType->base; 550 } 551 542 552 ObjectDecl * getParamThis( FunctionType * ftype ) { 543 553 assertf( ftype, "getParamThis: nullptr ftype" ); -
src/InitTweak/InitTweak.h
r813dfd86 r295dd61 10 10 // Created On : Fri May 13 11:26:36 2016 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Jul 19 14:18:00 201913 // Update Count : 612 // Last Modified On : Fri Nov 19 14:18:00 2021 13 // Update Count : 7 14 14 // 15 15 … … 35 35 /// returns the base type of the first parameter to a constructor/destructor/assignment function 36 36 Type * getTypeofThis( FunctionType * ftype ); 37 const ast::Type * getTypeofThis( const ast::FunctionType * ftype ); 37 38 38 39 /// returns the first parameter of a constructor/destructor/assignment function -
src/Validate/module.mk
r813dfd86 r295dd61 16 16 17 17 SRC_VALIDATE = \ 18 Validate/CompoundLiteral.cpp \ 19 Validate/CompoundLiteral.hpp \ 18 20 Validate/HandleAttributes.cc \ 19 21 Validate/HandleAttributes.h \ -
src/main.cc
r813dfd86 r295dd61 10 10 // Created On : Fri May 15 23:12:02 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Nov 12 11:06:00 202113 // Update Count : 65 812 // Last Modified On : Tue Nov 30 10:25:00 2021 13 // Update Count : 659 14 14 // 15 15 … … 50 50 #include "Common/UnimplementedError.h" // for UnimplementedError 51 51 #include "Common/utility.h" // for deleteAll, filter, printAll 52 #include "Concurrency/Keywords.h" // for implementMutex, implement... 52 53 #include "Concurrency/Waitfor.h" // for generateWaitfor 53 54 #include "ControlStruct/ExceptDecl.h" // for translateExcept … … 73 74 #include "Tuples/Tuples.h" // for expandMemberTuples, expan... 74 75 #include "Validate/FindSpecialDecls.h" // for findGlobalDecls 76 #include "Validate/CompoundLiteral.hpp" // for handleCompoundLiterals 75 77 #include "Validate/InitializerLength.hpp" // for setLengthFromInitializer 76 78 #include "Validate/LabelAddressFixer.hpp" // for fixLabelAddresses … … 325 327 PASS( "Validate-C", SymTab::validate_C( translationUnit ) ); 326 328 PASS( "Validate-D", SymTab::validate_D( translationUnit ) ); 327 PASS( "Validate-E", SymTab::validate_E( translationUnit ) );328 329 329 330 CodeTools::fillLocations( translationUnit ); … … 338 339 forceFillCodeLocations( transUnit ); 339 340 341 PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) ); 342 PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) ); 343 PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) ); 340 344 PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) ); 341 345 PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) ); … … 402 406 translationUnit = convert( move( transUnit ) ); 403 407 } else { 408 PASS( "Validate-E", SymTab::validate_E( translationUnit ) ); 404 409 PASS( "Validate-F", SymTab::validate_F( translationUnit ) ); 405 410 -
tests/pybin/tools.py
r813dfd86 r295dd61 374 374 375 375 if not os.path.isfile(core): 376 return 1, "ERR No core dump "376 return 1, "ERR No core dump (limit soft: {} hard: {})".format(*resource.getrlimit(resource.RLIMIT_CORE)) 377 377 378 378 try:
Note: See TracChangeset
for help on using the changeset viewer.