@@ -663,7 +663,7 @@ runfinq(void)
663
663
void
664
664
runtime·markallocated (void * v , uintptr n , bool noptr )
665
665
{
666
- uintptr * b , bits , off , shift ;
666
+ uintptr * b , obits , bits , off , shift ;
667
667
668
668
if (0 )
669
669
runtime·printf ("markallocated %p+%p\n" , v , n );
@@ -675,17 +675,27 @@ runtime·markallocated(void *v, uintptr n, bool noptr)
675
675
b = (uintptr * )runtime·mheap .arena_start - off /wordsPerBitmapWord - 1 ;
676
676
shift = off % wordsPerBitmapWord ;
677
677
678
- bits = (* b & ~(bitMask <<shift )) | (bitAllocated <<shift );
679
- if (noptr )
680
- bits |= bitNoPointers <<shift ;
681
- * b = bits ;
678
+ for (;;) {
679
+ obits = * b ;
680
+ bits = (obits & ~(bitMask <<shift )) | (bitAllocated <<shift );
681
+ if (noptr )
682
+ bits |= bitNoPointers <<shift ;
683
+ if (runtime·gomaxprocs == 1 ) {
684
+ * b = bits ;
685
+ break ;
686
+ } else {
687
+ // gomaxprocs > 1: use atomic op
688
+ if (runtime·casp ((void * * )b , (void * )obits , (void * )bits ))
689
+ break ;
690
+ }
691
+ }
682
692
}
683
693
684
694
// mark the block at v of size n as freed.
685
695
void
686
696
runtime·markfreed (void * v , uintptr n )
687
697
{
688
- uintptr * b , off , shift ;
698
+ uintptr * b , obits , bits , off , shift ;
689
699
690
700
if (0 )
691
701
runtime·printf ("markallocated %p+%p\n" , v , n );
@@ -697,7 +707,18 @@ runtime·markfreed(void *v, uintptr n)
697
707
b = (uintptr * )runtime·mheap .arena_start - off /wordsPerBitmapWord - 1 ;
698
708
shift = off % wordsPerBitmapWord ;
699
709
700
- * b = (* b & ~(bitMask <<shift )) | (bitBlockBoundary <<shift );
710
+ for (;;) {
711
+ obits = * b ;
712
+ bits = (obits & ~(bitMask <<shift )) | (bitBlockBoundary <<shift );
713
+ if (runtime·gomaxprocs == 1 ) {
714
+ * b = bits ;
715
+ break ;
716
+ } else {
717
+ // gomaxprocs > 1: use atomic op
718
+ if (runtime·casp ((void * * )b , (void * )obits , (void * )bits ))
719
+ break ;
720
+ }
721
+ }
701
722
}
702
723
703
724
// check that the block at v of size n is marked freed.
@@ -739,6 +760,10 @@ runtime·markspan(void *v, uintptr size, uintptr n, bool leftover)
739
760
if (leftover ) // mark a boundary just past end of last block too
740
761
n ++ ;
741
762
for (; n -- > 0 ; p += size ) {
763
+ // Okay to use non-atomic ops here, because we control
764
+ // the entire span, and each bitmap word has bits for only
765
+ // one span, so no other goroutines are changing these
766
+ // bitmap words.
742
767
off = (uintptr * )p - (uintptr * )runtime·mheap .arena_start ; // word offset
743
768
b = (uintptr * )runtime·mheap .arena_start - off /wordsPerBitmapWord - 1 ;
744
769
shift = off % wordsPerBitmapWord ;
@@ -763,6 +788,10 @@ runtime·unmarkspan(void *v, uintptr n)
763
788
n /= PtrSize ;
764
789
if (n %wordsPerBitmapWord != 0 )
765
790
runtime·throw ("unmarkspan: unaligned length" );
791
+ // Okay to use non-atomic ops here, because we control
792
+ // the entire span, and each bitmap word has bits for only
793
+ // one span, so no other goroutines are changing these
794
+ // bitmap words.
766
795
n /= wordsPerBitmapWord ;
767
796
while (n -- > 0 )
768
797
* b -- = 0 ;
@@ -783,13 +812,24 @@ runtime·blockspecial(void *v)
783
812
void
784
813
runtime·setblockspecial (void * v )
785
814
{
786
- uintptr * b , off , shift ;
815
+ uintptr * b , off , shift , bits , obits ;
787
816
788
817
off = (uintptr * )v - (uintptr * )runtime·mheap .arena_start ;
789
818
b = (uintptr * )runtime·mheap .arena_start - off /wordsPerBitmapWord - 1 ;
790
819
shift = off % wordsPerBitmapWord ;
791
820
792
- * b |= bitSpecial <<shift ;
821
+ for (;;) {
822
+ obits = * b ;
823
+ bits = obits | (bitSpecial <<shift );
824
+ if (runtime·gomaxprocs == 1 ) {
825
+ * b = bits ;
826
+ break ;
827
+ } else {
828
+ // gomaxprocs > 1: use atomic op
829
+ if (runtime·casp ((void * * )b , (void * )obits , (void * )bits ))
830
+ break ;
831
+ }
832
+ }
793
833
}
794
834
795
835
void
0 commit comments