@@ -65,8 +65,8 @@ typedef struct
65
65
pg_atomic_uint32 pss_pid ;
66
66
int pss_cancel_key_len ; /* 0 means no cancellation is possible */
67
67
uint8 pss_cancel_key [MAX_CANCEL_KEY_LENGTH ];
68
- volatile sig_atomic_t pss_signalFlags [ NUM_PROCSIGNALS ];
69
- slock_t pss_mutex ; /* protects the above fields */
68
+ pg_atomic_uint32 pss_signalFlags ; /* bitmask of pending signals */
69
+ slock_t pss_mutex ; /* protects cancel_key fields only */
70
70
71
71
/* Barrier-related fields (not protected by pss_mutex) */
72
72
pg_atomic_uint64 pss_barrierGeneration ;
@@ -105,7 +105,7 @@ struct ProcSignalHeader
105
105
NON_EXEC_STATIC ProcSignalHeader * ProcSignal = NULL ;
106
106
static ProcSignalSlot * MyProcSignalSlot = NULL ;
107
107
108
- static bool CheckProcSignal ( ProcSignalReason reason );
108
+ static bool HasProcSignalFlag ( uint32 flags , ProcSignalReason reason );
109
109
static void CleanupProcSignalState (int status , Datum arg );
110
110
static void ResetProcSignalBarrierBits (uint32 flags );
111
111
@@ -150,7 +150,7 @@ ProcSignalShmemInit(void)
150
150
SpinLockInit (& slot -> pss_mutex );
151
151
pg_atomic_init_u32 (& slot -> pss_pid , 0 );
152
152
slot -> pss_cancel_key_len = 0 ;
153
- MemSet ( slot -> pss_signalFlags , 0 , sizeof ( slot -> pss_signalFlags ) );
153
+ pg_atomic_init_u32 ( & slot -> pss_signalFlags , 0 );
154
154
pg_atomic_init_u64 (& slot -> pss_barrierGeneration , PG_UINT64_MAX );
155
155
pg_atomic_init_u32 (& slot -> pss_barrierCheckMask , 0 );
156
156
ConditionVariableInit (& slot -> pss_barrierCV );
@@ -182,7 +182,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
182
182
old_pss_pid = pg_atomic_read_u32 (& slot -> pss_pid );
183
183
184
184
/* Clear out any leftover signal reasons */
185
- MemSet ( slot -> pss_signalFlags , 0 , NUM_PROCSIGNALS * sizeof ( sig_atomic_t ) );
185
+ pg_atomic_write_u32 ( & slot -> pss_signalFlags , 0 );
186
186
187
187
/*
188
188
* Initialize barrier state. Since we're a brand-new process, there
@@ -212,7 +212,7 @@ ProcSignalInit(const uint8 *cancel_key, int cancel_key_len)
212
212
elog (LOG , "process %d taking over ProcSignal slot %d, but it's not empty" ,
213
213
MyProcPid , MyProcNumber );
214
214
215
- /* Remember slot location for CheckProcSignal */
215
+ /* Remember slot location for HasProcSignalFlag */
216
216
MyProcSignalSlot = slot ;
217
217
218
218
/* Set up to release the slot on process exit */
@@ -294,10 +294,15 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
294
294
if (pg_atomic_read_u32 (& slot -> pss_pid ) == pid )
295
295
{
296
296
/* Atomically set the proper flag */
297
- slot -> pss_signalFlags [reason ] = true;
297
+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
298
+ (uint32 ) 1 << reason );
299
+
298
300
SpinLockRelease (& slot -> pss_mutex );
299
- /* Send signal */
300
- return kill (pid , SIGUSR1 );
301
+ /* Send signal only if there were no pending signals before this. */
302
+ if (oldflags == 0 )
303
+ return kill (pid , SIGUSR1 );
304
+ else
305
+ return 0 ;
301
306
}
302
307
SpinLockRelease (& slot -> pss_mutex );
303
308
}
@@ -322,10 +327,15 @@ SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
322
327
if (pg_atomic_read_u32 (& slot -> pss_pid ) == pid )
323
328
{
324
329
/* Atomically set the proper flag */
325
- slot -> pss_signalFlags [reason ] = true;
330
+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
331
+ (uint32 ) 1 << reason );
332
+
326
333
SpinLockRelease (& slot -> pss_mutex );
327
- /* Send signal */
328
- return kill (pid , SIGUSR1 );
334
+ /* Send signal only if there were no pending signals before this. */
335
+ if (oldflags == 0 )
336
+ return kill (pid , SIGUSR1 );
337
+ else
338
+ return 0 ;
329
339
}
330
340
SpinLockRelease (& slot -> pss_mutex );
331
341
}
@@ -404,9 +414,13 @@ EmitProcSignalBarrier(ProcSignalBarrierType type)
404
414
if (pid != 0 )
405
415
{
406
416
/* see SendProcSignal for details */
407
- slot -> pss_signalFlags [PROCSIG_BARRIER ] = true;
417
+ uint32 oldflags = pg_atomic_fetch_or_u32 (& slot -> pss_signalFlags ,
418
+ (uint32 ) 1 << PROCSIG_BARRIER );
419
+
408
420
SpinLockRelease (& slot -> pss_mutex );
409
- kill (pid , SIGUSR1 );
421
+ /* Send signal only if there were no pending signals before this. */
422
+ if (oldflags == 0 )
423
+ kill (pid , SIGUSR1 );
410
424
}
411
425
else
412
426
SpinLockRelease (& slot -> pss_mutex );
@@ -641,30 +655,13 @@ ResetProcSignalBarrierBits(uint32 flags)
641
655
}
642
656
643
657
/*
644
- * CheckProcSignal - check to see if a particular reason has been
645
- * signaled, and clear the signal flag. Should be called after receiving
646
- * SIGUSR1.
658
+ * HasProcSignalFlag - check to see if a particular reason has been
659
+ * signaled in the given flags bitmask.
647
660
*/
648
661
static bool
649
- CheckProcSignal ( ProcSignalReason reason )
662
+ HasProcSignalFlag ( uint32 flags , ProcSignalReason reason )
650
663
{
651
- volatile ProcSignalSlot * slot = MyProcSignalSlot ;
652
-
653
- if (slot != NULL )
654
- {
655
- /*
656
- * Careful here --- don't clear flag if we haven't seen it set.
657
- * pss_signalFlags is of type "volatile sig_atomic_t" to allow us to
658
- * read it here safely, without holding the spinlock.
659
- */
660
- if (slot -> pss_signalFlags [reason ])
661
- {
662
- slot -> pss_signalFlags [reason ] = false;
663
- return true;
664
- }
665
- }
666
-
667
- return false;
664
+ return (flags & ((uint32 ) 1 << reason )) != 0 ;
668
665
}
669
666
670
667
/*
@@ -673,46 +670,54 @@ CheckProcSignal(ProcSignalReason reason)
673
670
void
674
671
procsignal_sigusr1_handler (SIGNAL_ARGS )
675
672
{
676
- if (CheckProcSignal (PROCSIG_CATCHUP_INTERRUPT ))
673
+ uint32 flags ;
674
+
675
+ /* Atomically consume all pending signals */
676
+ if (MyProcSignalSlot )
677
+ flags = pg_atomic_exchange_u32 (& MyProcSignalSlot -> pss_signalFlags , 0 );
678
+ else
679
+ flags = 0 ;
680
+
681
+ if (HasProcSignalFlag (flags , PROCSIG_CATCHUP_INTERRUPT ))
677
682
HandleCatchupInterrupt ();
678
683
679
- if (CheckProcSignal ( PROCSIG_NOTIFY_INTERRUPT ))
684
+ if (HasProcSignalFlag ( flags , PROCSIG_NOTIFY_INTERRUPT ))
680
685
HandleNotifyInterrupt ();
681
686
682
- if (CheckProcSignal ( PROCSIG_PARALLEL_MESSAGE ))
687
+ if (HasProcSignalFlag ( flags , PROCSIG_PARALLEL_MESSAGE ))
683
688
HandleParallelMessageInterrupt ();
684
689
685
- if (CheckProcSignal ( PROCSIG_WALSND_INIT_STOPPING ))
690
+ if (HasProcSignalFlag ( flags , PROCSIG_WALSND_INIT_STOPPING ))
686
691
HandleWalSndInitStopping ();
687
692
688
- if (CheckProcSignal ( PROCSIG_BARRIER ))
693
+ if (HasProcSignalFlag ( flags , PROCSIG_BARRIER ))
689
694
HandleProcSignalBarrierInterrupt ();
690
695
691
- if (CheckProcSignal ( PROCSIG_LOG_MEMORY_CONTEXT ))
696
+ if (HasProcSignalFlag ( flags , PROCSIG_LOG_MEMORY_CONTEXT ))
692
697
HandleLogMemoryContextInterrupt ();
693
698
694
- if (CheckProcSignal ( PROCSIG_PARALLEL_APPLY_MESSAGE ))
699
+ if (HasProcSignalFlag ( flags , PROCSIG_PARALLEL_APPLY_MESSAGE ))
695
700
HandleParallelApplyMessageInterrupt ();
696
701
697
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_DATABASE ))
702
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_DATABASE ))
698
703
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_DATABASE );
699
704
700
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_TABLESPACE ))
705
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_TABLESPACE ))
701
706
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_TABLESPACE );
702
707
703
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_LOCK ))
708
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_LOCK ))
704
709
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_LOCK );
705
710
706
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_SNAPSHOT ))
711
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_SNAPSHOT ))
707
712
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_SNAPSHOT );
708
713
709
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT ))
714
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT ))
710
715
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_LOGICALSLOT );
711
716
712
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK ))
717
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK ))
713
718
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK );
714
719
715
- if (CheckProcSignal ( PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ))
720
+ if (HasProcSignalFlag ( flags , PROCSIG_RECOVERY_CONFLICT_BUFFERPIN ))
716
721
HandleRecoveryConflictInterrupt (PROCSIG_RECOVERY_CONFLICT_BUFFERPIN );
717
722
718
723
SetLatch (MyLatch );
0 commit comments