comparison src/core/ngx_thread_pool.c @ 6517:657e029bac28

Thread pools: memory barriers in task completion notifications. The ngx_thread_pool_done object isn't volatile, and at least some compilers assume that it is permitted to reorder modifications of volatile and non-volatile objects. Added appropriate ngx_memory_barrier() calls to make sure all modifications will happen before the lock is released. Reported by Mindaugas Rasiukevicius, http://mailman.nginx.org/pipermail/nginx-devel/2016-April/008160.html.
author Maxim Dounin <mdounin@mdounin.ru>
date Tue, 19 Apr 2016 17:18:28 +0300
parents abde398f34a7
children 33d075b9097d
comparison
equal deleted inserted replaced
6516:ab16126a06a0 6517:657e029bac28
343 ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048); 343 ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048);
344 344
345 *ngx_thread_pool_done.last = task; 345 *ngx_thread_pool_done.last = task;
346 ngx_thread_pool_done.last = &task->next; 346 ngx_thread_pool_done.last = &task->next;
347 347
348 ngx_memory_barrier();
349
348 ngx_unlock(&ngx_thread_pool_done_lock); 350 ngx_unlock(&ngx_thread_pool_done_lock);
349 351
350 (void) ngx_notify(ngx_thread_pool_handler); 352 (void) ngx_notify(ngx_thread_pool_handler);
351 } 353 }
352 } 354 }
363 ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048); 365 ngx_spinlock(&ngx_thread_pool_done_lock, 1, 2048);
364 366
365 task = ngx_thread_pool_done.first; 367 task = ngx_thread_pool_done.first;
366 ngx_thread_pool_done.first = NULL; 368 ngx_thread_pool_done.first = NULL;
367 ngx_thread_pool_done.last = &ngx_thread_pool_done.first; 369 ngx_thread_pool_done.last = &ngx_thread_pool_done.first;
370
371 ngx_memory_barrier();
368 372
369 ngx_unlock(&ngx_thread_pool_done_lock); 373 ngx_unlock(&ngx_thread_pool_done_lock);
370 374
371 while (task) { 375 while (task) {
372 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, 376 ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,