@@ -215,18 +215,19 @@ static void *IOThreadMain(void *myid) {
215
215
long id = (long )myid ;
216
216
char thdname [32 ];
217
217
218
- serverAssert (server .io_threads_num > 0 );
219
- serverAssert (id > 0 && id < server .io_threads_num );
220
218
snprintf (thdname , sizeof (thdname ), "io_thd_%ld" , id );
221
219
valkey_set_thread_title (thdname );
222
220
serverSetCpuAffinity (server .server_cpulist );
223
221
makeThreadKillable ();
224
222
initSharedQueryBuf ();
223
+ pthread_cleanup_push (freeSharedQueryBuf , NULL );
225
224
226
225
thread_id = (int )id ;
227
226
size_t jobs_to_process = 0 ;
228
227
IOJobQueue * jq = & io_jobs [id ];
229
228
while (1 ) {
229
+ /* Cancellation point so that pthread_cancel() from main thread is honored. */
230
+ pthread_testcancel ();
230
231
/* Wait for jobs */
231
232
for (int j = 0 ; j < 1000000 ; j ++ ) {
232
233
jobs_to_process = IOJobQueue_availableJobs (jq );
@@ -255,12 +256,15 @@ static void *IOThreadMain(void *myid) {
255
256
* As the main-thread main concern is to check if the queue is empty, it's enough to do it once at the end. */
256
257
atomic_thread_fence (memory_order_release );
257
258
}
258
- freeSharedQueryBuf ( );
259
+ pthread_cleanup_pop ( 0 );
259
260
return NULL ;
260
261
}
261
262
262
263
#define IO_JOB_QUEUE_SIZE 2048
263
264
static void createIOThread (int id ) {
265
+ serverAssert (server .io_threads_num > 0 );
266
+ serverAssert (id > 0 && id < server .io_threads_num );
267
+
264
268
pthread_t tid ;
265
269
pthread_mutex_init (& io_threads_mutex [id ], NULL );
266
270
IOJobQueue_init (& io_jobs [id ], IO_JOB_QUEUE_SIZE );
@@ -287,7 +291,7 @@ static void shutdownIOThread(int id) {
287
291
} else {
288
292
serverLog (LL_NOTICE , "IO thread(tid:%lu) terminated" , (unsigned long )tid );
289
293
}
290
-
294
+ pthread_mutex_destroy ( & io_threads_mutex [ id ]);
291
295
IOJobQueue_cleanup (& io_jobs [id ]);
292
296
}
293
297
@@ -297,6 +301,44 @@ void killIOThreads(void) {
297
301
}
298
302
}
299
303
304
+ int updateIOThreads (const char * * err ) {
305
+ serverAssert (inMainThread ());
306
+ UNUSED (err );
307
+ int prev_threads_num = 1 ;
308
+ for (int i = IO_THREADS_MAX_NUM - 1 ; i > 0 ; i -- ) {
309
+ if (io_threads [i ]) {
310
+ prev_threads_num = i + 1 ;
311
+ break ;
312
+ }
313
+ }
314
+ if (prev_threads_num == server .io_threads_num ) return 1 ;
315
+
316
+ serverLog (LL_NOTICE , "Changing number of IO threads from %d to %d." , prev_threads_num , server .io_threads_num );
317
+ drainIOThreadsQueue ();
318
+ /* Set active threads to 1, will be adjusted based on workload later. */
319
+ for (int i = 1 ; i < server .active_io_threads_num ; i ++ ) {
320
+ pthread_mutex_lock (& io_threads_mutex [i ]);
321
+ }
322
+ server .active_io_threads_num = 1 ;
323
+
324
+ // Create new threads.
325
+ if (server .io_threads_num > prev_threads_num ) {
326
+ for (int i = prev_threads_num ; i < server .io_threads_num ; i ++ ) {
327
+ createIOThread (i );
328
+ }
329
+ }
330
+ // Decrease the number of threads.
331
+ else {
332
+ for (int i = prev_threads_num - 1 ; i >= server .io_threads_num ; i -- ) {
333
+ // Unblock inactive thread.
334
+ pthread_mutex_unlock (& io_threads_mutex [i ]);
335
+ shutdownIOThread (i );
336
+ io_threads [i ] = 0 ;
337
+ }
338
+ }
339
+ return 1 ;
340
+ }
341
+
300
342
/* Initialize the data structures needed for I/O threads. */
301
343
void initIOThreads (void ) {
302
344
server .active_io_threads_num = 1 ; /* We start with threads not active. */
0 commit comments