blob: 5b0c871b0593f4b0036c271dd64beda415cc648f [file] [log] [blame]
Igor Sysoev6b7cfab2003-01-21 17:36:01 +00001
Igor Sysoevfcce8d52003-01-23 18:47:54 +00002#include <ngx_config.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +00003#include <ngx_core.h>
Igor Sysoevfcce8d52003-01-23 18:47:54 +00004#include <ngx_event.h>
5
Igor Sysoevfcce8d52003-01-23 18:47:54 +00006
Igor Sysoevb54698b2004-02-23 20:57:12 +00007#if (NGX_THREADS)
Igor Sysoevf2334412004-02-25 20:16:15 +00008ngx_mutex_t *ngx_event_timer_mutex;
Igor Sysoevb54698b2004-02-23 20:57:12 +00009#endif
10
Igor Sysoevdc867cd2003-12-14 20:10:27 +000011
Igor Sysoevea0b1d92004-03-02 15:40:59 +000012ngx_thread_volatile ngx_rbtree_t *ngx_event_timer_rbtree;
13ngx_rbtree_t ngx_event_timer_sentinel;
Igor Sysoevf5003d82003-12-04 14:53:00 +000014
15
Igor Sysoevf2334412004-02-25 20:16:15 +000016ngx_int_t ngx_event_timer_init(ngx_log_t *log)
Igor Sysoevf5003d82003-12-04 14:53:00 +000017{
Igor Sysoev3c3ca172004-01-05 20:55:48 +000018 if (ngx_event_timer_rbtree) {
Igor Sysoevd94049b2004-02-29 21:03:02 +000019#if (NGX_THREADS)
Igor Sysoevf2334412004-02-25 20:16:15 +000020 ngx_event_timer_mutex->log = log;
Igor Sysoevd94049b2004-02-29 21:03:02 +000021#endif
Igor Sysoevf2334412004-02-25 20:16:15 +000022 return NGX_OK;
Igor Sysoev2b58fbf2003-12-09 15:08:11 +000023 }
24
Igor Sysoev62260f22003-12-05 17:07:27 +000025 ngx_event_timer_rbtree = &ngx_event_timer_sentinel;
Igor Sysoevf2334412004-02-25 20:16:15 +000026
Igor Sysoevd94049b2004-02-29 21:03:02 +000027#if (NGX_THREADS)
Igor Sysoevf2334412004-02-25 20:16:15 +000028 if (!(ngx_event_timer_mutex = ngx_mutex_init(log, 0))) {
29 return NGX_ERROR;
30 }
Igor Sysoevd94049b2004-02-29 21:03:02 +000031#endif
Igor Sysoevf2334412004-02-25 20:16:15 +000032
33 return NGX_OK;
Igor Sysoevf5003d82003-12-04 14:53:00 +000034}
35
36
Igor Sysoevfaca1192003-12-05 07:11:46 +000037ngx_msec_t ngx_event_find_timer(void)
Igor Sysoevf5003d82003-12-04 14:53:00 +000038{
Igor Sysoevb3968b32004-04-14 17:44:28 +000039 ngx_msec_t timer;
Igor Sysoevf5003d82003-12-04 14:53:00 +000040 ngx_rbtree_t *node;
41
Igor Sysoev1cd1e272003-12-19 12:45:27 +000042 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) {
Igor Sysoevcccc5522004-04-14 20:34:05 +000043 return NGX_TIMER_INFINITE;
Igor Sysoev1cd1e272003-12-19 12:45:27 +000044 }
45
Igor Sysoevf2334412004-02-25 20:16:15 +000046 if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) {
47 return NGX_TIMER_ERROR;
48 }
Igor Sysoevf2334412004-02-25 20:16:15 +000049
Igor Sysoevd94049b2004-02-29 21:03:02 +000050 node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree,
51 &ngx_event_timer_sentinel);
Igor Sysoevf5003d82003-12-04 14:53:00 +000052
Igor Sysoevf2334412004-02-25 20:16:15 +000053 ngx_mutex_unlock(ngx_event_timer_mutex);
Igor Sysoevf2334412004-02-25 20:16:15 +000054
Igor Sysoevb3968b32004-04-14 17:44:28 +000055 timer = (ngx_msec_t)
Igor Sysoevdc867cd2003-12-14 20:10:27 +000056 (node->key * NGX_TIMER_RESOLUTION -
57 ngx_elapsed_msec / NGX_TIMER_RESOLUTION * NGX_TIMER_RESOLUTION);
58#if 0
Igor Sysoevfaca1192003-12-05 07:11:46 +000059 (node->key * NGX_TIMER_RESOLUTION - ngx_elapsed_msec);
Igor Sysoevdc867cd2003-12-14 20:10:27 +000060#endif
Igor Sysoevb3968b32004-04-14 17:44:28 +000061
Igor Sysoevcccc5522004-04-14 20:34:05 +000062 return timer > 0 ? timer: 0 ;
Igor Sysoevf5003d82003-12-04 14:53:00 +000063}
64
65
66void ngx_event_expire_timers(ngx_msec_t timer)
67{
68 ngx_event_t *ev;
69 ngx_rbtree_t *node;
70
Igor Sysoev81a432a2004-07-06 16:12:16 +000071 if (timer < 0) {
72 /* avoid the endless loop if the time goes backward for some reason */
73 timer = 0;
74 }
75
Igor Sysoevf5003d82003-12-04 14:53:00 +000076 for ( ;; ) {
Igor Sysoevf5003d82003-12-04 14:53:00 +000077
Igor Sysoev1cd1e272003-12-19 12:45:27 +000078 if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) {
Igor Sysoevb14b9102004-06-28 16:05:02 +000079 return;
Igor Sysoevf5003d82003-12-04 14:53:00 +000080 }
81
Igor Sysoevf2334412004-02-25 20:16:15 +000082 if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) {
83 return;
84 }
Igor Sysoevf2334412004-02-25 20:16:15 +000085
Igor Sysoevd94049b2004-02-29 21:03:02 +000086 node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree,
Igor Sysoev1cd1e272003-12-19 12:45:27 +000087 &ngx_event_timer_sentinel);
88
Igor Sysoevcccc5522004-04-14 20:34:05 +000089 if (node->key <= (ngx_msec_t)
Igor Sysoev62260f22003-12-05 17:07:27 +000090 (ngx_old_elapsed_msec + timer) / NGX_TIMER_RESOLUTION)
Igor Sysoevf5003d82003-12-04 14:53:00 +000091 {
92 ev = (ngx_event_t *)
Igor Sysoevfaca1192003-12-05 07:11:46 +000093 ((char *) node - offsetof(ngx_event_t, rbtree_key));
Igor Sysoevf5003d82003-12-04 14:53:00 +000094
Igor Sysoev0a94cfd2004-06-28 21:03:14 +000095#if (NGX_THREADS)
Igor Sysoev98c1cf12004-07-02 15:54:34 +000096
97 if (ngx_threaded && ngx_trylock(ev->lock) == 0) {
98
99 /*
100 * We can not change the timer of the event that is been
101 * handling by another thread. And we can not easy walk
102 * the rbtree to find a next expired timer so we exit the loop.
103 * However it should be rare case when the event that is
104 * been handling has expired timer.
105 */
106
Igor Sysoev81a432a2004-07-06 16:12:16 +0000107 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
108 "event " PTR_FMT " is busy in expire timers",
109 ev);
Igor Sysoevb14b9102004-06-28 16:05:02 +0000110 break;
111 }
Igor Sysoev0a94cfd2004-06-28 21:03:14 +0000112#endif
Igor Sysoevf5003d82003-12-04 14:53:00 +0000113
Igor Sysoevb14b9102004-06-28 16:05:02 +0000114 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
115 "event timer del: %d: %d",
116 ngx_event_ident(ev->data), ev->rbtree_key);
117
118 ngx_rbtree_delete((ngx_rbtree_t **) &ngx_event_timer_rbtree,
119 &ngx_event_timer_sentinel,
120 (ngx_rbtree_t *) &ev->rbtree_key);
121
122 ngx_mutex_unlock(ngx_event_timer_mutex);
123
124#if (NGX_DEBUG)
125 ev->rbtree_left = NULL;
126 ev->rbtree_right = NULL;
127 ev->rbtree_parent = NULL;
128#endif
129
130 ev->timer_set = 0;
Igor Sysoevf5003d82003-12-04 14:53:00 +0000131
Igor Sysoev98c1cf12004-07-02 15:54:34 +0000132#if (NGX_THREADS)
Igor Sysoev9a864bd2004-04-04 20:32:09 +0000133 if (ngx_threaded) {
134 if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
135 return;
136 }
137
Igor Sysoev46cd7c22004-07-02 05:47:00 +0000138 ev->posted_timedout = 1;
Igor Sysoev9a864bd2004-04-04 20:32:09 +0000139 ngx_post_event(ev);
140
141 ngx_mutex_unlock(ngx_posted_events_mutex);
Igor Sysoev98c1cf12004-07-02 15:54:34 +0000142
143 ngx_unlock(ev->lock);
144
Igor Sysoev9a864bd2004-04-04 20:32:09 +0000145 continue;
146 }
Igor Sysoev98c1cf12004-07-02 15:54:34 +0000147#endif
Igor Sysoevf2334412004-02-25 20:16:15 +0000148
Igor Sysoev46cd7c22004-07-02 05:47:00 +0000149 ev->timedout = 1;
150
Igor Sysoevf5003d82003-12-04 14:53:00 +0000151 ev->event_handler(ev);
Igor Sysoev46cd7c22004-07-02 05:47:00 +0000152
Igor Sysoevf5003d82003-12-04 14:53:00 +0000153 continue;
154 }
Igor Sysoev46cd7c22004-07-02 05:47:00 +0000155
Igor Sysoevf5003d82003-12-04 14:53:00 +0000156 break;
157 }
Igor Sysoevb14b9102004-06-28 16:05:02 +0000158
159 ngx_mutex_unlock(ngx_event_timer_mutex);
Igor Sysoevf5003d82003-12-04 14:53:00 +0000160}