3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
8 #include <ngx_config.h>
10 #include <ngx_event.h>
14 ngx_mutex_t
*ngx_event_timer_mutex
;
18 ngx_thread_volatile ngx_rbtree_t ngx_event_timer_rbtree
;
19 static ngx_rbtree_node_t ngx_event_timer_sentinel
;
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
28 ngx_event_timer_init(ngx_log_t
*log
)
30 ngx_rbtree_init(&ngx_event_timer_rbtree
, &ngx_event_timer_sentinel
,
31 ngx_rbtree_insert_timer_value
);
35 if (ngx_event_timer_mutex
) {
36 ngx_event_timer_mutex
->log
= log
;
40 ngx_event_timer_mutex
= ngx_mutex_init(log
, 0);
41 if (ngx_event_timer_mutex
== NULL
) {
52 ngx_event_find_timer(void)
55 ngx_rbtree_node_t
*node
, *root
, *sentinel
;
57 if (ngx_event_timer_rbtree
.root
== &ngx_event_timer_sentinel
) {
58 return NGX_TIMER_INFINITE
;
61 ngx_mutex_lock(ngx_event_timer_mutex
);
63 root
= ngx_event_timer_rbtree
.root
;
64 sentinel
= ngx_event_timer_rbtree
.sentinel
;
66 node
= ngx_rbtree_min(root
, sentinel
);
68 ngx_mutex_unlock(ngx_event_timer_mutex
);
70 timer
= (ngx_msec_int_t
) (node
->key
- ngx_current_msec
);
72 return (ngx_msec_t
) (timer
> 0 ? timer
: 0);
77 ngx_event_expire_timers(void)
80 ngx_rbtree_node_t
*node
, *root
, *sentinel
;
82 sentinel
= ngx_event_timer_rbtree
.sentinel
;
86 ngx_mutex_lock(ngx_event_timer_mutex
);
88 root
= ngx_event_timer_rbtree
.root
;
90 if (root
== sentinel
) {
94 node
= ngx_rbtree_min(root
, sentinel
);
96 /* node->key <= ngx_current_time */
98 if ((ngx_msec_int_t
) (node
->key
- ngx_current_msec
) <= 0) {
99 ev
= (ngx_event_t
*) ((char *) node
- offsetof(ngx_event_t
, timer
));
103 if (ngx_threaded
&& ngx_trylock(ev
->lock
) == 0) {
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.
113 ngx_log_debug1(NGX_LOG_DEBUG_EVENT
, ev
->log
, 0,
114 "event %p is busy in expire timers", ev
);
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
);
123 ngx_rbtree_delete(&ngx_event_timer_rbtree
, &ev
->timer
);
125 ngx_mutex_unlock(ngx_event_timer_mutex
);
128 ev
->timer
.left
= NULL
;
129 ev
->timer
.right
= NULL
;
130 ev
->timer
.parent
= NULL
;
137 ev
->posted_timedout
= 1;
139 ngx_post_event(ev
, &ngx_posted_events
);
141 ngx_unlock(ev
->lock
);
157 ngx_mutex_unlock(ngx_event_timer_mutex
);