Changes in / [794db28:36de20d]


Ignore:
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • benchmark/io/readv-posix.c

    r794db28 r36de20d  
    4444
    4545int main(int argc, char * argv[]) {
     46        BENCH_DECL
    4647        unsigned flags = 0;
    4748        unsigned sublen = 16;
  • libcfa/src/bits/locks.hfa

    r794db28 r36de20d  
    219219                }
    220220        }
    221 
    222         // Semaphore which only supports a single thread and one post
    223         // Semaphore which only supports a single thread
    224         struct oneshot {
    225                 struct $thread * volatile ptr;
    226         };
    227 
    228         static inline {
    229                 void  ?{}(oneshot & this) {
    230                         this.ptr = 0p;
    231                 }
    232 
    233                 void ^?{}(oneshot & this) {}
    234 
    235                 bool wait(oneshot & this) {
    236                         for() {
    237                                 struct $thread * expected = this.ptr;
    238                                 if(expected == 1p) return false;
    239                                 /* paranoid */ verify( expected == 0p );
    240                                 if(__atomic_compare_exchange_n(&this.ptr, &expected, active_thread(), false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)) {
    241                                         park( __cfaabi_dbg_ctx );
    242                                         /* paranoid */ verify( this.ptr == 1p );
    243                                         return true;
    244                                 }
    245                         }
    246                 }
    247 
    248                 bool post(oneshot & this) {
    249                         struct $thread * got = __atomic_exchange_n( &this.ptr, 1p, __ATOMIC_SEQ_CST);
    250                         if( got == 0p ) return false;
    251                         unpark( got __cfaabi_dbg_ctx2 );
    252                         return true;
    253                 }
    254         }
    255221#endif
  • libcfa/src/concurrency/io.cfa

    r794db28 r36de20d  
    4141        #include "kernel/fwd.hfa"
    4242        #include "io/types.hfa"
    43 
    44         // returns true of acquired as leader or second leader
    45         static inline bool try_lock( __leaderlock_t & this ) {
    46                 const uintptr_t thrd = 1z | (uintptr_t)active_thread();
    47                 bool block;
    48                 disable_interrupts();
    49                 for() {
    50                         struct $thread * expected = this.value;
    51                         if( 1p != expected && 0p != expected ) {
    52                                 /* paranoid */ verify( thrd != (uintptr_t)expected ); // We better not already be the next leader
    53                                 enable_interrupts( __cfaabi_dbg_ctx );
    54                                 return false;
    55                         }
    56                         struct $thread * desired;
    57                         if( 0p == expected ) {
    58                                 // If the lock isn't locked acquire it, no need to block
    59                                 desired = 1p;
    60                                 block = false;
    61                         }
    62                         else {
    63                                 // If the lock is already locked try becomming the next leader
    64                                 desired = (struct $thread *)thrd;
    65                                 block = true;
    66                         }
    67                         if( __atomic_compare_exchange_n(&this.value, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) break;
    68                 }
    69                 if( block ) {
    70                         enable_interrupts( __cfaabi_dbg_ctx );
    71                         park( __cfaabi_dbg_ctx );
    72                         disable_interrupts();
    73                 }
    74                 return true;
    75         }
    76 
    77         static inline bool next( __leaderlock_t & this ) {
    78                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    79                 struct $thread * nextt;
    80                 for() {
    81                         struct $thread * expected = this.value;
    82                         /* paranoid */ verify( (1 & (uintptr_t)expected) == 1 ); // The lock better be locked
    83 
    84                         struct $thread * desired;
    85                         if( 1p == expected ) {
    86                                 // No next leader, just unlock
    87                                 desired = 0p;
    88                                 nextt   = 0p;
    89                         }
    90                         else {
    91                                 // There is a next leader, remove but keep locked
    92                                 desired = 1p;
    93                                 nextt   = (struct $thread *)(~1z & (uintptr_t)expected);
    94                         }
    95                         if( __atomic_compare_exchange_n(&this.value, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ) break;
    96                 }
    97 
    98                 if(nextt) {
    99                         unpark( nextt __cfaabi_dbg_ctx2 );
    100                         enable_interrupts( __cfaabi_dbg_ctx );
    101                         return true;
    102                 }
    103                 enable_interrupts( __cfaabi_dbg_ctx );
    104                 return false;
    105         }
    10643
    10744//=============================================================================================
     
    15693//=============================================================================================
    15794        static unsigned __collect_submitions( struct __io_data & ring );
    158         static __u32 __release_consumed_submission( struct __io_data & ring );
     95        static uint32_t __release_consumed_submission( struct __io_data & ring );
    15996
    16097        static inline void process(struct io_uring_cqe & cqe ) {
     
    163100
    164101                data->result = cqe.res;
    165                 post( data->sem );
     102                unpark( data->thrd __cfaabi_dbg_ctx2 );
    166103        }
    167104
     
    199136                unsigned head = *ring.completion_q.head;
    200137                unsigned tail = *ring.completion_q.tail;
    201                 const __u32 mask = *ring.completion_q.mask;
     138                const uint32_t mask = *ring.completion_q.mask;
    202139
    203140                // Nothing was new return 0
     
    206143                }
    207144
    208                 __u32 count = tail - head;
     145                uint32_t count = tail - head;
    209146                /* paranoid */ verify( count != 0 );
    210147                for(i; count) {
     
    245182                                __STATS__( true,
    246183                                        io.complete_q.completed_avg.val += count;
    247                                         io.complete_q.completed_avg.cnt += 1;
     184                                        io.complete_q.completed_avg.fast_cnt += 1;
    248185                                )
    249186                        enable_interrupts( __cfaabi_dbg_ctx );
     
    255192                        // We didn't get anything baton pass to the slow poller
    256193                        else {
    257                                 __STATS__( true,
    258                                         io.complete_q.blocks += 1;
    259                                 )
    260194                                __cfadbg_print_safe(io_core, "Kernel I/O : Parking io poller %p\n", &this.self);
    261195                                reset = 0;
     
    290224//
    291225
    292         [* struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data ) {
     226        [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data ) {
    293227                /* paranoid */ verify( data != 0 );
    294228
     
    296230                __attribute((unused)) int len   = 0;
    297231                __attribute((unused)) int block = 0;
    298                 __u32 cnt = *ring.submit_q.num;
    299                 __u32 mask = *ring.submit_q.mask;
     232                uint32_t cnt = *ring.submit_q.num;
     233                uint32_t mask = *ring.submit_q.mask;
    300234
    301235                disable_interrupts();
    302                         __u32 off = __tls_rand();
     236                        uint32_t off = __tls_rand();
    303237                enable_interrupts( __cfaabi_dbg_ctx );
    304238
     
    307241                        // Look through the list starting at some offset
    308242                        for(i; cnt) {
    309                                 __u64 expected = 0;
    310                                 __u32 idx = (i + off) & mask;
     243                                uint64_t expected = 0;
     244                                uint32_t idx = (i + off) & mask;
    311245                                struct io_uring_sqe * sqe = &ring.submit_q.sqes[idx];
    312                                 volatile __u64 * udata = &sqe->user_data;
     246                                volatile uint64_t * udata = (volatile uint64_t *)&sqe->user_data;
    313247
    314248                                if( *udata == expected &&
     
    336270        }
    337271
    338         static inline __u32 __submit_to_ready_array( struct __io_data & ring, __u32 idx, const __u32 mask ) {
     272        static inline uint32_t __submit_to_ready_array( struct __io_data & ring, uint32_t idx, const uint32_t mask ) {
    339273                /* paranoid */ verify( idx <= mask   );
    340274                /* paranoid */ verify( idx != -1ul32 );
     
    343277                __attribute((unused)) int len   = 0;
    344278                __attribute((unused)) int block = 0;
    345                 __u32 ready_mask = ring.submit_q.ready_cnt - 1;
     279                uint32_t ready_mask = ring.submit_q.ready_cnt - 1;
    346280
    347281                disable_interrupts();
    348                         __u32 off = __tls_rand();
     282                        uint32_t off = __tls_rand();
    349283                enable_interrupts( __cfaabi_dbg_ctx );
    350284
    351                 __u32 picked;
     285                uint32_t picked;
    352286                LOOKING: for() {
    353287                        for(i; ring.submit_q.ready_cnt) {
    354288                                picked = (i + off) & ready_mask;
    355                                 __u32 expected = -1ul32;
     289                                uint32_t expected = -1ul32;
    356290                                if( __atomic_compare_exchange_n( &ring.submit_q.ready[picked], &expected, idx, true, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED ) ) {
    357291                                        break LOOKING;
     
    363297
    364298                        block++;
    365 
    366                         __u32 released = __release_consumed_submission( ring );
    367                         if( released == 0 ) {
     299                        if( try_lock(ring.submit_q.lock __cfaabi_dbg_ctx2) ) {
     300                                __release_consumed_submission( ring );
     301                                unlock( ring.submit_q.lock );
     302                        }
     303                        else {
    368304                                yield();
    369305                        }
     
    380316        }
    381317
    382         void __submit( struct io_context * ctx, __u32 idx ) __attribute__((nonnull (1))) {
     318        void __submit( struct io_context * ctx, uint32_t idx ) __attribute__((nonnull (1))) {
    383319                __io_data & ring = *ctx->thrd.ring;
    384320                // Get now the data we definetely need
    385                 volatile __u32 * const tail = ring.submit_q.tail;
    386                 const __u32 mask  = *ring.submit_q.mask;
     321                volatile uint32_t * const tail = ring.submit_q.tail;
     322                const uint32_t mask  = *ring.submit_q.mask;
    387323
    388324                // There are 2 submission schemes, check which one we are using
     
    396332                }
    397333                else if( ring.eager_submits ) {
    398                         __u32 picked = __submit_to_ready_array( ring, idx, mask );
    399 
    400                         #if defined(LEADER_LOCK)
    401                                 if( !try_lock(ring.submit_q.submit_lock) ) {
     334                        uint32_t picked = __submit_to_ready_array( ring, idx, mask );
     335
     336                        for() {
     337                                yield();
     338
     339                                // If some one else collected our index, we are done
     340                                #warning ABA problem
     341                                if( ring.submit_q.ready[picked] != idx ) {
    402342                                        __STATS__( false,
    403343                                                io.submit_q.helped += 1;
     
    405345                                        return;
    406346                                }
    407                                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    408                                 __STATS__( true,
    409                                         io.submit_q.leader += 1;
     347
     348                                if( try_lock(ring.submit_q.lock __cfaabi_dbg_ctx2) ) {
     349                                        __STATS__( false,
     350                                                io.submit_q.leader += 1;
     351                                        )
     352                                        break;
     353                                }
     354
     355                                __STATS__( false,
     356                                        io.submit_q.busy += 1;
    410357                                )
    411                         #else
    412                                 for() {
    413                                         yield();
    414 
    415                                         if( try_lock(ring.submit_q.submit_lock __cfaabi_dbg_ctx2) ) {
    416                                                 __STATS__( false,
    417                                                         io.submit_q.leader += 1;
    418                                                 )
    419                                                 break;
    420                                         }
    421 
    422                                         // If some one else collected our index, we are done
    423                                         #warning ABA problem
    424                                         if( ring.submit_q.ready[picked] != idx ) {
    425                                                 __STATS__( false,
    426                                                         io.submit_q.helped += 1;
    427                                                 )
    428                                                 return;
    429                                         }
    430 
    431                                         __STATS__( false,
    432                                                 io.submit_q.busy += 1;
    433                                         )
    434                                 }
    435                         #endif
     358                        }
    436359
    437360                        // We got the lock
     
    442365                        int ret = __io_uring_enter( ring, to_submit, false );
    443366
    444                         #if defined(LEADER_LOCK)
    445                                 /* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
    446                                 next(ring.submit_q.submit_lock);
    447                         #else
    448                                 unlock(ring.submit_q.submit_lock);
    449                         #endif
     367                        unlock(ring.submit_q.lock);
    450368                        if( ret < 0 ) return;
    451369
     
    462380                else {
    463381                        // get mutual exclusion
    464                         #if defined(LEADER_LOCK)
    465                                 while(!try_lock(ring.submit_q.submit_lock));
    466                         #else
    467                                 lock(ring.submit_q.submit_lock __cfaabi_dbg_ctx2);
    468                         #endif
     382                        lock(ring.submit_q.lock __cfaabi_dbg_ctx2);
    469383
    470384                        /* paranoid */ verifyf( ring.submit_q.sqes[ idx ].user_data != 0,
     
    504418                        __release_consumed_submission( ring );
    505419
    506                         #if defined(LEADER_LOCK)
    507                                 next(ring.submit_q.submit_lock);
    508                         #else
    509                                 unlock(ring.submit_q.submit_lock);
    510                         #endif
     420                        unlock(ring.submit_q.lock);
    511421
    512422                        __cfadbg_print_safe( io, "Kernel I/O : Performed io_submit for %p, returned %d\n", active_thread(), ret );
     
    514424        }
    515425
    516         // #define PARTIAL_SUBMIT 32
    517426        static unsigned __collect_submitions( struct __io_data & ring ) {
    518427                /* paranoid */ verify( ring.submit_q.ready != 0p );
     
    520429
    521430                unsigned to_submit = 0;
    522                 __u32 tail = *ring.submit_q.tail;
    523                 const __u32 mask = *ring.submit_q.mask;
    524                 #if defined(PARTIAL_SUBMIT)
    525                         #if defined(LEADER_LOCK)
    526                                 #error PARTIAL_SUBMIT and LEADER_LOCK cannot co-exist
    527                         #endif
    528                         const __u32 cnt = ring.submit_q.ready_cnt > PARTIAL_SUBMIT ? PARTIAL_SUBMIT : ring.submit_q.ready_cnt;
    529                         const __u32 offset = ring.submit_q.prev_ready;
    530                         ring.submit_q.prev_ready += cnt;
    531                 #else
    532                         const __u32 cnt = ring.submit_q.ready_cnt;
    533                         const __u32 offset = 0;
    534                 #endif
     431                uint32_t tail = *ring.submit_q.tail;
     432                const uint32_t mask = *ring.submit_q.mask;
    535433
    536434                // Go through the list of ready submissions
    537                 for( c; cnt ) {
    538                         __u32 i = (offset + c) % ring.submit_q.ready_cnt;
    539 
     435                for( i; ring.submit_q.ready_cnt ) {
    540436                        // replace any submission with the sentinel, to consume it.
    541                         __u32 idx = __atomic_exchange_n( &ring.submit_q.ready[i], -1ul32, __ATOMIC_RELAXED);
     437                        uint32_t idx = __atomic_exchange_n( &ring.submit_q.ready[i], -1ul32, __ATOMIC_RELAXED);
    542438
    543439                        // If it was already the sentinel, then we are done
     
    555451        }
    556452
    557         static __u32 __release_consumed_submission( struct __io_data & ring ) {
    558                 const __u32 smask = *ring.submit_q.mask;
     453        static uint32_t __release_consumed_submission( struct __io_data & ring ) {
     454                const uint32_t smask = *ring.submit_q.mask;
    559455
    560456                if( !try_lock(ring.submit_q.release_lock __cfaabi_dbg_ctx2) ) return 0;
    561                 __u32 chead = *ring.submit_q.head;
    562                 __u32 phead = ring.submit_q.prev_head;
     457                uint32_t chead = *ring.submit_q.head;
     458                uint32_t phead = ring.submit_q.prev_head;
    563459                ring.submit_q.prev_head = chead;
    564460                unlock(ring.submit_q.release_lock);
    565461
    566                 __u32 count = chead - phead;
     462                uint32_t count = chead - phead;
    567463                for( i; count ) {
    568                         __u32 idx = ring.submit_q.array[ (phead + i) & smask ];
     464                        uint32_t idx = ring.submit_q.array[ (phead + i) & smask ];
    569465                        ring.submit_q.sqes[ idx ].user_data = 0;
    570466                }
  • libcfa/src/concurrency/io/setup.cfa

    r794db28 r36de20d  
    298298                if( params_in.poll_complete ) params.flags |= IORING_SETUP_IOPOLL;
    299299
    300                 __u32 nentries = params_in.num_entries != 0 ? params_in.num_entries : 256;
     300                uint32_t nentries = params_in.num_entries != 0 ? params_in.num_entries : 256;
    301301                if( !is_pow2(nentries) ) {
    302302                        abort("ERROR: I/O setup 'num_entries' must be a power of 2\n");
     
    362362                // Get the pointers from the kernel to fill the structure
    363363                // submit queue
    364                 sq.head    = (volatile __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.head);
    365                 sq.tail    = (volatile __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.tail);
    366                 sq.mask    = (   const __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_mask);
    367                 sq.num     = (   const __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_entries);
    368                 sq.flags   = (         __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.flags);
    369                 sq.dropped = (         __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
    370                 sq.array   = (         __u32 *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
     364                sq.head    = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.head);
     365                sq.tail    = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.tail);
     366                sq.mask    = (   const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_mask);
     367                sq.num     = (   const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_entries);
     368                sq.flags   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.flags);
     369                sq.dropped = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
     370                sq.array   = (         uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
    371371                sq.prev_head = *sq.head;
    372372
    373373                {
    374                         const __u32 num = *sq.num;
     374                        const uint32_t num = *sq.num;
    375375                        for( i; num ) {
    376376                                sq.sqes[i].user_data = 0ul64;
     
    378378                }
    379379
    380                 (sq.submit_lock){};
     380                (sq.lock){};
    381381                (sq.release_lock){};
    382382
     
    388388                                sq.ready[i] = -1ul32;
    389389                        }
    390                         sq.prev_ready = 0;
    391390                }
    392391                else {
    393392                        sq.ready_cnt = 0;
    394393                        sq.ready = 0p;
    395                         sq.prev_ready = 0;
    396394                }
    397395
    398396                // completion queue
    399                 cq.head      = (volatile __u32 *)(((intptr_t)cq.ring_ptr) + params.cq_off.head);
    400                 cq.tail      = (volatile __u32 *)(((intptr_t)cq.ring_ptr) + params.cq_off.tail);
    401                 cq.mask      = (   const __u32 *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_mask);
    402                 cq.num       = (   const __u32 *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_entries);
    403                 cq.overflow  = (         __u32 *)(((intptr_t)cq.ring_ptr) + params.cq_off.overflow);
    404                 cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
     397                cq.head     = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.head);
     398                cq.tail     = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.tail);
     399                cq.mask     = (   const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_mask);
     400                cq.num      = (   const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_entries);
     401                cq.overflow = (         uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.overflow);
     402                cq.cqes   = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
    405403
    406404                // some paranoid checks
     
    450448        void __ioctx_register($io_ctx_thread & ctx, struct epoll_event & ev) {
    451449                ev.events = EPOLLIN | EPOLLONESHOT;
    452                 ev.data.u64 = (__u64)&ctx;
     450                ev.data.u64 = (uint64_t)&ctx;
    453451                int ret = epoll_ctl(iopoll.epollfd, EPOLL_CTL_ADD, ctx.ring->fd, &ev);
    454452                if (ret < 0) {
  • libcfa/src/concurrency/io/types.hfa

    r794db28 r36de20d  
    1717
    1818#if defined(CFA_HAVE_LINUX_IO_URING_H)
    19         extern "C" {
    20                 #include <linux/types.h>
    21         }
    22 
    2319      #include "bits/locks.hfa"
    24 
    25         #define LEADER_LOCK
    26         struct __leaderlock_t {
    27                 struct $thread * volatile value;        // ($thread) next_leader | (bool:1) is_locked
    28         };
    29 
    30         static inline void ?{}( __leaderlock_t & this ) { this.value = 0p; }
    3120
    3221        //-----------------------------------------------------------------------
     
    3423      struct __submition_data {
    3524                // Head and tail of the ring (associated with array)
    36                 volatile __u32 * head;
    37                 volatile __u32 * tail;
    38                 volatile __u32 prev_head;
     25                volatile uint32_t * head;
     26                volatile uint32_t * tail;
     27                volatile uint32_t prev_head;
    3928
    4029                // The actual kernel ring which uses head/tail
    4130                // indexes into the sqes arrays
    42                 __u32 * array;
     31                uint32_t * array;
    4332
    4433                // number of entries and mask to go with it
    45                 const __u32 * num;
    46                 const __u32 * mask;
     34                const uint32_t * num;
     35                const uint32_t * mask;
    4736
    4837                // Submission flags (Not sure what for)
    49                 __u32 * flags;
     38                uint32_t * flags;
    5039
    5140                // number of sqes not submitted (whatever that means)
    52                 __u32 * dropped;
     41                uint32_t * dropped;
    5342
    5443                // Like head/tail but not seen by the kernel
    55                 volatile __u32 * ready;
    56                 __u32 ready_cnt;
    57                 __u32 prev_ready;
     44                volatile uint32_t * ready;
     45                uint32_t ready_cnt;
    5846
    59                 #if defined(LEADER_LOCK)
    60                         __leaderlock_t submit_lock;
    61                 #else
    62                         __spinlock_t submit_lock;
    63                 #endif
    64                 __spinlock_t  release_lock;
     47                __spinlock_t lock;
     48                __spinlock_t release_lock;
    6549
    6650                // A buffer of sqes (not the actual ring)
     
    7458        struct __completion_data {
    7559                // Head and tail of the ring
    76                 volatile __u32 * head;
    77                 volatile __u32 * tail;
     60                volatile uint32_t * head;
     61                volatile uint32_t * tail;
    7862
    7963                // number of entries and mask to go with it
    80                 const __u32 * mask;
    81                 const __u32 * num;
     64                const uint32_t * mask;
     65                const uint32_t * num;
    8266
    8367                // number of cqes not submitted (whatever that means)
    84                 __u32 * overflow;
     68                uint32_t * overflow;
    8569
    8670                // the kernel ring
     
    9579                struct __submition_data submit_q;
    9680                struct __completion_data completion_q;
    97                 __u32 ring_flags;
     81                uint32_t ring_flags;
    9882                int fd;
    9983                bool eager_submits:1;
     
    10589        // IO user data
    10690        struct __io_user_data_t {
    107                 __s32 result;
    108                 oneshot sem;
     91                int32_t result;
     92                $thread * thrd;
    10993        };
    11094
  • libcfa/src/concurrency/iocall.cfa

    r794db28 r36de20d  
    3232        #include "io/types.hfa"
    3333
    34         extern [* struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data );
    35         extern void __submit( struct io_context * ctx, __u32 idx ) __attribute__((nonnull (1)));
    36 
    37         static inline void ?{}(struct io_uring_sqe & this, __u8 opcode, int fd) {
     34        extern [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data );
     35        extern void __submit( struct io_context * ctx, uint32_t idx ) __attribute__((nonnull (1)));
     36
     37        static inline void ?{}(struct io_uring_sqe & this, uint8_t opcode, int fd) {
    3838                this.opcode = opcode;
    3939                #if !defined(IOSQE_ASYNC)
     
    5151        }
    5252
    53         static inline void ?{}(struct io_uring_sqe & this, __u8 opcode, int fd, void * addr, __u32 len, __u64 off ) {
     53        static inline void ?{}(struct io_uring_sqe & this, uint8_t opcode, int fd, void * addr, uint32_t len, uint64_t off ) {
    5454                (this){ opcode, fd };
    5555                this.off = off;
    56                 this.addr = (__u64)(uintptr_t)addr;
     56                this.addr = (uint64_t)(uintptr_t)addr;
    5757                this.len = len;
    5858        }
     
    105105                (void)timeout; (void)cancellation; \
    106106                if( !context ) context = __get_io_context(); \
    107                 __io_user_data_t data = { 0 }; \
     107                __io_user_data_t data = { 0, active_thread() }; \
    108108                struct __io_data & ring = *context->thrd.ring; \
    109109                struct io_uring_sqe * sqe; \
    110                 __u32 idx; \
    111                 __u8 sflags = REGULAR_FLAGS & submit_flags; \
    112                 [sqe, idx] = __submit_alloc( ring, (__u64)(uintptr_t)&data ); \
     110                uint32_t idx; \
     111                uint8_t sflags = REGULAR_FLAGS & submit_flags; \
     112                [sqe, idx] = __submit_alloc( ring, (uint64_t)(uintptr_t)&data ); \
    113113                sqe->flags = sflags;
    114114
    115115        #define __submit_wait \
    116116                /*__cfaabi_bits_print_safe( STDERR_FILENO, "Preparing user data %p for %p\n", &data, data.thrd );*/ \
    117                 verify( sqe->user_data == (__u64)(uintptr_t)&data ); \
     117                verify( sqe->user_data == (uint64_t)(uintptr_t)&data ); \
    118118                __submit( context, idx ); \
    119                 wait( data.sem ); \
     119                park( __cfaabi_dbg_ctx ); \
    120120                if( data.result < 0 ) { \
    121121                        errno = -data.result; \
     
    149149
    150150        extern int fsync(int fd);
    151 
    152         typedef __off64_t off_t;
    153         typedef __off64_t off64_t;
    154         extern int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags);
     151        extern int sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags);
    155152
    156153        struct msghdr;
     
    163160        extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    164161
    165         extern int fallocate(int fd, int mode, off_t offset, off_t len);
    166         extern int posix_fadvise(int fd, off_t offset, off_t len, int advice);
     162        extern int fallocate(int fd, int mode, uint64_t offset, uint64_t len);
     163        extern int posix_fadvise(int fd, uint64_t offset, uint64_t len, int advice);
    167164        extern int madvise(void *addr, size_t length, int advice);
    168165
     
    193190                        sqe->fd = fd;
    194191                        sqe->off = offset;
    195                         sqe->addr = (__u64)iov;
     192                        sqe->addr = (uint64_t)(uintptr_t)iov;
    196193                        sqe->len = iovcnt;
    197194                        sqe->rw_flags = 0;
     
    210207                        __submit_prelude
    211208
    212                         sqe->opcode = IORING_OP_WRITEV;
    213                         sqe->ioprio = 0;
    214                         sqe->fd = fd;
    215                         sqe->off = offset;
    216                         sqe->addr = (__u64)iov;
    217                         sqe->len = iovcnt;
    218                         sqe->rw_flags = 0;
    219                         sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
     209                        (*sqe){ IORING_OP_WRITEV, fd, iov, iovcnt, offset };
    220210
    221211                        __submit_wait
     
    230220                __submit_prelude
    231221
    232                 sqe->opcode = IORING_OP_FSYNC;
    233                 sqe->ioprio = 0;
    234                 sqe->fd = fd;
    235                 sqe->off = 0;
    236                 sqe->addr = 0;
    237                 sqe->len = 0;
    238                 sqe->rw_flags = 0;
    239                 sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
    240 
    241                 __submit_wait
    242         #endif
    243 }
    244 
    245 int cfa_sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
     222                (*sqe){ IORING_OP_FSYNC, fd };
     223
     224                __submit_wait
     225        #endif
     226}
     227
     228int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
    246229        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_SYNC_FILE_RANGE)
    247230                return sync_file_range(fd, offset, nbytes, flags);
     
    292275
    293276                (*sqe){ IORING_OP_SEND, sockfd };
    294                 sqe->addr = (__u64)buf;
     277                sqe->addr = (uint64_t)buf;
    295278                sqe->len = len;
    296279                sqe->msg_flags = flags;
     
    307290
    308291                (*sqe){ IORING_OP_RECV, sockfd };
    309                 sqe->addr = (__u64)buf;
     292                sqe->addr = (uint64_t)buf;
    310293                sqe->len = len;
    311294                sqe->msg_flags = flags;
     
    322305
    323306                (*sqe){ IORING_OP_ACCEPT, sockfd };
    324                 sqe->addr  = (__u64)addr;
    325                 sqe->addr2 = (__u64)addrlen;
     307                sqe->addr = (uint64_t)(uintptr_t)addr;
     308                sqe->addr2 = (uint64_t)(uintptr_t)addrlen;
    326309                sqe->accept_flags = flags;
    327310
     
    337320
    338321                (*sqe){ IORING_OP_CONNECT, sockfd };
    339                 sqe->addr = (__u64)addr;
    340                 sqe->off  = (__u64)addrlen;
    341 
    342                 __submit_wait
    343         #endif
    344 }
    345 
    346 int cfa_fallocate(int fd, int mode, off_t offset, off_t len, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
     322                sqe->addr = (uint64_t)(uintptr_t)addr;
     323                sqe->off  = (uint64_t)(uintptr_t)addrlen;
     324
     325                __submit_wait
     326        #endif
     327}
     328
     329int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
    347330        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_FALLOCATE)
    348331                return fallocate( fd, mode, offset, len );
     
    361344}
    362345
    363 int cfa_fadvise(int fd, off_t offset, off_t len, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
     346int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {
    364347        #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_FADVISE)
    365348                return posix_fadvise( fd, offset, len, advice );
     
    368351
    369352                (*sqe){ IORING_OP_FADVISE, fd };
    370                 sqe->off = (__u64)offset;
     353                sqe->off = (uint64_t)offset;
    371354                sqe->len = len;
    372355                sqe->fadvise_advice = advice;
     
    383366
    384367                (*sqe){ IORING_OP_MADVISE, 0 };
    385                 sqe->addr = (__u64)addr;
     368                sqe->addr = (uint64_t)addr;
    386369                sqe->len = length;
    387370                sqe->fadvise_advice = advice;
     
    398381
    399382                (*sqe){ IORING_OP_OPENAT, dirfd };
    400                 sqe->addr = (__u64)pathname;
     383                sqe->addr = (uint64_t)pathname;
    401384                sqe->open_flags = flags;
    402385                sqe->len = mode;
     
    431414                __submit_prelude
    432415
    433                 (*sqe){ IORING_OP_STATX, dirfd, pathname, mask, (__u64)statxbuf };
     416                (*sqe){ IORING_OP_STATX, dirfd, pathname, mask, (uint64_t)statxbuf };
    434417                sqe->statx_flags = flags;
    435418
     
    473456                }
    474457                else {
    475                         sqe->off = (__u64)-1;
     458                        sqe->off = (uint64_t)-1;
    476459                }
    477460                sqe->len = len;
     
    481464                }
    482465                else {
    483                         sqe->splice_off_in = (__u64)-1;
     466                        sqe->splice_off_in = (uint64_t)-1;
    484467                }
    485468                sqe->splice_flags  = flags | (SPLICE_FLAGS & submit_flags);
  • libcfa/src/concurrency/kernel.cfa

    r794db28 r36de20d  
    532532                unsigned total   = this.total;
    533533                processor * proc = &this.list`first;
    534                 // Compiler fence is unnecessary, but gcc-8 and older incorrectly reorder code without it
    535                 asm volatile("": : :"memory");
     534                // Thread fence is unnecessary, but gcc-8 and older incorrectly reorder code without it
     535                __atomic_thread_fence(__ATOMIC_SEQ_CST);
    536536                if(l != __atomic_load_n(&this.lock, __ATOMIC_SEQ_CST)) { Pause(); continue; }
    537537                return [idle, total, proc];
  • libcfa/src/concurrency/stats.cfa

    r794db28 r36de20d  
    3838                        stats->io.submit_q.busy   = 0;
    3939                        stats->io.complete_q.completed_avg.val = 0;
    40                         stats->io.complete_q.completed_avg.cnt = 0;
    41                         stats->io.complete_q.blocks = 0;
     40                        stats->io.complete_q.completed_avg.slow_cnt = 0;
     41                        stats->io.complete_q.completed_avg.fast_cnt = 0;
    4242                #endif
    4343        }
     
    6060
    6161                #if defined(CFA_HAVE_LINUX_IO_URING_H)
    62                         __atomic_fetch_add( &cltr->io.submit_q.submit_avg.rdy     , proc->io.submit_q.submit_avg.rdy     , __ATOMIC_SEQ_CST );
    63                         __atomic_fetch_add( &cltr->io.submit_q.submit_avg.csm     , proc->io.submit_q.submit_avg.csm     , __ATOMIC_SEQ_CST );
    64                         __atomic_fetch_add( &cltr->io.submit_q.submit_avg.avl     , proc->io.submit_q.submit_avg.avl     , __ATOMIC_SEQ_CST );
    65                         __atomic_fetch_add( &cltr->io.submit_q.submit_avg.cnt     , proc->io.submit_q.submit_avg.cnt     , __ATOMIC_SEQ_CST );
    66                         __atomic_fetch_add( &cltr->io.submit_q.look_avg.val       , proc->io.submit_q.look_avg.val       , __ATOMIC_SEQ_CST );
    67                         __atomic_fetch_add( &cltr->io.submit_q.look_avg.cnt       , proc->io.submit_q.look_avg.cnt       , __ATOMIC_SEQ_CST );
    68                         __atomic_fetch_add( &cltr->io.submit_q.look_avg.block     , proc->io.submit_q.look_avg.block     , __ATOMIC_SEQ_CST );
    69                         __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.val      , proc->io.submit_q.alloc_avg.val      , __ATOMIC_SEQ_CST );
    70                         __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.cnt      , proc->io.submit_q.alloc_avg.cnt      , __ATOMIC_SEQ_CST );
    71                         __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.block    , proc->io.submit_q.alloc_avg.block    , __ATOMIC_SEQ_CST );
    72                         __atomic_fetch_add( &cltr->io.submit_q.helped             , proc->io.submit_q.helped             , __ATOMIC_SEQ_CST );
    73                         __atomic_fetch_add( &cltr->io.submit_q.leader             , proc->io.submit_q.leader             , __ATOMIC_SEQ_CST );
    74                         __atomic_fetch_add( &cltr->io.submit_q.busy               , proc->io.submit_q.busy               , __ATOMIC_SEQ_CST );
    75                         __atomic_fetch_add( &cltr->io.complete_q.completed_avg.val, proc->io.complete_q.completed_avg.val, __ATOMIC_SEQ_CST );
    76                         __atomic_fetch_add( &cltr->io.complete_q.completed_avg.cnt, proc->io.complete_q.completed_avg.cnt, __ATOMIC_SEQ_CST );
    77                         __atomic_fetch_add( &cltr->io.complete_q.blocks           , proc->io.complete_q.blocks           , __ATOMIC_SEQ_CST );
     62                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.rdy          , proc->io.submit_q.submit_avg.rdy          , __ATOMIC_SEQ_CST );
     63                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.csm          , proc->io.submit_q.submit_avg.csm          , __ATOMIC_SEQ_CST );
     64                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.avl          , proc->io.submit_q.submit_avg.avl          , __ATOMIC_SEQ_CST );
     65                        __atomic_fetch_add( &cltr->io.submit_q.submit_avg.cnt          , proc->io.submit_q.submit_avg.cnt          , __ATOMIC_SEQ_CST );
     66                        __atomic_fetch_add( &cltr->io.submit_q.look_avg.val            , proc->io.submit_q.look_avg.val            , __ATOMIC_SEQ_CST );
     67                        __atomic_fetch_add( &cltr->io.submit_q.look_avg.cnt            , proc->io.submit_q.look_avg.cnt            , __ATOMIC_SEQ_CST );
     68                        __atomic_fetch_add( &cltr->io.submit_q.look_avg.block          , proc->io.submit_q.look_avg.block          , __ATOMIC_SEQ_CST );
     69                        __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.val           , proc->io.submit_q.alloc_avg.val           , __ATOMIC_SEQ_CST );
     70                        __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.cnt           , proc->io.submit_q.alloc_avg.cnt           , __ATOMIC_SEQ_CST );
     71                        __atomic_fetch_add( &cltr->io.submit_q.alloc_avg.block         , proc->io.submit_q.alloc_avg.block         , __ATOMIC_SEQ_CST );
     72                        __atomic_fetch_add( &cltr->io.submit_q.helped                  , proc->io.submit_q.helped                  , __ATOMIC_SEQ_CST );
     73                        __atomic_fetch_add( &cltr->io.submit_q.leader                  , proc->io.submit_q.leader                  , __ATOMIC_SEQ_CST );
     74                        __atomic_fetch_add( &cltr->io.submit_q.busy                    , proc->io.submit_q.busy                    , __ATOMIC_SEQ_CST );
     75                        __atomic_fetch_add( &cltr->io.complete_q.completed_avg.val     , proc->io.complete_q.completed_avg.val     , __ATOMIC_SEQ_CST );
     76                        __atomic_fetch_add( &cltr->io.complete_q.completed_avg.slow_cnt, proc->io.complete_q.completed_avg.slow_cnt, __ATOMIC_SEQ_CST );
     77                        __atomic_fetch_add( &cltr->io.complete_q.completed_avg.fast_cnt, proc->io.complete_q.completed_avg.fast_cnt, __ATOMIC_SEQ_CST );
    7878                #endif
    7979        }
     
    154154                                        "- avg alloc search len   : %'18.2lf\n"
    155155                                        "- avg alloc search block : %'18.2lf\n"
    156                                         "- total wait calls       : %'15" PRIu64 "\n"
     156                                        "- total wait calls       : %'15" PRIu64 "   (%'" PRIu64 " slow, %'" PRIu64 " fast)\n"
    157157                                        "- avg completion/wait    : %'18.2lf\n"
    158                                         "- total completion blocks: %'15" PRIu64 "\n"
    159158                                        "\n"
    160159                                        , cluster ? "Cluster" : "Processor",  name, id
     
    166165                                        , io.submit_q.alloc_avg.cnt
    167166                                        , aavgv, aavgb
    168                                         , io.complete_q.completed_avg.cnt
    169                                         , ((double)io.complete_q.completed_avg.val) / io.complete_q.completed_avg.cnt
    170                                         , io.complete_q.blocks
     167                                        , io.complete_q.completed_avg.slow_cnt + io.complete_q.completed_avg.fast_cnt
     168                                        , io.complete_q.completed_avg.slow_cnt,  io.complete_q.completed_avg.fast_cnt
     169                                        , ((double)io.complete_q.completed_avg.val) / (io.complete_q.completed_avg.slow_cnt + io.complete_q.completed_avg.fast_cnt)
    171170                                );
    172171                        }
  • libcfa/src/concurrency/stats.hfa

    r794db28 r36de20d  
    9090                                struct {
    9191                                        volatile uint64_t val;
    92                                         volatile uint64_t cnt;
     92                                        volatile uint64_t slow_cnt;
     93                                        volatile uint64_t fast_cnt;
    9394                                } completed_avg;
    94                                 volatile uint64_t blocks;
    9595                        } complete_q;
    9696                };
  • libcfa/src/parseargs.cfa

    r794db28 r36de20d  
    137137        int width = 0;
    138138        {
     139                int idx = 0;
    139140                for(i; opt_count) {
    140141                        if(options[i].long_name) {
Note: See TracChangeset for help on using the changeset viewer.