Return to ngx_event_timer.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / nginx / src / event |
1.1 ! misho 1: ! 2: /* ! 3: * Copyright (C) Igor Sysoev ! 4: * Copyright (C) Nginx, Inc. ! 5: */ ! 6: ! 7: ! 8: #include <ngx_config.h> ! 9: #include <ngx_core.h> ! 10: #include <ngx_event.h> ! 11: ! 12: ! 13: #if (NGX_THREADS) ! 14: ngx_mutex_t *ngx_event_timer_mutex; ! 15: #endif ! 16: ! 17: ! 18: ngx_thread_volatile ngx_rbtree_t ngx_event_timer_rbtree; ! 19: static ngx_rbtree_node_t ngx_event_timer_sentinel; ! 20: ! 21: /* ! 22: * the event timer rbtree may contain the duplicate keys, however, ! 23: * it should not be a problem, because we use the rbtree to find ! 24: * a minimum timer value only ! 25: */ ! 26: ! 27: ngx_int_t ! 28: ngx_event_timer_init(ngx_log_t *log) ! 29: { ! 30: ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel, ! 31: ngx_rbtree_insert_timer_value); ! 32: ! 33: #if (NGX_THREADS) ! 34: ! 35: if (ngx_event_timer_mutex) { ! 36: ngx_event_timer_mutex->log = log; ! 37: return NGX_OK; ! 38: } ! 39: ! 40: ngx_event_timer_mutex = ngx_mutex_init(log, 0); ! 41: if (ngx_event_timer_mutex == NULL) { ! 42: return NGX_ERROR; ! 43: } ! 44: ! 45: #endif ! 46: ! 47: return NGX_OK; ! 48: } ! 49: ! 50: ! 51: ngx_msec_t ! 52: ngx_event_find_timer(void) ! 53: { ! 54: ngx_msec_int_t timer; ! 55: ngx_rbtree_node_t *node, *root, *sentinel; ! 56: ! 57: if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) { ! 58: return NGX_TIMER_INFINITE; ! 59: } ! 60: ! 61: ngx_mutex_lock(ngx_event_timer_mutex); ! 62: ! 63: root = ngx_event_timer_rbtree.root; ! 64: sentinel = ngx_event_timer_rbtree.sentinel; ! 65: ! 66: node = ngx_rbtree_min(root, sentinel); ! 67: ! 68: ngx_mutex_unlock(ngx_event_timer_mutex); ! 69: ! 70: timer = (ngx_msec_int_t) (node->key - ngx_current_msec); ! 71: ! 72: return (ngx_msec_t) (timer > 0 ? timer : 0); ! 73: } ! 74: ! 75: ! 76: void ! 77: ngx_event_expire_timers(void) ! 78: { ! 79: ngx_event_t *ev; ! 80: ngx_rbtree_node_t *node, *root, *sentinel; ! 81: ! 82: sentinel = ngx_event_timer_rbtree.sentinel; ! 83: ! 84: for ( ;; ) { ! 85: ! 86: ngx_mutex_lock(ngx_event_timer_mutex); ! 87: ! 88: root = ngx_event_timer_rbtree.root; ! 89: ! 90: if (root == sentinel) { ! 91: return; ! 92: } ! 93: ! 94: node = ngx_rbtree_min(root, sentinel); ! 95: ! 96: /* node->key <= ngx_current_time */ ! 97: ! 98: if ((ngx_msec_int_t) (node->key - ngx_current_msec) <= 0) { ! 99: ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, timer)); ! 100: ! 101: #if (NGX_THREADS) ! 102: ! 103: if (ngx_threaded && ngx_trylock(ev->lock) == 0) { ! 104: ! 105: /* ! 106: * We cannot change the timer of the event that is being ! 107: * handled by another thread. And we cannot easy walk ! 108: * the rbtree to find next expired timer so we exit the loop. ! 109: * However, it should be a rare case when the event that is ! 110: * being handled has an expired timer. ! 111: */ ! 112: ! 113: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, ! 114: "event %p is busy in expire timers", ev); ! 115: break; ! 116: } ! 117: #endif ! 118: ! 119: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, ! 120: "event timer del: %d: %M", ! 121: ngx_event_ident(ev->data), ev->timer.key); ! 122: ! 123: ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer); ! 124: ! 125: ngx_mutex_unlock(ngx_event_timer_mutex); ! 126: ! 127: #if (NGX_DEBUG) ! 128: ev->timer.left = NULL; ! 129: ev->timer.right = NULL; ! 130: ev->timer.parent = NULL; ! 131: #endif ! 132: ! 133: ev->timer_set = 0; ! 134: ! 135: #if (NGX_THREADS) ! 136: if (ngx_threaded) { ! 137: ev->posted_timedout = 1; ! 138: ! 139: ngx_post_event(ev, &ngx_posted_events); ! 140: ! 141: ngx_unlock(ev->lock); ! 142: ! 143: continue; ! 144: } ! 145: #endif ! 146: ! 147: ev->timedout = 1; ! 148: ! 149: ev->handler(ev); ! 150: ! 151: continue; ! 152: } ! 153: ! 154: break; ! 155: } ! 156: ! 157: ngx_mutex_unlock(ngx_event_timer_mutex); ! 158: }