Changeset 295dd61


Ignore:
Timestamp:
Dec 6, 2021, 5:06:14 PM (6 weeks ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
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.
Message:

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

Files:
11 added
22 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/Makefile.am

    r813dfd86 r295dd61  
    8484        time.hfa \
    8585        bits/weakso_locks.hfa \
     86        algorithms/range_iterator.hfa \
    8687        containers/maybe.hfa \
    8788        containers/pair.hfa \
  • libcfa/src/concurrency/io.cfa

    r813dfd86 r295dd61  
    3333                #include <sys/syscall.h>
    3434                #include <sys/eventfd.h>
     35                #include <sys/uio.h>
    3536
    3637                #include <linux/io_uring.h>
     
    133134        }
    134135
    135         void __cfa_io_flush( processor * proc ) {
     136        bool __cfa_io_flush( processor * proc, int min_comp ) {
    136137                /* paranoid */ verify( ! __preemption_enabled() );
    137138                /* paranoid */ verify( proc );
     
    141142                $io_context & ctx = *proc->io.ctx;
    142143
    143                 // for(i; 2) {
    144                 //      unsigned idx = proc->rdq.id + i;
    145                 //      cltr->ready_queue.lanes.tscs[idx].tv = -1ull;
    146                 // }
    147 
    148144                __ioarbiter_flush( ctx );
    149145
    150146                __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);
    152148                if( ret < 0 ) {
    153149                        switch((int)errno) {
     
    157153                                // Update statistics
    158154                                __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;
    164156                        default:
    165157                                abort( "KERNEL ERROR: IO_URING SYSCALL - (%d) %s\n", (int)errno, strerror(errno) );
     
    182174
    183175                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;
    190180        }
    191181
     
    291281        }
    292282
    293 
    294283        //=============================================================================================
    295284        // submission
     
    314303                ctx->proc->io.dirty   = true;
    315304                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 );
    319306                }
    320307        }
     
    515502                }
    516503        }
     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
    517552#endif
  • libcfa/src/concurrency/io/setup.cfa

    r813dfd86 r295dd61  
    3232
    3333        void __cfa_io_start( processor * proc ) {}
    34         void __cfa_io_flush( processor * proc ) {}
     34        bool __cfa_io_flush( processor * proc, int ) {}
    3535        void __cfa_io_stop ( processor * proc ) {}
    3636
     
    111111                this.ext_sq.empty = true;
    112112                (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 );
    114114                __cfadbg_print_safe(io_core, "Kernel I/O : Created ring for io_context %u (%p)\n", this.fd, &this);
    115115        }
     
    220220                cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
    221221
    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
    237239
    238240                // some paranoid checks
  • libcfa/src/concurrency/io/types.hfa

    r813dfd86 r295dd61  
    185185
    186186        // 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); }
    194190}
  • libcfa/src/concurrency/kernel.cfa

    r813dfd86 r295dd61  
    2727extern "C" {
    2828        #include <sys/eventfd.h>
     29        #include <sys/uio.h>
    2930}
    3031
     
    3435#include "strstream.hfa"
    3536#include "device/cpu.hfa"
     37#include "io/types.hfa"
    3638
    3739//Private includes
     
    124126static void __wake_one(cluster * cltr);
    125127
     128static void idle_sleep(processor * proc, io_future_t & future, iovec & iov);
    126129static bool mark_idle (__cluster_proc_list & idles, processor & proc);
    127130static void mark_awake(__cluster_proc_list & idles, processor & proc);
     
    129132extern void __cfa_io_start( processor * );
    130133extern bool __cfa_io_drain( processor * );
    131 extern void __cfa_io_flush( processor * );
     134extern bool __cfa_io_flush( processor *, int min_comp );
    132135extern void __cfa_io_stop ( processor * );
    133136static 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
    134141
    135142extern void __disable_interrupts_hard();
     
    147154        /* paranoid */ verify( __preemption_enabled() );
    148155}
     156
    149157
    150158//=============================================================================================
     
    162170        verify(this);
    163171
     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
    164177        __cfa_io_start( this );
    165178
     
    195208
    196209                        if( !readyThread ) {
    197                                 ready_schedule_lock();
    198                                 __cfa_io_flush( this );
    199                                 ready_schedule_unlock();
     210                                __cfa_io_flush( this, 0 );
    200211
    201212                                readyThread = __next_thread_slow( this->cltr );
     
    228239                                }
    229240
    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 );
    233293                                        }
    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);
    237331
    238332                                {
    239333                                        eventfd_t val;
    240                                         ssize_t ret = read( this->idle, &val, sizeof(val) );
     334                                        ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
    241335                                        if(ret < 0) {
    242336                                                switch((int)errno) {
     
    254348                                }
    255349
    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()); )
    261351
    262352                                // We were woken up, remove self from idle
     
    267357                        }
    268358
    269                         /* paranoid */ verify( readyThread );
    270 
    271                         // Reset io dirty bit
    272                         this->io.dirty = false;
    273 
    274                         // We found a thread run it
    275                         __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                         #else
    287                                 #warning new kernel loop
    288                         SEARCH: {
    289                                 /* paranoid */ verify( ! __preemption_enabled() );
    290 
    291                                 // First, lock the scheduler since we are searching for a thread
    292                                 ready_schedule_lock();
    293 
    294                                 // Try to get the next thread
    295                                 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/O
    299                                 if(this->io.pending) { __cfa_io_flush( this ); }
    300 
    301                                 // Spin a little on I/O, just in case
    302                                 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 times
    309                                 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 thread
    319                                 readyThread = pop_search( this->cltr );
    320                                 if(readyThread) { ready_schedule_unlock(); break SEARCH; }
    321 
    322                                 // Don't block if we are done
    323                                 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 stack
    331                                 ready_schedule_unlock();
    332                                 if(!mark_idle(this->cltr->procs, * this)) goto SEARCH;
    333                                 ready_schedule_lock();
    334 
    335                                 // Confirm the ready-queue is empty
    336                                 __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 halt
    342                                         mark_awake(this->cltr->procs, * this);
    343 
    344                                         __STATS( __tls_stats()->ready.sleep.cancels++; )
    345 
    346                                         // continue the main loop
    347                                         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 != EWOULDBLOCK
    360                                                         case EWOULDBLOCK:
    361                                                 #endif
    362                                                 case EINTR:
    363                                                         // No need to do anything special here, just assume it's a legitimate wake-up
    364                                                         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 idle
    374                                 mark_awake(this->cltr->procs, * this);
    375 
    376                                 // DON'T just proceed, start looking again
    377                                 continue MAIN_LOOP;
    378                         }
    379 
    380359                RUN_THREAD:
    381360                        /* paranoid */ verify( ! __preemption_enabled() );
     
    392371
    393372                        if(this->io.pending && !this->io.dirty) {
    394                                 __cfa_io_flush( this );
     373                                __cfa_io_flush( this, 0 );
    395374                        }
    396375
     
    402381
    403382                __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 );
    404388        }
    405389
     
    798782                eventfd_t val;
    799783                val = 1;
    800                 eventfd_write( this->idle, val );
     784                eventfd_write( this->idle_fd, val );
    801785        __enable_interrupts_checked();
     786}
     787
     788static 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
    802832}
    803833
     
    810840                insert_first(this.idles, proc);
    811841
    812                 __atomic_store_n(&this.fd, proc.idle, __ATOMIC_SEQ_CST);
     842                __atomic_store_n(&this.fd, proc.idle_fd, __ATOMIC_SEQ_CST);
    813843        unlock( this );
    814844        /* paranoid */ verify( ! __preemption_enabled() );
     
    827857                {
    828858                        int fd = 0;
    829                         if(!this.idles`isEmpty) fd = this.idles`first.idle;
     859                        if(!this.idles`isEmpty) fd = this.idles`first.idle_fd;
    830860                        __atomic_store_n(&this.fd, fd, __ATOMIC_SEQ_CST);
    831861                }
  • libcfa/src/concurrency/kernel.hfa

    r813dfd86 r295dd61  
    100100
    101101        // Idle lock (kernel semaphore)
    102         int idle;
     102        int idle_fd;
    103103
    104104        // Termination synchronisation (user semaphore)
  • libcfa/src/concurrency/kernel/startup.cfa

    r813dfd86 r295dd61  
    527527        this.local_data = 0p;
    528528
    529         this.idle = eventfd(0, 0);
    530         if (idle < 0) {
     529        this.idle_fd = eventfd(0, 0);
     530        if (idle_fd < 0) {
    531531                abort("KERNEL ERROR: PROCESSOR EVENTFD - %s\n", strerror(errno));
    532532        }
     
    542542// Not a ctor, it just preps the destruction but should not destroy members
    543543static void deinit(processor & this) {
    544         close(this.idle);
     544        close(this.idle_fd);
    545545}
    546546
  • libcfa/src/concurrency/kernel_private.hfa

    r813dfd86 r295dd61  
    3939}
    4040
     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
    4151//-----------------------------------------------------------------------------
    4252// Scheduler
     
    149159        __atomic_store_n(ll, (bool)false, __ATOMIC_RELEASE);
    150160}
    151 
    152 
    153 
    154 
    155161
    156162//-----------------------------------------------------------------------
  • libcfa/src/device/cpu.cfa

    r813dfd86 r295dd61  
    135135                count++;
    136136        }
    137         iterate_dir(path, lambda);
     137        int ret = iterate_dir(path, lambda);
     138        if(ret == ENOTDIR) return 0;
    138139
    139140        /* paranoid */ verifyf(count == max + 1, "Inconsistent %s count, counted %d, but max %s was %d", prefix, count, prefix, (int)max);
     
    159160
    160161        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, &_);;
    164163}
    165164
     
    226225
    227226struct 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
    231230        // FIXME add at least size and type
    232231};
     
    235234static void ^?{}(raw_cache_instance & this) { free(this.range);}
    236235
     236// Returns a 2D array of instances of size [cpu count][cache levels]
     237// where cache level doesn't include instruction caches
    237238raw_cache_instance ** build_raw_cache_table(unsigned cpus, unsigned idxs, unsigned cache_levels)
    238239{
    239240        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.
    240243        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                }
    253266        }
    254267
     
    333346                unsigned cache_levels = 0;
    334347                unsigned llc = 0;
    335                 {
     348                if (idxs != 0) {
    336349                        unsigned char prev = -1u;
    337350                        void first(unsigned idx, unsigned char level, const char * map, size_t len) {
     
    416429                cpu_info.llc_map = entries;
    417430                cpu_info.hthrd_count = cpus;
     431                cpu_info.llc_count = map_cnt;
    418432        }
    419433
  • libcfa/src/device/cpu.hfa

    r813dfd86 r295dd61  
    2323
    2424struct cpu_info_t {
    25          // array of size [hthrd_count]
     25        // Array of size [hthrd_count]
    2626        const cpu_map_entry_t * llc_map;
    2727
    28          // Number of _hardware_ threads present in the system
     28        // Number of _hardware_ threads present in the system
    2929        size_t hthrd_count;
     30
     31        // Number of distinct last level caches
     32        size_t llc_count;
    3033};
    3134
  • src/AST/Decl.hpp

    r813dfd86 r295dd61  
    270270        : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {}
    271271
    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   ; }
    276276
    277277        const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Expr.cpp

    r813dfd86 r295dd61  
    99// Author           : Aaron B. Moss
    1010// Created On       : Wed May 15 17:00:00 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Created On       : Thr Jun 13 13:38:00 2019
    13 // Update Count     : 6
     11// Last Modified By : Andrew Beach
     12// Created On       : Tue Nov 30 14:23:00 2021
     13// Update Count     : 7
    1414//
    1515
     
    141141        /// The type of the address of a type.
    142142        /// 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 );
    146146                } else {
    147                         return new PointerType{ type };
     147                        return new PointerType( type );
    148148                }
    149149        }
    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 );
    158164                } 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: " );
    168167                }
    169168        }
    170169}
     170
     171AddressExpr::AddressExpr( const CodeLocation & loc, const Expr * a ) :
     172        Expr( loc, addrExprType( loc, a ) ), arg( a )
     173{}
    171174
    172175// --- LabelAddressExpr
  • src/AST/Print.cpp

    r813dfd86 r295dd61  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Print.cpp --
     7// Print.cpp -- Print an AST (or sub-tree) to a stream.
    88//
    99// Author           : Thierry Delisle
  • src/AST/Print.hpp

    r813dfd86 r295dd61  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Print.hpp --
     7// Print.hpp -- Print an AST (or sub-tree) to a stream.
    88//
    99// Author           : Thierry Delisle
     
    3535template< typename Coll >
    3636void printAll( std::ostream & os, const Coll & c, Indenter indent = {} ) {
    37     for ( const auto & i : c ) {
    38         if ( ! i ) continue;
    39        
    40         os << indent;
    41         print( os, i, indent );
    42         os << std::endl;
    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        }
    4444}
    4545
  • src/Concurrency/Keywords.cc

    r813dfd86 r295dd61  
    979979                        // If this is the destructor for a monitor it must be mutex
    980980                        if(isDtor) {
     981                                // This reflects MutexKeyword::validate, except does not produce an error.
    981982                                Type* ty = decl->get_functionType()->get_parameters().front()->get_type();
    982983
  • src/Concurrency/Keywords.h

    r813dfd86 r295dd61  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Keywords.h --
     7// Keywords.h -- Implement concurrency constructs from their keywords.
    88//
    99// Author           : Thierry Delisle
     
    1919
    2020class Declaration;
     21namespace ast {
     22        class TranslationUnit;
     23}
    2124
    2225namespace Concurrency {
     
    2427        void implementMutexFuncs( std::list< Declaration * > & translationUnit );
    2528        void implementThreadStarter( std::list< Declaration * > & translationUnit );
     29
     30/// Implement the sue-like keywords and the suspend keyword.
     31void implementKeywords( ast::TranslationUnit & translationUnit );
     32/// Implement the mutex parameters and mutex statement.
     33void implementMutex( ast::TranslationUnit & translationUnit );
     34/// Add the thread starter code to constructors.
     35void implementThreadStarter( ast::TranslationUnit & translationUnit );
    2636};
    2737
  • src/Concurrency/module.mk

    r813dfd86 r295dd61  
    1515###############################################################################
    1616
    17 SRC += Concurrency/Keywords.cc Concurrency/Keywords.h Concurrency/Waitfor.cc Concurrency/Waitfor.h
    18 SRCDEMANGLE += Concurrency/Keywords.cc
     17SRC_CONCURRENCY = \
     18        Concurrency/KeywordsNew.cpp \
     19        Concurrency/Keywords.cc
    1920
     21SRC += $(SRC_CONCURRENCY) \
     22        Concurrency/Keywords.h \
     23        Concurrency/Waitfor.cc \
     24        Concurrency/Waitfor.h
     25
     26SRCDEMANGLE += $(SRC_CONCURRENCY)
     27
  • src/InitTweak/InitTweak.cc

    r813dfd86 r295dd61  
    99// Author           : Rob Schluntz
    1010// Created On       : Fri May 13 11:26:36 2016
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Jun 16 20:57:22 2021
    13 // Update Count     : 18
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Nov 19 19:22:00 2021
     13// Update Count     : 19
    1414//
    1515
     
    540540        }
    541541
     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
    542552        ObjectDecl * getParamThis( FunctionType * ftype ) {
    543553                assertf( ftype, "getParamThis: nullptr ftype" );
  • src/InitTweak/InitTweak.h

    r813dfd86 r295dd61  
    1010// Created On       : Fri May 13 11:26:36 2016
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Jul 19 14:18:00 2019
    13 // Update Count     : 6
     12// Last Modified On : Fri Nov 19 14:18:00 2021
     13// Update Count     : 7
    1414//
    1515
     
    3535        /// returns the base type of the first parameter to a constructor/destructor/assignment function
    3636        Type * getTypeofThis( FunctionType * ftype );
     37        const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
    3738
    3839        /// returns the first parameter of a constructor/destructor/assignment function
  • src/Validate/module.mk

    r813dfd86 r295dd61  
    1616
    1717SRC_VALIDATE = \
     18        Validate/CompoundLiteral.cpp \
     19        Validate/CompoundLiteral.hpp \
    1820        Validate/HandleAttributes.cc \
    1921        Validate/HandleAttributes.h \
  • src/main.cc

    r813dfd86 r295dd61  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Nov 12 11:06:00 2021
    13 // Update Count     : 658
     12// Last Modified On : Tue Nov 30 10:25:00 2021
     13// Update Count     : 659
    1414//
    1515
     
    5050#include "Common/UnimplementedError.h"      // for UnimplementedError
    5151#include "Common/utility.h"                 // for deleteAll, filter, printAll
     52#include "Concurrency/Keywords.h"           // for implementMutex, implement...
    5253#include "Concurrency/Waitfor.h"            // for generateWaitfor
    5354#include "ControlStruct/ExceptDecl.h"       // for translateExcept
     
    7374#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    7475#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     76#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    7577#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
    7678#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
     
    325327                PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
    326328                PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
    327                 PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
    328329
    329330                CodeTools::fillLocations( translationUnit );
     
    338339                        forceFillCodeLocations( transUnit );
    339340
     341                        PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
     342                        PASS( "Implement Thread Start", Concurrency::implementThreadStarter( transUnit ) );
     343                        PASS( "Compound Literal", Validate::handleCompoundLiterals( transUnit ) );
    340344                        PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
    341345                        PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
     
    402406                        translationUnit = convert( move( transUnit ) );
    403407                } else {
     408                        PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
    404409                        PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
    405410
  • tests/pybin/tools.py

    r813dfd86 r295dd61  
    374374
    375375        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))
    377377
    378378        try:
Note: See TracChangeset for help on using the changeset viewer.