Ignore:
Timestamp:
Jul 28, 2022, 12:04:25 PM (2 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, master, pthread-emulation
Children:
32d1383, d0fcc82
Parents:
3f95dab (diff), 2af1943 (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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/ready_subqueue.hfa

    r3f95dab rc4c8571  
    66
    77// Intrusives lanes which are used by the relaxed ready queue
    8 struct __attribute__((aligned(128))) __intrusive_lane_t {
    9         struct thread$ * prev;
     8union __attribute__((aligned(64))) __intrusive_lane_t {
     9        struct {
     10                struct thread$ * prev;
    1011
    11         // spin lock protecting the queue
    12         volatile bool lock;
     12                // spin lock protecting the queue
     13                volatile bool lock;
    1314
    14         __thread_desc_link anchor;
     15                __thread_desc_link anchor;
    1516
    16         #if !defined(__CFA_NO_STATISTICS__)
    17                 unsigned cnt;
    18         #endif
     17                #if !defined(__CFA_NO_STATISTICS__)
     18                        unsigned cnt;
     19                #endif
     20        } l;
     21        char __padding[192];
    1922};
    2023
     
    2225static inline thread$ * mock_head(const __intrusive_lane_t & this) {
    2326        thread$ * rhead = (thread$ *)(
    24                 (uintptr_t)( &this.anchor ) - __builtin_offsetof( thread$, link )
     27                (uintptr_t)( &this.l.anchor ) - __builtin_offsetof( thread$, link )
    2528        );
    2629        return rhead;
     
    3033// returns true of lane was empty before push, false otherwise
    3134static inline void push( __intrusive_lane_t & this, thread$ * node ) {
    32         /* paranoid */ verify( this.lock );
     35        /* paranoid */ verify( this.l.lock );
    3336        /* paranoid */ verify( node->link.next == 0p );
    3437        /* paranoid */ verify( __atomic_load_n(&node->link.ts, __ATOMIC_RELAXED) == MAX  );
    35         /* paranoid */ verify( this.prev->link.next == 0p );
    36         /* paranoid */ verify( __atomic_load_n(&this.prev->link.ts, __ATOMIC_RELAXED)   == MAX  );
    37         if( this.anchor.next == 0p ) {
    38                 /* paranoid */ verify( this.anchor.next == 0p );
    39                 /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) == MAX );
    40                 /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) != 0  );
    41                 /* paranoid */ verify( this.prev == mock_head( this ) );
     38        /* paranoid */ verify( this.l.prev->link.next == 0p );
     39        /* paranoid */ verify( __atomic_load_n(&this.l.prev->link.ts, __ATOMIC_RELAXED)   == MAX  );
     40        if( this.l.anchor.next == 0p ) {
     41                /* paranoid */ verify( this.l.anchor.next == 0p );
     42                /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) == MAX );
     43                /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) != 0  );
     44                /* paranoid */ verify( this.l.prev == mock_head( this ) );
    4245        } else {
    43                 /* paranoid */ verify( this.anchor.next != 0p );
    44                 /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) != MAX );
    45                 /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) != 0  );
    46                 /* paranoid */ verify( this.prev != mock_head( this ) );
     46                /* paranoid */ verify( this.l.anchor.next != 0p );
     47                /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) != MAX );
     48                /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) != 0  );
     49                /* paranoid */ verify( this.l.prev != mock_head( this ) );
    4750        }
    4851
    4952        // Get the relevant nodes locally
    50         this.prev->link.next = node;
    51         __atomic_store_n(&this.prev->link.ts, rdtscl(), __ATOMIC_RELAXED);
    52         this.prev = node;
     53        this.l.prev->link.next = node;
     54        __atomic_store_n(&this.l.prev->link.ts, rdtscl(), __ATOMIC_RELAXED);
     55        this.l.prev = node;
    5356        #if !defined(__CFA_NO_STATISTICS__)
    54                 this.cnt++;
     57                this.l.cnt++;
    5558        #endif
    5659}
     
    6063// returns true of lane was empty before push, false otherwise
    6164static inline [* thread$, unsigned long long] pop( __intrusive_lane_t & this ) {
    62         /* paranoid */ verify( this.lock );
    63         /* paranoid */ verify( this.anchor.next != 0p );
    64         /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) != MAX );
    65         /* paranoid */ verify( __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED) != 0   );
     65        /* paranoid */ verify( this.l.lock );
     66        /* paranoid */ verify( this.l.anchor.next != 0p );
     67        /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) != MAX );
     68        /* paranoid */ verify( __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED) != 0   );
    6669
    6770        // Get the relevant nodes locally
    68         thread$ * node = this.anchor.next;
    69         this.anchor.next = node->link.next;
    70         __atomic_store_n(&this.anchor.ts, __atomic_load_n(&node->link.ts, __ATOMIC_RELAXED), __ATOMIC_RELAXED);
    71         bool is_empty = this.anchor.next == 0p;
     71        thread$ * node = this.l.anchor.next;
     72        this.l.anchor.next = node->link.next;
     73        __atomic_store_n(&this.l.anchor.ts, __atomic_load_n(&node->link.ts, __ATOMIC_RELAXED), __ATOMIC_RELAXED);
     74        bool is_empty = this.l.anchor.next == 0p;
    7275        node->link.next = 0p;
    7376        __atomic_store_n(&node->link.ts, ULLONG_MAX, __ATOMIC_RELAXED);
    7477        #if !defined(__CFA_NO_STATISTICS__)
    75                 this.cnt--;
     78                this.l.cnt--;
    7679        #endif
    7780
    7881        // Update head time stamp
    79         if(is_empty) this.prev = mock_head( this );
     82        if(is_empty) this.l.prev = mock_head( this );
    8083
    81         unsigned long long ats = __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED);
     84        unsigned long long ats = __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED);
    8285        /* paranoid */ verify( node->link.next == 0p );
    8386        /* paranoid */ verify( __atomic_load_n(&node->link.ts , __ATOMIC_RELAXED) == MAX );
     
    9093// Check whether or not list is empty
    9194static inline bool is_empty(__intrusive_lane_t & this) {
    92         return this.anchor.next == 0p;
     95        return this.l.anchor.next == 0p;
    9396}
    9497
     
    9699static inline unsigned long long ts(__intrusive_lane_t & this) {
    97100        // Cannot verify 'emptiness' here since it may not be locked
    98         /* paranoid */ verify(this.anchor.ts != 0);
    99         /* paranoid */ static_assert(__atomic_always_lock_free(sizeof(this.anchor.ts), &this.anchor.ts));
    100         return __atomic_load_n(&this.anchor.ts, __ATOMIC_RELAXED);
     101        /* paranoid */ verify(this.l.anchor.ts != 0);
     102        /* paranoid */ static_assert(__atomic_always_lock_free(sizeof(this.l.anchor.ts), &this.l.anchor.ts));
     103        return __atomic_load_n(&this.l.anchor.ts, __ATOMIC_RELAXED);
    101104}
Note: See TracChangeset for help on using the changeset viewer.