@@ -73,6 +73,22 @@ int fpm_scoreboard_init_main(void)
7373 return 0 ;
7474}
7575
76+ static inline void fpm_scoreboard_readers_decrement (struct fpm_scoreboard_s * scoreboard )
77+ {
78+ fpm_spinlock (& scoreboard -> lock , 1 );
79+ if (scoreboard -> reader_count > 0 ) {
80+ scoreboard -> reader_count -= 1 ;
81+ }
82+ #ifdef PHP_FPM_ZLOG_TRACE
83+ unsigned int current_reader_count = scoreboard -> reader_count ;
84+ #endif
85+ fpm_unlock (scoreboard -> lock );
86+ #ifdef PHP_FPM_ZLOG_TRACE
87+ /* this is useful for debugging but currently needs to be hidden as external logger would always log it */
88+ zlog (ZLOG_DEBUG , "scoreboard: for proc %d reader decremented to value %u" , getpid (), current_reader_count );
89+ #endif
90+ }
91+
7692static struct fpm_scoreboard_s * fpm_scoreboard_get_for_update (struct fpm_scoreboard_s * scoreboard ) /* {{{ */
7793{
7894 if (!scoreboard ) {
@@ -93,7 +109,33 @@ void fpm_scoreboard_update_begin(struct fpm_scoreboard_s *scoreboard) /* {{{ */
93109 return ;
94110 }
95111
96- fpm_spinlock (& scoreboard -> lock , 0 );
112+ int retries = 0 ;
113+ while (1 ) {
114+ fpm_spinlock (& scoreboard -> lock , 1 );
115+ if (scoreboard -> reader_count == 0 ) {
116+ if (!fpm_spinlock_with_max_retries (& scoreboard -> writer_active , FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES )) {
117+ /* in this case the writer might have crashed so just warn and continue as the lock was acquired */
118+ zlog (ZLOG_WARNING , "scoreboard: writer %d waited too long for another writer to release lock." , getpid ());
119+ }
120+ #ifdef PHP_FPM_ZLOG_TRACE
121+ else {
122+ zlog (ZLOG_DEBUG , "scoreboard: writer lock acquired by writer %d" , getpid ());
123+ }
124+ #endif
125+ fpm_unlock (scoreboard -> lock );
126+ break ;
127+ }
128+ fpm_unlock (scoreboard -> lock );
129+
130+ if (++ retries > FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES ) {
131+ /* decrement reader count by 1 (assuming a killed or crashed reader) */
132+ fpm_scoreboard_readers_decrement (scoreboard );
133+ zlog (ZLOG_WARNING , "scoreboard: writer detected a potential crashed reader, decrementing reader count." );
134+ retries = 0 ;
135+ }
136+
137+ sched_yield ();
138+ }
97139}
98140/* }}} */
99141
@@ -173,7 +215,10 @@ void fpm_scoreboard_update_commit(
173215 scoreboard -> memory_peak = memory_peak ;
174216 }
175217
176- fpm_unlock (scoreboard -> lock );
218+ fpm_unlock (scoreboard -> writer_active );
219+ #ifdef PHP_FPM_ZLOG_TRACE
220+ zlog (ZLOG_DEBUG , "scoreboard: writer lock released by writer %d" , getpid ());
221+ #endif
177222}
178223/* }}} */
179224
@@ -237,16 +282,37 @@ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_chil
237282
238283struct fpm_scoreboard_s * fpm_scoreboard_acquire (struct fpm_scoreboard_s * scoreboard , int nohang ) /* {{{ */
239284{
240- struct fpm_scoreboard_s * s ;
241-
242- s = scoreboard ? scoreboard : fpm_scoreboard ;
285+ struct fpm_scoreboard_s * s = scoreboard ? scoreboard : fpm_scoreboard ;
243286 if (!s ) {
244287 return NULL ;
245288 }
246289
247- if (!fpm_spinlock (& s -> lock , nohang )) {
248- return NULL ;
290+ int retries = 0 ;
291+ while (1 ) {
292+ /* increment reader if no writer active */
293+ fpm_spinlock (& s -> lock , 1 );
294+ if (!s -> writer_active ) {
295+ s -> reader_count += 1 ;
296+ #ifdef PHP_FPM_ZLOG_TRACE
297+ unsigned int current_reader_count = s -> reader_count ;
298+ #endif
299+ fpm_unlock (s -> lock );
300+ #ifdef PHP_FPM_ZLOG_TRACE
301+ zlog (ZLOG_DEBUG , "scoreboard: for proc %d reader incremented to value %u" , getpid (), current_reader_count );
302+ #endif
303+ break ;
304+ }
305+ fpm_unlock (s -> lock );
306+
307+ sched_yield ();
308+
309+ if (++ retries > FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES ) {
310+ zlog (ZLOG_WARNING , "scoreboard: reader waited too long for writer to release lock." );
311+ fpm_scoreboard_readers_decrement (s );
312+ return NULL ;
313+ }
249314 }
315+
250316 return s ;
251317}
252318/* }}} */
@@ -256,7 +322,7 @@ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
256322 return ;
257323 }
258324
259- scoreboard -> lock = 0 ;
325+ fpm_scoreboard_readers_decrement ( scoreboard ) ;
260326}
261327
262328struct fpm_scoreboard_s * fpm_scoreboard_copy (struct fpm_scoreboard_s * scoreboard , int copy_procs )
0 commit comments