@@ -73,6 +73,17 @@ int fpm_scoreboard_init_main(void)
73
73
return 0 ;
74
74
}
75
75
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
+
76
87
static struct fpm_scoreboard_s * fpm_scoreboard_get_for_update (struct fpm_scoreboard_s * scoreboard ) /* {{{ */
77
88
{
78
89
if (!scoreboard ) {
@@ -93,7 +104,30 @@ void fpm_scoreboard_update_begin(struct fpm_scoreboard_s *scoreboard) /* {{{ */
93
104
return ;
94
105
}
95
106
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
+ }
97
131
}
98
132
/* }}} */
99
133
@@ -170,7 +204,8 @@ void fpm_scoreboard_update_commit(
170
204
scoreboard -> active_max = scoreboard -> active ;
171
205
}
172
206
173
- fpm_unlock (scoreboard -> lock );
207
+ fpm_unlock (scoreboard -> writer_active );
208
+ zlog (ZLOG_DEBUG , "scoreboard: writer lock released by writer %d" , getpid ());
174
209
}
175
210
/* }}} */
176
211
@@ -234,16 +269,33 @@ struct fpm_scoreboard_proc_s *fpm_scoreboard_proc_get_from_child(struct fpm_chil
234
269
235
270
struct fpm_scoreboard_s * fpm_scoreboard_acquire (struct fpm_scoreboard_s * scoreboard , int nohang ) /* {{{ */
236
271
{
237
- struct fpm_scoreboard_s * s ;
238
-
239
- s = scoreboard ? scoreboard : fpm_scoreboard ;
272
+ struct fpm_scoreboard_s * s = scoreboard ? scoreboard : fpm_scoreboard ;
240
273
if (!s ) {
241
274
return NULL ;
242
275
}
243
276
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
+ }
246
297
}
298
+
247
299
return s ;
248
300
}
249
301
/* }}} */
@@ -253,7 +305,7 @@ void fpm_scoreboard_release(struct fpm_scoreboard_s *scoreboard) {
253
305
return ;
254
306
}
255
307
256
- scoreboard -> lock = 0 ;
308
+ fpm_scoreboard_readers_decrement ( scoreboard ) ;
257
309
}
258
310
259
311
struct fpm_scoreboard_s * fpm_scoreboard_copy (struct fpm_scoreboard_s * scoreboard , int copy_procs )
0 commit comments