@@ -211,7 +211,7 @@ DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
211211static bool
212212bitmap_is_full (bitmap_t bits )
213213{
214- return (bits == BITMAP_ALL_ONES );
214+ return atomic_load_explicit (bits , memory_order_relaxed ) == BITMAP_ALL_ONES );
215215}
216216
217217#define NO_BITS_WERE_UNSET (UINT_MAX)
@@ -220,7 +220,7 @@ bitmap_is_full(bitmap_t bits)
220220// allowed to be set.
221221DISPATCH_ALWAYS_INLINE_NDEBUG
222222static unsigned int
223- bitmap_set_first_unset_bit_upto_index (volatile bitmap_t * bitmap ,
223+ bitmap_set_first_unset_bit_upto_index (bitmap_t * bitmap ,
224224 unsigned int max_index )
225225{
226226 // No barriers needed in acquire path: the just-allocated
@@ -233,7 +233,7 @@ bitmap_set_first_unset_bit_upto_index(volatile bitmap_t *bitmap,
233233
234234DISPATCH_ALWAYS_INLINE
235235static unsigned int
236- bitmap_set_first_unset_bit (volatile bitmap_t * bitmap )
236+ bitmap_set_first_unset_bit (bitmap_t * bitmap )
237237{
238238 return bitmap_set_first_unset_bit_upto_index (bitmap , UINT_MAX );
239239}
@@ -244,7 +244,7 @@ bitmap_set_first_unset_bit(volatile bitmap_t *bitmap)
244244// Return true if this bit was the last in the bitmap, and it is now all zeroes
245245DISPATCH_ALWAYS_INLINE_NDEBUG
246246static bool
247- bitmap_clear_bit (volatile bitmap_t * bitmap , unsigned int index ,
247+ bitmap_clear_bit (bitmap_t * bitmap , unsigned int index ,
248248 bool exclusively )
249249{
250250#if DISPATCH_DEBUG
@@ -267,8 +267,8 @@ bitmap_clear_bit(volatile bitmap_t *bitmap, unsigned int index,
267267
268268DISPATCH_ALWAYS_INLINE_NDEBUG
269269static void
270- mark_bitmap_as_full_if_still_full (volatile bitmap_t * supermap ,
271- unsigned int bitmap_index , volatile bitmap_t * bitmap )
270+ mark_bitmap_as_full_if_still_full (bitmap_t * supermap ,
271+ unsigned int bitmap_index , bitmap_t * bitmap )
272272{
273273#if DISPATCH_DEBUG
274274 dispatch_assert (bitmap_index < BITMAPS_PER_SUPERMAP );
@@ -321,12 +321,12 @@ alloc_continuation_from_magazine(struct dispatch_magazine_s *magazine)
321321 unsigned int s , b , index ;
322322
323323 for (s = 0 ; s < SUPERMAPS_PER_MAGAZINE ; s ++ ) {
324- volatile bitmap_t * supermap = supermap_address (magazine , s );
324+ bitmap_t * supermap = supermap_address (magazine , s );
325325 if (bitmap_is_full (* supermap )) {
326326 continue ;
327327 }
328328 for (b = 0 ; b < BITMAPS_PER_SUPERMAP ; b ++ ) {
329- volatile bitmap_t * bitmap = bitmap_address (magazine , s , b );
329+ bitmap_t * bitmap = bitmap_address (magazine , s , b );
330330 index = bitmap_set_first_unset_bit (bitmap );
331331 if (index != NO_BITS_WERE_UNSET ) {
332332 set_last_found_page (
@@ -530,44 +530,37 @@ _dispatch_alloc_maybe_madvise_page(dispatch_continuation_t c)
530530 // page can't be madvised; maybe it contains non-continuations
531531 return ;
532532 }
533- // Are all the continuations in this page unallocated?
534- volatile bitmap_t * page_bitmaps ;
533+
534+ bitmap_t * page_bitmaps ;
535535 get_maps_and_indices_for_continuation ((dispatch_continuation_t )page , NULL ,
536- NULL , ( bitmap_t * * ) & page_bitmaps , NULL );
536+ NULL , & page_bitmaps , NULL );
537537 unsigned int i ;
538+
539+ // Try to take ownership of them all, and if it fails, unlock the ones we locked
538540 for (i = 0 ; i < BITMAPS_PER_PAGE ; i ++ ) {
539- if (page_bitmaps [i ] != 0 ) {
540- return ;
541- }
542- }
543- // They are all unallocated, so we could madvise the page. Try to
544- // take ownership of them all.
545- int last_locked = 0 ;
546- do {
547- if (!os_atomic_cmpxchg (& page_bitmaps [last_locked ], BITMAP_C (0 ),
541+ if (!os_atomic_cmpxchg (& page_bitmaps [i ], BITMAP_C (0 ),
548542 BITMAP_ALL_ONES , relaxed )) {
549543 // We didn't get one; since there is a cont allocated in
550544 // the page, we can't madvise. Give up and unlock all.
551- goto unlock ;
545+ break ;
552546 }
553- } while (++ last_locked < (signed )BITMAPS_PER_PAGE );
547+ }
548+
549+ if (i >= BITMAPS_PER_PAGE ) {
554550#if DISPATCH_DEBUG
555- // fprintf(stderr, "%s: madvised page %p for cont %p (next = %p), "
556- // "[%u+1]=%u bitmaps at %p\n", __func__, page, c, c->do_next,
557- // last_locked-1, BITMAPS_PER_PAGE, &page_bitmaps[0]);
558- // Scribble to expose use-after-free bugs
559- // madvise (syscall) flushes these stores
560- memset (page , DISPATCH_ALLOCATOR_SCRIBBLE , DISPATCH_ALLOCATOR_PAGE_SIZE );
551+ // fprintf(stderr, "%s: madvised page %p for cont %p (next = %p), "
552+ // "[%u+1]=%u bitmaps at %p\n", __func__, page, c, c->do_next,
553+ // last_locked-1, BITMAPS_PER_PAGE, &page_bitmaps[0]);
554+ // Scribble to expose use-after-free bugs
555+ // madvise (syscall) flushes these stores
556+ memset (page , DISPATCH_ALLOCATOR_SCRIBBLE , DISPATCH_ALLOCATOR_PAGE_SIZE );
561557#endif
562- (void )dispatch_assume_zero (madvise (page , DISPATCH_ALLOCATOR_PAGE_SIZE ,
563- MADV_FREE ));
564-
565- unlock :
566- while (last_locked > 1 ) {
567- page_bitmaps [-- last_locked ] = BITMAP_C (0 );
558+ // madvise the page
559+ (void )dispatch_assume_zero (madvise (page , DISPATCH_ALLOCATOR_PAGE_SIZE ,
560+ MADV_FREE ));
568561 }
569- if ( last_locked ) {
570- os_atomic_store (& page_bitmaps [0 ], BITMAP_C (0 ), relaxed );
562+ while ( i ) {
563+ os_atomic_store (& page_bitmaps [-- i ], BITMAP_C (0 ), relaxed );
571564 }
572565 return ;
573566}
0 commit comments