@@ -73,6 +73,17 @@ 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+ unsigned int current_reader_count = (unsigned ) scoreboard -> reader_count ;
83+ fpm_unlock (scoreboard -> lock );
84+ zlog (ZLOG_DEBUG , "scoreboard: for proc %d reader decremented to value %u" , getpid (), current_reader_count );
85+ }
86+
7687static struct fpm_scoreboard_s * fpm_scoreboard_get_for_update (struct fpm_scoreboard_s * scoreboard ) /* {{{ */
7788{
7889 if (!scoreboard ) {
@@ -93,7 +104,30 @@ void fpm_scoreboard_update_begin(struct fpm_scoreboard_s *scoreboard) /* {{{ */
93104 return ;
94105 }
95106
96- fpm_spinlock (& scoreboard -> lock , 0 );
107+ int retries = 0 ;
108+ while (1 ) {
109+ fpm_spinlock (& scoreboard -> lock , 1 );
110+ if (scoreboard -> reader_count == 0 ) {
111+ if (!fpm_spinlock_with_max_retries (& scoreboard -> writer_active , FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES )) {
112+ /* in this case the writer might have crashed so just warn and continue as the lock was acquired */
113+ zlog (ZLOG_WARNING , "scoreboard: writer %d waited too long for another writer to release lock." , getpid ());
114+ } else {
115+ zlog (ZLOG_DEBUG , "scoreboard: writer lock acquired by writer %d" , getpid ());
116+ }
117+ fpm_unlock (scoreboard -> lock );
118+ break ;
119+ }
120+ fpm_unlock (scoreboard -> lock );
121+
122+ if (++ retries > FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES ) {
123+ /* decrement reader count by 1 (assuming a killed or crashed reader) */
124+ fpm_scoreboard_readers_decrement (scoreboard );
125+ zlog (ZLOG_WARNING , "scoreboard: writer detected a potential crashed reader, decrementing reader count." );
126+ retries = 0 ;
127+ }
128+
129+ sched_yield ();
130+ }
97131}
98132/* }}} */
99133
@@ -170,7 +204,8 @@ void fpm_scoreboard_update_commit(
170204 scoreboard -> active_max = scoreboard -> active ;
171205 }
172206
173- fpm_unlock (scoreboard -> lock );
207+ fpm_unlock (scoreboard -> writer_active );
208+ zlog (ZLOG_DEBUG , "scoreboard: writer lock released by writer %d" , getpid ());
174209}
175210/* }}} */
176211
@@ -234,16 +269,33 @@ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_chil
234269
235270struct fpm_scoreboard_s * fpm_scoreboard_acquire (struct fpm_scoreboard_s * scoreboard , int nohang ) /* {{{ */
236271{
237- struct fpm_scoreboard_s * s ;
238-
239- s = scoreboard ? scoreboard : fpm_scoreboard ;
272+ struct fpm_scoreboard_s * s = scoreboard ? scoreboard : fpm_scoreboard ;
240273 if (!s ) {
241274 return NULL ;
242275 }
243276
244- if (!fpm_spinlock (& s -> lock , nohang )) {
245- return NULL ;
277+ int retries = 0 ;
278+ while (1 ) {
279+ /* increment reader if no writer active */
280+ fpm_spinlock (& scoreboard -> lock , 1 );
281+ if (!s -> writer_active ) {
282+ scoreboard -> reader_count += 1 ;
283+ unsigned int current_reader_count = (unsigned ) scoreboard -> reader_count ;
284+ fpm_unlock (scoreboard -> lock );
285+ zlog (ZLOG_DEBUG , "scoreboard: for proc %d reader incremented to value %u" , getpid (), current_reader_count );
286+ break ;
287+ }
288+ fpm_unlock (scoreboard -> lock );
289+
290+ sched_yield ();
291+
292+ if (++ retries > FPM_SCOREBOARD_SPINLOCK_MAX_RETRIES ) {
293+ zlog (ZLOG_WARNING , "scoreboard: reader waited too long for writer to release lock." );
294+ fpm_scoreboard_readers_decrement (s );
295+ return NULL ;
296+ }
246297 }
298+
247299 return s ;
248300}
249301/* }}} */
@@ -253,7 +305,7 @@ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
253305 return ;
254306 }
255307
256- scoreboard -> lock = 0 ;
308+ fpm_scoreboard_readers_decrement ( scoreboard ) ;
257309}
258310
259311struct fpm_scoreboard_s * fpm_scoreboard_copy (struct fpm_scoreboard_s * scoreboard , int copy_procs )
0 commit comments