134
134
* SerializableXactHashLock
135
135
* - Protects both PredXact and SerializableXidHash.
136
136
*
137
+ * SerialControlLock
138
+ * - Protects SerialControlData members
139
+ *
140
+ * SerialSLRULock
141
+ * - Protects SerialSlruCtl
137
142
*
138
143
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
139
144
* Portions Copyright (c) 1994, Regents of the University of California
@@ -828,9 +833,11 @@ SerialInit(void)
828
833
/*
829
834
* Set control information to reflect empty SLRU.
830
835
*/
836
+ LWLockAcquire (SerialControlLock , LW_EXCLUSIVE );
831
837
serialControl -> headPage = -1 ;
832
838
serialControl -> headXid = InvalidTransactionId ;
833
839
serialControl -> tailXid = InvalidTransactionId ;
840
+ LWLockRelease (SerialControlLock );
834
841
}
835
842
}
836
843
@@ -852,7 +859,12 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
852
859
853
860
targetPage = SerialPage (xid );
854
861
855
- LWLockAcquire (SerialSLRULock , LW_EXCLUSIVE );
862
+ /*
863
+ * In this routine, we must hold both SerialControlLock and SerialSLRULock
864
+ * simultaneously while making the SLRU data catch up with the new state
865
+ * that we determine.
866
+ */
867
+ LWLockAcquire (SerialControlLock , LW_EXCLUSIVE );
856
868
857
869
/*
858
870
* If no serializable transactions are active, there shouldn't be anything
@@ -886,6 +898,8 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
886
898
if (isNewPage )
887
899
serialControl -> headPage = targetPage ;
888
900
901
+ LWLockAcquire (SerialSLRULock , LW_EXCLUSIVE );
902
+
889
903
if (isNewPage )
890
904
{
891
905
/* Initialize intervening pages. */
@@ -903,6 +917,7 @@ SerialAdd(TransactionId xid, SerCommitSeqNo minConflictCommitSeqNo)
903
917
SerialSlruCtl -> shared -> page_dirty [slotno ] = true;
904
918
905
919
LWLockRelease (SerialSLRULock );
920
+ LWLockRelease (SerialControlLock );
906
921
}
907
922
908
923
/*
@@ -920,10 +935,10 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid)
920
935
921
936
Assert (TransactionIdIsValid (xid ));
922
937
923
- LWLockAcquire (SerialSLRULock , LW_SHARED );
938
+ LWLockAcquire (SerialControlLock , LW_SHARED );
924
939
headXid = serialControl -> headXid ;
925
940
tailXid = serialControl -> tailXid ;
926
- LWLockRelease (SerialSLRULock );
941
+ LWLockRelease (SerialControlLock );
927
942
928
943
if (!TransactionIdIsValid (headXid ))
929
944
return 0 ;
@@ -954,7 +969,7 @@ SerialGetMinConflictCommitSeqNo(TransactionId xid)
954
969
static void
955
970
SerialSetActiveSerXmin (TransactionId xid )
956
971
{
957
- LWLockAcquire (SerialSLRULock , LW_EXCLUSIVE );
972
+ LWLockAcquire (SerialControlLock , LW_EXCLUSIVE );
958
973
959
974
/*
960
975
* When no sxacts are active, nothing overlaps, set the xid values to
@@ -966,7 +981,7 @@ SerialSetActiveSerXmin(TransactionId xid)
966
981
{
967
982
serialControl -> tailXid = InvalidTransactionId ;
968
983
serialControl -> headXid = InvalidTransactionId ;
969
- LWLockRelease (SerialSLRULock );
984
+ LWLockRelease (SerialControlLock );
970
985
return ;
971
986
}
972
987
@@ -984,7 +999,7 @@ SerialSetActiveSerXmin(TransactionId xid)
984
999
{
985
1000
serialControl -> tailXid = xid ;
986
1001
}
987
- LWLockRelease (SerialSLRULock );
1002
+ LWLockRelease (SerialControlLock );
988
1003
return ;
989
1004
}
990
1005
@@ -993,7 +1008,7 @@ SerialSetActiveSerXmin(TransactionId xid)
993
1008
994
1009
serialControl -> tailXid = xid ;
995
1010
996
- LWLockRelease (SerialSLRULock );
1011
+ LWLockRelease (SerialControlLock );
997
1012
}
998
1013
999
1014
/*
@@ -1007,12 +1022,12 @@ CheckPointPredicate(void)
1007
1022
{
1008
1023
int truncateCutoffPage ;
1009
1024
1010
- LWLockAcquire (SerialSLRULock , LW_EXCLUSIVE );
1025
+ LWLockAcquire (SerialControlLock , LW_EXCLUSIVE );
1011
1026
1012
1027
/* Exit quickly if the SLRU is currently not in use. */
1013
1028
if (serialControl -> headPage < 0 )
1014
1029
{
1015
- LWLockRelease (SerialSLRULock );
1030
+ LWLockRelease (SerialControlLock );
1016
1031
return ;
1017
1032
}
1018
1033
@@ -1072,9 +1087,13 @@ CheckPointPredicate(void)
1072
1087
serialControl -> headPage = -1 ;
1073
1088
}
1074
1089
1075
- LWLockRelease (SerialSLRULock );
1090
+ LWLockRelease (SerialControlLock );
1076
1091
1077
- /* Truncate away pages that are no longer required */
1092
+ /*
1093
+ * Truncate away pages that are no longer required. Note that no
1094
+ * additional locking is required, because this is only called as part of
1095
+ * a checkpoint, and the validity limits have already been determined.
1096
+ */
1078
1097
SimpleLruTruncate (SerialSlruCtl , truncateCutoffPage );
1079
1098
1080
1099
/*
0 commit comments