~nginx/nginx/1.0

« back to all changes in this revision

Viewing changes to src/event/ngx_event_timer.c

  • Committer: Michael Lustfield
  • Date: 2010-12-01 08:06:25 UTC
  • Revision ID: michael@profarius.com-20101201080625-y8i4bq0e54ev2qwy
Tags: 0.9.0
Nginx v0.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Copyright (C) Igor Sysoev
 
4
 */
 
5
 
 
6
 
 
7
#include <ngx_config.h>
 
8
#include <ngx_core.h>
 
9
#include <ngx_event.h>
 
10
 
 
11
 
 
12
#if (NGX_THREADS)
 
13
ngx_mutex_t  *ngx_event_timer_mutex;
 
14
#endif
 
15
 
 
16
 
 
17
ngx_thread_volatile ngx_rbtree_t  ngx_event_timer_rbtree;
 
18
static ngx_rbtree_node_t          ngx_event_timer_sentinel;
 
19
 
 
20
/*
 
21
 * the event timer rbtree may contain the duplicate keys, however,
 
22
 * it should not be a problem, because we use the rbtree to find
 
23
 * a minimum timer value only
 
24
 */
 
25
 
 
26
ngx_int_t
 
27
ngx_event_timer_init(ngx_log_t *log)
 
28
{
 
29
    ngx_rbtree_init(&ngx_event_timer_rbtree, &ngx_event_timer_sentinel,
 
30
                    ngx_rbtree_insert_timer_value);
 
31
 
 
32
#if (NGX_THREADS)
 
33
 
 
34
    if (ngx_event_timer_mutex) {
 
35
        ngx_event_timer_mutex->log = log;
 
36
        return NGX_OK;
 
37
    }
 
38
 
 
39
    ngx_event_timer_mutex = ngx_mutex_init(log, 0);
 
40
    if (ngx_event_timer_mutex == NULL) {
 
41
        return NGX_ERROR;
 
42
    }
 
43
 
 
44
#endif
 
45
 
 
46
    return NGX_OK;
 
47
}
 
48
 
 
49
 
 
50
ngx_msec_t
 
51
ngx_event_find_timer(void)
 
52
{
 
53
    ngx_msec_int_t      timer;
 
54
    ngx_rbtree_node_t  *node, *root, *sentinel;
 
55
 
 
56
    if (ngx_event_timer_rbtree.root == &ngx_event_timer_sentinel) {
 
57
        return NGX_TIMER_INFINITE;
 
58
    }
 
59
 
 
60
    ngx_mutex_lock(ngx_event_timer_mutex);
 
61
 
 
62
    root = ngx_event_timer_rbtree.root;
 
63
    sentinel = ngx_event_timer_rbtree.sentinel;
 
64
 
 
65
    node = ngx_rbtree_min(root, sentinel);
 
66
 
 
67
    ngx_mutex_unlock(ngx_event_timer_mutex);
 
68
 
 
69
    timer = (ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec;
 
70
 
 
71
    return (ngx_msec_t) (timer > 0 ? timer : 0);
 
72
}
 
73
 
 
74
 
 
75
void
 
76
ngx_event_expire_timers(void)
 
77
{
 
78
    ngx_event_t        *ev;
 
79
    ngx_rbtree_node_t  *node, *root, *sentinel;
 
80
 
 
81
    sentinel = ngx_event_timer_rbtree.sentinel;
 
82
 
 
83
    for ( ;; ) {
 
84
 
 
85
        ngx_mutex_lock(ngx_event_timer_mutex);
 
86
 
 
87
        root = ngx_event_timer_rbtree.root;
 
88
 
 
89
        if (root == sentinel) {
 
90
            return;
 
91
        }
 
92
 
 
93
        node = ngx_rbtree_min(root, sentinel);
 
94
 
 
95
        /* node->key <= ngx_current_time */
 
96
 
 
97
        if ((ngx_msec_int_t) node->key - (ngx_msec_int_t) ngx_current_msec <= 0)
 
98
        {
 
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 can not change the timer of the event that is been
 
107
                 * handling by another thread.  And we can not easy walk
 
108
                 * the rbtree to find a next expired timer so we exit the loop.
 
109
                 * However it should be rare case when the event that is
 
110
                 * been handling has 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
}