Changeset 22226e4 for libcfa/src


Ignore:
Timestamp:
Mar 18, 2022, 12:42:39 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
0b4ddb71, 51239d1b
Parents:
3bc69f2
Message:

Tentative fix for spurious deadlock in some concurrency tests

Location:
libcfa/src/concurrency
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/io/setup.cfa

    r3bc69f2 r22226e4  
    115115                this.ext_sq.empty = true;
    116116                (this.ext_sq.queue){};
    117                 __io_uring_setup( this, cl.io.params, proc->idle_fd );
     117                __io_uring_setup( this, cl.io.params, proc->idle_wctx.evfd );
    118118                __cfadbg_print_safe(io_core, "Kernel I/O : Created ring for io_context %u (%p)\n", this.fd, &this);
    119119        }
     
    125125                __cfadbg_print_safe(io_core, "Kernel I/O : Destroyed ring for io_context %u\n", this.fd);
    126126        }
    127 
    128         extern void __disable_interrupts_hard();
    129         extern void __enable_interrupts_hard();
    130127
    131128        static void __io_uring_setup( $io_context & this, const io_context_params & params_in, int procfd ) {
     
    230227                        __cfadbg_print_safe(io_core, "Kernel I/O : registering %d for completion with ring %d\n", procfd, fd);
    231228
    232                         __disable_interrupts_hard();
    233 
    234229                        int ret = syscall( __NR_io_uring_register, fd, IORING_REGISTER_EVENTFD, &procfd, 1);
    235230                        if (ret < 0) {
    236231                                abort("KERNEL ERROR: IO_URING EVENTFD REGISTER - %s\n", strerror(errno));
    237232                        }
    238 
    239                         __enable_interrupts_hard();
    240233
    241234                        __cfadbg_print_safe(io_core, "Kernel I/O : registered %d for completion with ring %d\n", procfd, fd);
  • libcfa/src/concurrency/kernel.cfa

    r3bc69f2 r22226e4  
    136136static void mark_awake(__cluster_proc_list & idles, processor & proc);
    137137
    138 extern void __cfa_io_start( processor * );
    139138extern bool __cfa_io_drain( processor * );
    140139extern bool __cfa_io_flush( processor *, int min_comp );
    141 extern void __cfa_io_stop ( processor * );
    142140static inline bool __maybe_io_drain( processor * );
    143141
     
    164162        verify(this);
    165163
    166         io_future_t future; // used for idle sleep when io_uring is present
    167         future.self.ptr = 1p;  // mark it as already fulfilled so we know if there is a pending request or not
    168         eventfd_t idle_val;
    169         iovec idle_iovec = { &idle_val, sizeof(idle_val) };
    170 
    171         __cfa_io_start( this );
     164        /* paranoid */ verify( this->idle_wctx.ftr   != 0p );
     165        /* paranoid */ verify( this->idle_wctx.rdbuf != 0p );
     166
     167        // used for idle sleep when io_uring is present
     168        // mark it as already fulfilled so we know if there is a pending request or not
     169        this->idle_wctx.ftr->self.ptr = 1p;
     170        iovec idle_iovec = { this->idle_wctx.rdbuf, sizeof(eventfd_t) };
    172171
    173172        __cfadbg_print_safe(runtime_core, "Kernel : core %p starting\n", this);
     
    236235                                }
    237236
    238                                 idle_sleep( this, future, idle_iovec );
     237                                idle_sleep( this, *this->idle_wctx.ftr, idle_iovec );
    239238
    240239                                // We were woken up, remove self from idle
     
    264263                __cfadbg_print_safe(runtime_core, "Kernel : core %p stopping\n", this);
    265264        }
    266 
    267         for(int i = 0; !available(future); i++) {
    268                 if(i > 1000) __cfaabi_dbg_write( "ERROR: kernel has bin spinning on a flush after exit loop.\n", 60);
    269                 __cfa_io_flush( this, 1 );
    270         }
    271 
    272         __cfa_io_stop( this );
    273265
    274266        post( this->terminated );
     
    639631
    640632        int fd = 1;
    641         if( __atomic_load_n(&fdp->fd, __ATOMIC_SEQ_CST) != 1 ) {
    642                 fd = __atomic_exchange_n(&fdp->fd, 1, __ATOMIC_RELAXED);
     633        if( __atomic_load_n(&fdp->sem, __ATOMIC_SEQ_CST) != 1 ) {
     634                fd = __atomic_exchange_n(&fdp->sem, 1, __ATOMIC_RELAXED);
    643635        }
    644636
     
    682674        __cfadbg_print_safe(runtime_core, "Kernel : waking Processor %p\n", this);
    683675
    684         this->idle_wctx.fd = 1;
     676        this->idle_wctx.sem = 1;
    685677
    686678        eventfd_t val;
    687679        val = 1;
    688         eventfd_write( this->idle_fd, val );
     680        eventfd_write( this->idle_wctx.evfd, val );
    689681
    690682        /* paranoid */ verify( ! __preemption_enabled() );
     
    694686        // Tell everyone we are ready to go do sleep
    695687        for() {
    696                 int expected = this->idle_wctx.fd;
     688                int expected = this->idle_wctx.sem;
    697689
    698690                // Someone already told us to wake-up! No time for a nap.
     
    700692
    701693                // Try to mark that we are going to sleep
    702                 if(__atomic_compare_exchange_n(&this->idle_wctx.fd, &expected, this->idle_fd, false,  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
     694                if(__atomic_compare_exchange_n(&this->idle_wctx.sem, &expected, this->idle_wctx.evfd, false,  __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) {
    703695                        // Every one agreed, taking a nap
    704696                        break;
     
    718710                {
    719711                        eventfd_t val;
    720                         ssize_t ret = read( this->idle_fd, &val, sizeof(val) );
     712                        ssize_t ret = read( this->idle_wctx.evfd, &val, sizeof(val) );
    721713                        if(ret < 0) {
    722714                                switch((int)errno) {
     
    745737                        reset(future);
    746738
    747                         __kernel_read(this, future, iov, this->idle_fd );
     739                        __kernel_read(this, future, iov, this->idle_wctx.evfd );
    748740                }
    749741
     
    755747        __STATS__(true, ready.sleep.halts++; )
    756748
    757         proc.idle_wctx.fd = 0;
     749        proc.idle_wctx.sem = 0;
    758750
    759751        /* paranoid */ verify( ! __preemption_enabled() );
  • libcfa/src/concurrency/kernel.hfa

    r3bc69f2 r22226e4  
    4848extern struct cluster * mainCluster;
    4949
    50 // Processor id, required for scheduling threads
    51 
    52 
     50// Coroutine used py processors for the 2-step context switch
    5351coroutine processorCtx_t {
    5452        struct processor * proc;
    5553};
    5654
    57 
     55struct io_future_t;
     56
     57// Information needed for idle sleep
    5858struct __fd_waitctx {
    59         volatile int fd;
     59        // semaphore/future like object
     60        // values can be 0, 1 or some file descriptor.
     61        // 0 - is the default state
     62        // 1 - means the proc should wake-up immediately
     63        // FD - means the proc is going asleep and should be woken by writing to the FD.
     64        volatile int sem;
     65
     66        // The event FD that corresponds to this processor
     67        int evfd;
     68
     69        // buffer into which the proc will read from evfd
     70        // unused if not using io_uring for idle sleep
     71        void * rdbuf;
     72
     73        // future use to track the read of the eventfd
     74        // unused if not using io_uring for idle sleep
     75        io_future_t * ftr;
    6076};
    6177
     
    103119        bool pending_preemption;
    104120
    105         // Idle lock (kernel semaphore)
    106         int idle_fd;
    107 
    108         // Idle waitctx
     121        // context for idle sleep
    109122        struct __fd_waitctx idle_wctx;
    110123
     
    168181        volatile unsigned id;
    169182};
    170 
    171 // //TODO adjust cache size to ARCHITECTURE
    172 // // Structure holding the ready queue
    173 // struct __ready_queue_t {
    174 //      // Data tracking the actual lanes
    175 //      // On a seperate cacheline from the used struct since
    176 //      // used can change on each push/pop but this data
    177 //      // only changes on shrink/grow
    178 //      struct {
    179 //              // Arary of lanes
    180 //              __intrusive_lane_t * volatile data;
    181 
    182 //              __cache_id_t * volatile caches;
    183 
    184 //              // Number of lanes (empty or not)
    185 //              volatile size_t count;
    186 //      } lanes;
    187 // };
    188 
    189 // void  ?{}(__ready_queue_t & this);
    190 // void ^?{}(__ready_queue_t & this);
    191183
    192184// Idle Sleep
  • libcfa/src/concurrency/kernel/startup.cfa

    r3bc69f2 r22226e4  
    3333// CFA Includes
    3434#include "kernel/private.hfa"
     35#include "iofwd.hfa"
    3536#include "startup.hfa"                                  // STARTUP_PRIORITY_XXX
    3637#include "limits.hfa"
     
    9798extern void __kernel_alarm_startup(void);
    9899extern void __kernel_alarm_shutdown(void);
     100extern void __cfa_io_start( processor * );
     101extern void __cfa_io_stop ( processor * );
    99102
    100103//-----------------------------------------------------------------------------
     
    111114KERNEL_STORAGE(__stack_t,            mainThreadCtx);
    112115KERNEL_STORAGE(__scheduler_RWLock_t, __scheduler_lock);
     116KERNEL_STORAGE(eventfd_t,            mainIdleEventFd);
     117KERNEL_STORAGE(io_future_t,          mainIdleFuture);
    113118#if !defined(__CFA_NO_STATISTICS__)
    114119KERNEL_STORAGE(__stats_t, mainProcStats);
     
    224229        (*mainProcessor){};
    225230
     231        mainProcessor->idle_wctx.rdbuf = &storage_mainIdleEventFd;
     232        mainProcessor->idle_wctx.ftr   = (io_future_t*)&storage_mainIdleFuture;
     233        /* paranoid */ verify( sizeof(storage_mainIdleEventFd) == sizeof(eventfd_t) );
     234
    226235        register_tls( mainProcessor );
     236        __cfa_io_start( mainProcessor );
    227237
    228238        // Start by initializing the main thread
     
    304314        mainProcessor->local_data = 0p;
    305315
     316        __cfa_io_stop( mainProcessor );
    306317        unregister_tls( mainProcessor );
    307318
     
    355366        register_tls( proc );
    356367
     368        __cfa_io_start( proc );
     369
     370        // used for idle sleep when io_uring is present
     371        io_future_t future;
     372        eventfd_t idle_buf;
     373        proc->idle_wctx.ftr = &future;
     374        proc->idle_wctx.rdbuf = &idle_buf;
     375
     376
    357377        // SKULLDUGGERY: We want to create a context for the processor coroutine
    358378        // which is needed for the 2-step context switch. However, there is no reason
     
    381401        // Main routine of the core returned, the core is now fully terminated
    382402        __cfadbg_print_safe(runtime_core, "Kernel : core %p main ended (%p)\n", proc, &proc->runner);
     403
     404        __cfa_io_stop( proc );
    383405
    384406        #if !defined(__CFA_NO_STATISTICS__)
     
    532554        this.local_data = 0p;
    533555
    534         this.idle_fd = eventfd(0, 0);
    535         if (idle_fd < 0) {
     556        idle_wctx.evfd = eventfd(0, 0);
     557        if (idle_wctx.evfd < 0) {
    536558                abort("KERNEL ERROR: PROCESSOR EVENTFD - %s\n", strerror(errno));
    537559        }
    538560
    539         this.idle_wctx.fd = 0;
     561        idle_wctx.sem = 0;
    540562
    541563        // I'm assuming these two are reserved for standard input and output
    542564        // so I'm using them as sentinels with idle_wctx.
    543         /* paranoid */ verify( this.idle_fd != 0 );
    544         /* paranoid */ verify( this.idle_fd != 1 );
     565        /* paranoid */ verify( idle_wctx.evfd != 0 );
     566        /* paranoid */ verify( idle_wctx.evfd != 1 );
    545567
    546568        #if !defined(__CFA_NO_STATISTICS__)
     
    554576// Not a ctor, it just preps the destruction but should not destroy members
    555577static void deinit(processor & this) {
    556         close(this.idle_fd);
     578        close(this.idle_wctx.evfd);
    557579}
    558580
Note: See TracChangeset for help on using the changeset viewer.