3
3
#include "Python.h"
4
4
#include "pycore_abstract.h" // _PyIndex_Check()
5
5
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
6
+ #include "pycore_pyatomic_ft_wrappers.h"
6
7
#include "pycore_interp.h" // PyInterpreterState.list
7
8
#include "pycore_list.h" // struct _Py_list_freelist, _PyListIterObject
8
9
#include "pycore_long.h" // _PyLong_DigitCount
@@ -20,14 +21,6 @@ class list "PyListObject *" "&PyList_Type"
20
21
21
22
_Py_DECLARE_STR (list_err , "list index out of range" );
22
23
23
- #ifdef Py_GIL_DISABLED
24
- # define LOAD_SSIZE (value ) _Py_atomic_load_ssize_relaxed(&value)
25
- # define STORE_SSIZE (value , new_value ) _Py_atomic_store_ssize_relaxed(&value, new_value)
26
- #else
27
- # define LOAD_SSIZE (value ) value
28
- # define STORE_SSIZE (value , new_value ) value = new_value
29
- #endif
30
-
31
24
#ifdef WITH_FREELISTS
32
25
static struct _Py_list_freelist *
33
26
get_list_freelist (void )
@@ -563,20 +556,12 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
563
556
}
564
557
565
558
static PyObject *
566
- list_concat ( PyObject * aa , PyObject * bb )
559
+ list_concat_lock_held ( PyListObject * a , PyListObject * b )
567
560
{
568
- PyListObject * a = (PyListObject * )aa ;
569
561
Py_ssize_t size ;
570
562
Py_ssize_t i ;
571
563
PyObject * * src , * * dest ;
572
564
PyListObject * np ;
573
- if (!PyList_Check (bb )) {
574
- PyErr_Format (PyExc_TypeError ,
575
- "can only concatenate list (not \"%.200s\") to list" ,
576
- Py_TYPE (bb )-> tp_name );
577
- return NULL ;
578
- }
579
- #define b ((PyListObject *)bb)
580
565
assert ((size_t )Py_SIZE (a ) + (size_t )Py_SIZE (b ) < PY_SSIZE_T_MAX );
581
566
size = Py_SIZE (a ) + Py_SIZE (b );
582
567
if (size == 0 ) {
@@ -590,23 +575,39 @@ list_concat(PyObject *aa, PyObject *bb)
590
575
dest = np -> ob_item ;
591
576
for (i = 0 ; i < Py_SIZE (a ); i ++ ) {
592
577
PyObject * v = src [i ];
593
- dest [i ] = Py_NewRef (v );
578
+ FT_ATOMIC_STORE_PTR_RELAXED ( dest [i ], Py_NewRef (v ) );
594
579
}
595
580
src = b -> ob_item ;
596
581
dest = np -> ob_item + Py_SIZE (a );
597
582
for (i = 0 ; i < Py_SIZE (b ); i ++ ) {
598
583
PyObject * v = src [i ];
599
- dest [i ] = Py_NewRef (v );
584
+ FT_ATOMIC_STORE_PTR_RELAXED ( dest [i ], Py_NewRef (v ) );
600
585
}
601
586
Py_SET_SIZE (np , size );
602
587
return (PyObject * )np ;
603
- #undef b
604
588
}
605
589
606
590
static PyObject *
607
- list_repeat (PyObject * aa , Py_ssize_t n )
591
+ list_concat (PyObject * aa , PyObject * bb )
608
592
{
593
+ if (!PyList_Check (bb )) {
594
+ PyErr_Format (PyExc_TypeError ,
595
+ "can only concatenate list (not \"%.200s\") to list" ,
596
+ Py_TYPE (bb )-> tp_name );
597
+ return NULL ;
598
+ }
609
599
PyListObject * a = (PyListObject * )aa ;
600
+ PyListObject * b = (PyListObject * )bb ;
601
+ PyObject * ret ;
602
+ Py_BEGIN_CRITICAL_SECTION2 (a , b );
603
+ ret = list_concat_lock_held (a , b );
604
+ Py_END_CRITICAL_SECTION2 ();
605
+ return ret ;
606
+ }
607
+
608
+ static PyObject *
609
+ list_repeat_lock_held (PyListObject * a , Py_ssize_t n )
610
+ {
610
611
const Py_ssize_t input_size = Py_SIZE (a );
611
612
if (input_size == 0 || n <= 0 )
612
613
return PyList_New (0 );
@@ -626,15 +627,15 @@ list_repeat(PyObject *aa, Py_ssize_t n)
626
627
_Py_RefcntAdd (elem , n );
627
628
PyObject * * dest_end = dest + output_size ;
628
629
while (dest < dest_end ) {
629
- * dest ++ = elem ;
630
+ FT_ATOMIC_STORE_PTR_RELAXED ( * dest ++ , elem ) ;
630
631
}
631
632
}
632
633
else {
633
634
PyObject * * src = a -> ob_item ;
634
635
PyObject * * src_end = src + input_size ;
635
636
while (src < src_end ) {
636
637
_Py_RefcntAdd (* src , n );
637
- * dest ++ = * src ++ ;
638
+ FT_ATOMIC_STORE_PTR_RELAXED ( * dest ++ , * src ++ ) ;
638
639
}
639
640
640
641
_Py_memory_repeat ((char * )np -> ob_item , sizeof (PyObject * )* output_size ,
@@ -645,6 +646,17 @@ list_repeat(PyObject *aa, Py_ssize_t n)
645
646
return (PyObject * ) np ;
646
647
}
647
648
649
+ static PyObject *
650
+ list_repeat (PyObject * aa , Py_ssize_t n )
651
+ {
652
+ PyObject * ret ;
653
+ PyListObject * a = (PyListObject * )aa ;
654
+ Py_BEGIN_CRITICAL_SECTION (a );
655
+ ret = list_repeat_lock_held (a , n );
656
+ Py_END_CRITICAL_SECTION ();
657
+ return ret ;
658
+ }
659
+
648
660
static void
649
661
list_clear (PyListObject * a )
650
662
{
@@ -657,11 +669,12 @@ list_clear(PyListObject *a)
657
669
this list, we make it empty first. */
658
670
Py_ssize_t i = Py_SIZE (a );
659
671
Py_SET_SIZE (a , 0 );
660
- a -> ob_item = NULL ;
672
+ FT_ATOMIC_STORE_PTR_RELEASE ( a -> ob_item , NULL ) ;
661
673
a -> allocated = 0 ;
662
674
while (-- i >= 0 ) {
663
675
Py_XDECREF (items [i ]);
664
676
}
677
+ // TODO: Use QSBR technique, if the list is shared between threads,
665
678
PyMem_Free (items );
666
679
667
680
// Note that there is no guarantee that the list is actually empty
@@ -798,9 +811,8 @@ PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
798
811
}
799
812
800
813
static PyObject *
801
- list_inplace_repeat ( PyObject * _self , Py_ssize_t n )
814
+ list_inplace_repeat_lock_held ( PyListObject * self , Py_ssize_t n )
802
815
{
803
- PyListObject * self = (PyListObject * )_self ;
804
816
Py_ssize_t input_size = PyList_GET_SIZE (self );
805
817
if (input_size == 0 || n == 1 ) {
806
818
return Py_NewRef (self );
@@ -829,21 +841,51 @@ list_inplace_repeat(PyObject *_self, Py_ssize_t n)
829
841
return Py_NewRef (self );
830
842
}
831
843
844
+ static PyObject *
845
+ list_inplace_repeat (PyObject * _self , Py_ssize_t n )
846
+ {
847
+ PyObject * ret ;
848
+ PyListObject * self = (PyListObject * ) _self ;
849
+ Py_BEGIN_CRITICAL_SECTION (self );
850
+ ret = list_inplace_repeat_lock_held (self , n );
851
+ Py_END_CRITICAL_SECTION ();
852
+ return ret ;
853
+ }
854
+
832
855
static int
833
- list_ass_item ( PyObject * aa , Py_ssize_t i , PyObject * v )
856
+ list_ass_item_lock_held ( PyListObject * a , Py_ssize_t i , PyObject * v )
834
857
{
835
- PyListObject * a = (PyListObject * )aa ;
836
858
if (!valid_index (i , Py_SIZE (a ))) {
837
859
PyErr_SetString (PyExc_IndexError ,
838
860
"list assignment index out of range" );
839
861
return -1 ;
840
862
}
841
- if (v == NULL )
842
- return list_ass_slice (a , i , i + 1 , v );
843
- Py_SETREF (a -> ob_item [i ], Py_NewRef (v ));
863
+ PyObject * tmp = a -> ob_item [i ];
864
+ if (v == NULL ) {
865
+ Py_ssize_t size = Py_SIZE (a );
866
+ for (Py_ssize_t idx = i ; idx < size - 1 ; idx ++ ) {
867
+ FT_ATOMIC_STORE_PTR_RELAXED (a -> ob_item [idx ], a -> ob_item [idx + 1 ]);
868
+ }
869
+ Py_SET_SIZE (a , size - 1 );
870
+ }
871
+ else {
872
+ FT_ATOMIC_STORE_PTR_RELEASE (a -> ob_item [i ], Py_NewRef (v ));
873
+ }
874
+ Py_DECREF (tmp );
844
875
return 0 ;
845
876
}
846
877
878
+ static int
879
+ list_ass_item (PyObject * aa , Py_ssize_t i , PyObject * v )
880
+ {
881
+ int ret ;
882
+ PyListObject * a = (PyListObject * )aa ;
883
+ Py_BEGIN_CRITICAL_SECTION (a );
884
+ ret = list_ass_item_lock_held (a , i , v );
885
+ Py_END_CRITICAL_SECTION ();
886
+ return ret ;
887
+ }
888
+
847
889
/*[clinic input]
848
890
@critical_section
849
891
list.insert
@@ -2979,7 +3021,7 @@ list___sizeof___impl(PyListObject *self)
2979
3021
/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
2980
3022
{
2981
3023
size_t res = _PyObject_SIZE (Py_TYPE (self ));
2982
- Py_ssize_t allocated = LOAD_SSIZE (self -> allocated );
3024
+ Py_ssize_t allocated = FT_ATOMIC_LOAD_SSIZE_RELAXED (self -> allocated );
2983
3025
res += (size_t )allocated * sizeof (void * );
2984
3026
return PyLong_FromSize_t (res );
2985
3027
}
@@ -3382,23 +3424,23 @@ static PyObject *
3382
3424
listiter_next (PyObject * self )
3383
3425
{
3384
3426
_PyListIterObject * it = (_PyListIterObject * )self ;
3385
- Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3427
+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (it -> it_index );
3386
3428
if (index < 0 ) {
3387
3429
return NULL ;
3388
3430
}
3389
3431
3390
3432
PyObject * item = list_get_item_ref (it -> it_seq , index );
3391
3433
if (item == NULL ) {
3392
3434
// out-of-bounds
3393
- STORE_SSIZE (it -> it_index , -1 );
3435
+ FT_ATOMIC_STORE_SSIZE_RELAXED (it -> it_index , -1 );
3394
3436
#ifndef Py_GIL_DISABLED
3395
3437
PyListObject * seq = it -> it_seq ;
3396
3438
it -> it_seq = NULL ;
3397
3439
Py_DECREF (seq );
3398
3440
#endif
3399
3441
return NULL ;
3400
3442
}
3401
- STORE_SSIZE (it -> it_index , index + 1 );
3443
+ FT_ATOMIC_STORE_SSIZE_RELAXED (it -> it_index , index + 1 );
3402
3444
return item ;
3403
3445
}
3404
3446
@@ -3407,7 +3449,7 @@ listiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
3407
3449
{
3408
3450
assert (self != NULL );
3409
3451
_PyListIterObject * it = (_PyListIterObject * )self ;
3410
- Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3452
+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (it -> it_index );
3411
3453
if (index >= 0 ) {
3412
3454
Py_ssize_t len = PyList_GET_SIZE (it -> it_seq ) - index ;
3413
3455
if (len >= 0 )
@@ -3537,7 +3579,7 @@ listreviter_next(PyObject *self)
3537
3579
{
3538
3580
listreviterobject * it = (listreviterobject * )self ;
3539
3581
assert (it != NULL );
3540
- Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3582
+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (it -> it_index );
3541
3583
if (index < 0 ) {
3542
3584
return NULL ;
3543
3585
}
@@ -3546,10 +3588,10 @@ listreviter_next(PyObject *self)
3546
3588
assert (PyList_Check (seq ));
3547
3589
PyObject * item = list_get_item_ref (seq , index );
3548
3590
if (item != NULL ) {
3549
- STORE_SSIZE (it -> it_index , index - 1 );
3591
+ FT_ATOMIC_STORE_SSIZE_RELAXED (it -> it_index , index - 1 );
3550
3592
return item ;
3551
3593
}
3552
- STORE_SSIZE (it -> it_index , -1 );
3594
+ FT_ATOMIC_STORE_SSIZE_RELAXED (it -> it_index , -1 );
3553
3595
#ifndef Py_GIL_DISABLED
3554
3596
it -> it_seq = NULL ;
3555
3597
Py_DECREF (seq );
@@ -3561,7 +3603,7 @@ static PyObject *
3561
3603
listreviter_len (PyObject * self , PyObject * Py_UNUSED (ignored ))
3562
3604
{
3563
3605
listreviterobject * it = (listreviterobject * )self ;
3564
- Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3606
+ Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED (it -> it_index );
3565
3607
Py_ssize_t len = index + 1 ;
3566
3608
if (it -> it_seq == NULL || PyList_GET_SIZE (it -> it_seq ) < len )
3567
3609
len = 0 ;
0 commit comments