|  |  | 
|  | /* | 
|  | * Copyright (C) Igor Sysoev | 
|  | */ | 
|  |  | 
|  |  | 
|  | #include <ngx_config.h> | 
|  | #include <ngx_core.h> | 
|  | #include <ngx_event.h> | 
|  |  | 
|  |  | 
|  | ngx_thread_volatile ngx_event_t  *ngx_posted_accept_events; | 
|  | ngx_thread_volatile ngx_event_t  *ngx_posted_events; | 
|  |  | 
|  | #if (NGX_THREADS) | 
|  | ngx_mutex_t                      *ngx_posted_events_mutex; | 
|  | #endif | 
|  |  | 
|  |  | 
|  | void | 
|  | ngx_event_process_posted(ngx_cycle_t *cycle, | 
|  | ngx_thread_volatile ngx_event_t **posted) | 
|  | { | 
|  | ngx_event_t  *ev; | 
|  |  | 
|  | for ( ;; ) { | 
|  |  | 
|  | ev = (ngx_event_t *) *posted; | 
|  |  | 
|  | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 
|  | "posted event %p", ev); | 
|  |  | 
|  | if (ev == NULL) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | ngx_delete_posted_event(ev); | 
|  |  | 
|  | ev->handler(ev); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | #if (NGX_THREADS) && !(NGX_WIN32) | 
|  |  | 
|  | void | 
|  | ngx_wakeup_worker_thread(ngx_cycle_t *cycle) | 
|  | { | 
|  | ngx_int_t     i; | 
|  | #if 0 | 
|  | ngx_uint_t    busy; | 
|  | ngx_event_t  *ev; | 
|  |  | 
|  | busy = 1; | 
|  |  | 
|  | if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | for (ev = (ngx_event_t *) ngx_posted_events; ev; ev = ev->next) { | 
|  | if (*(ev->lock) == 0) { | 
|  | busy = 0; | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | ngx_mutex_unlock(ngx_posted_events_mutex); | 
|  |  | 
|  | if (busy) { | 
|  | return; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | for (i = 0; i < ngx_threads_n; i++) { | 
|  | if (ngx_threads[i].state == NGX_THREAD_FREE) { | 
|  | ngx_cond_signal(ngx_threads[i].cv); | 
|  | return; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | ngx_int_t | 
|  | ngx_event_thread_process_posted(ngx_cycle_t *cycle) | 
|  | { | 
|  | ngx_event_t  *ev; | 
|  |  | 
|  | for ( ;; ) { | 
|  |  | 
|  | ev = (ngx_event_t *) ngx_posted_events; | 
|  |  | 
|  | for ( ;; ) { | 
|  |  | 
|  | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 
|  | "posted event %p", ev); | 
|  |  | 
|  | if (ev == NULL) { | 
|  | return NGX_OK; | 
|  | } | 
|  |  | 
|  | if (ngx_trylock(ev->lock) == 0) { | 
|  |  | 
|  | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 
|  | "posted event %p is busy", ev); | 
|  |  | 
|  | ev = ev->next; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (ev->lock != ev->own_lock) { | 
|  | if (*(ev->own_lock)) { | 
|  | ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | 
|  | "the own lock of the posted event %p is busy", ev); | 
|  | ngx_unlock(ev->lock); | 
|  | ev = ev->next; | 
|  | continue; | 
|  | } | 
|  | *(ev->own_lock) = 1; | 
|  | } | 
|  |  | 
|  | ngx_delete_posted_event(ev); | 
|  |  | 
|  | ev->locked = 1; | 
|  |  | 
|  | ev->ready |= ev->posted_ready; | 
|  | ev->timedout |= ev->posted_timedout; | 
|  | ev->pending_eof |= ev->posted_eof; | 
|  | #if (NGX_HAVE_KQUEUE) | 
|  | ev->kq_errno |= ev->posted_errno; | 
|  | #endif | 
|  | if (ev->posted_available) { | 
|  | ev->available = ev->posted_available; | 
|  | } | 
|  |  | 
|  | ev->posted_ready = 0; | 
|  | ev->posted_timedout = 0; | 
|  | ev->posted_eof = 0; | 
|  | #if (NGX_HAVE_KQUEUE) | 
|  | ev->posted_errno = 0; | 
|  | #endif | 
|  | ev->posted_available = 0; | 
|  |  | 
|  | ngx_mutex_unlock(ngx_posted_events_mutex); | 
|  |  | 
|  | ev->handler(ev); | 
|  |  | 
|  | ngx_mutex_lock(ngx_posted_events_mutex); | 
|  |  | 
|  | if (ev->locked) { | 
|  | ngx_unlock(ev->lock); | 
|  |  | 
|  | if (ev->lock != ev->own_lock) { | 
|  | ngx_unlock(ev->own_lock); | 
|  | } | 
|  | } | 
|  |  | 
|  | ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 
|  | "posted event %p is done", ev); | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | #else | 
|  |  | 
|  | void | 
|  | ngx_wakeup_worker_thread(ngx_cycle_t *cycle) | 
|  | { | 
|  | } | 
|  |  | 
|  | #endif |