~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/event/modules/ngx_epoll_module.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
43
44
    epoll_data_t  data;
44
45
};
45
46
 
 
47
 
46
48
int epoll_create(int size);
 
49
 
 
50
int epoll_create(int size)
 
51
{
 
52
    return -1;
 
53
}
 
54
 
 
55
 
47
56
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
 
57
 
 
58
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
 
59
{
 
60
    return -1;
 
61
}
 
62
 
 
63
 
48
64
int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);
49
65
 
50
 
int epoll_create(int size)
51
 
{
52
 
    return -1;
53
 
}
54
 
 
55
 
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
56
 
{
57
 
    return -1;
58
 
}
59
 
 
60
66
int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
61
67
{
62
68
    return -1;
63
69
}
64
70
 
 
71
#if (NGX_HAVE_FILE_AIO)
 
72
 
 
73
#define SYS_io_setup      245
 
74
#define SYS_io_destroy    246
 
75
#define SYS_io_getevents  247
 
76
#define SYS_eventfd       323
 
77
 
 
78
typedef u_int  aio_context_t;
 
79
 
 
80
struct io_event {
 
81
    uint64_t  data;  /* the data field from the iocb */
 
82
    uint64_t  obj;   /* what iocb this event came from */
 
83
    int64_t   res;   /* result code for this event */
 
84
    int64_t   res2;  /* secondary result */
 
85
};
 
86
 
 
87
 
 
88
#endif
65
89
#endif
66
90
 
67
91
 
68
92
typedef struct {
69
93
    ngx_uint_t  events;
 
94
    ngx_uint_t  aio_requests;
70
95
} ngx_epoll_conf_t;
71
96
 
72
97
 
82
107
static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
83
108
    ngx_uint_t flags);
84
109
 
 
110
#if (NGX_HAVE_FILE_AIO)
 
111
static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
 
112
#endif
 
113
 
85
114
static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
86
115
static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);
87
116
 
89
118
static struct epoll_event  *event_list;
90
119
static ngx_uint_t           nevents;
91
120
 
 
121
#if (NGX_HAVE_FILE_AIO)
 
122
 
 
123
int                         ngx_eventfd = -1;
 
124
aio_context_t               ngx_aio_ctx = 0;
 
125
 
 
126
static ngx_event_t          ngx_eventfd_event;
 
127
static ngx_connection_t     ngx_eventfd_conn;
 
128
 
 
129
#endif
92
130
 
93
131
static ngx_str_t      epoll_name = ngx_string("epoll");
94
132
 
101
139
      offsetof(ngx_epoll_conf_t, events),
102
140
      NULL },
103
141
 
 
142
    { ngx_string("worker_aio_requests"),
 
143
      NGX_EVENT_CONF|NGX_CONF_TAKE1,
 
144
      ngx_conf_set_num_slot,
 
145
      0,
 
146
      offsetof(ngx_epoll_conf_t, aio_requests),
 
147
      NULL },
 
148
 
104
149
      ngx_null_command
105
150
};
106
151
 
140
185
};
141
186
 
142
187
 
 
188
#if (NGX_HAVE_FILE_AIO)
 
189
 
 
190
/*
 
191
 * We call io_setup(), io_destroy() io_submit(), and io_getevents() directly
 
192
 * as syscalls instead of libaio usage, because the library header file
 
193
 * supports eventfd() since 0.3.107 version only.
 
194
 *
 
195
 * Also we do not use eventfd() in glibc, because glibc supports it
 
196
 * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2()
 
197
 * into single eventfd() function with different number of parameters.
 
198
 */
 
199
 
 
200
static int
 
201
io_setup(u_int nr_reqs, aio_context_t *ctx)
 
202
{
 
203
    return syscall(SYS_io_setup, nr_reqs, ctx);
 
204
}
 
205
 
 
206
 
 
207
static int
 
208
io_destroy(aio_context_t ctx)
 
209
{
 
210
    return syscall(SYS_io_destroy, ctx);
 
211
}
 
212
 
 
213
 
 
214
static int
 
215
io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
 
216
    struct timespec *tmo)
 
217
{
 
218
    return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
 
219
}
 
220
 
 
221
 
 
222
static void
 
223
ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
 
224
{
 
225
    int                 n;
 
226
    struct epoll_event  ee;
 
227
 
 
228
    ngx_eventfd = syscall(SYS_eventfd, 0);
 
229
 
 
230
    if (ngx_eventfd == -1) {
 
231
        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
 
232
                      "eventfd() failed");
 
233
        ngx_file_aio = 0;
 
234
        return;
 
235
    }
 
236
 
 
237
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
 
238
                   "eventfd: %d", ngx_eventfd);
 
239
 
 
240
    n = 1;
 
241
 
 
242
    if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) {
 
243
        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
 
244
                      "ioctl(eventfd, FIONBIO) failed");
 
245
        goto failed;
 
246
    }
 
247
 
 
248
    if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
 
249
        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
 
250
                      "io_setup() failed");
 
251
        goto failed;
 
252
    }
 
253
 
 
254
    ngx_eventfd_event.data = &ngx_eventfd_conn;
 
255
    ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
 
256
    ngx_eventfd_event.log = cycle->log;
 
257
    ngx_eventfd_event.active = 1;
 
258
    ngx_eventfd_conn.fd = ngx_eventfd;
 
259
    ngx_eventfd_conn.read = &ngx_eventfd_event;
 
260
    ngx_eventfd_conn.log = cycle->log;
 
261
 
 
262
    ee.events = EPOLLIN|EPOLLET;
 
263
    ee.data.ptr = &ngx_eventfd_conn;
 
264
 
 
265
    if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
 
266
        return;
 
267
    }
 
268
 
 
269
    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
 
270
                  "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");
 
271
 
 
272
    if (io_destroy(ngx_aio_ctx) == -1) {
 
273
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
 
274
                      "io_destroy() failed");
 
275
    }
 
276
 
 
277
failed:
 
278
 
 
279
    if (close(ngx_eventfd) == -1) {
 
280
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
 
281
                      "eventfd close() failed");
 
282
    }
 
283
 
 
284
    ngx_eventfd = -1;
 
285
    ngx_aio_ctx = 0;
 
286
    ngx_file_aio = 0;
 
287
}
 
288
 
 
289
#endif
 
290
 
 
291
 
143
292
static ngx_int_t
144
293
ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
145
294
{
146
 
    ngx_event_conf_t  *ecf;
147
295
    ngx_epoll_conf_t  *epcf;
148
296
 
149
 
    ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
150
 
 
151
297
    epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
152
298
 
153
299
    if (ep == -1) {
154
 
        ep = epoll_create(ecf->connections / 2);
 
300
        ep = epoll_create(cycle->connection_n / 2);
155
301
 
156
302
        if (ep == -1) {
157
303
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
158
304
                          "epoll_create() failed");
159
305
            return NGX_ERROR;
160
306
        }
 
307
 
 
308
#if (NGX_HAVE_FILE_AIO)
 
309
 
 
310
        ngx_epoll_aio_init(cycle, epcf);
 
311
 
 
312
#endif
161
313
    }
162
314
 
163
315
    if (nevents < epcf->events) {
200
352
 
201
353
    ep = -1;
202
354
 
 
355
#if (NGX_HAVE_FILE_AIO)
 
356
 
 
357
    if (ngx_eventfd != -1) {
 
358
 
 
359
        if (io_destroy(ngx_aio_ctx) == -1) {
 
360
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
 
361
                          "io_destroy() failed");
 
362
        }
 
363
 
 
364
        if (close(ngx_eventfd) == -1) {
 
365
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
 
366
                          "eventfd close() failed");
 
367
        }
 
368
 
 
369
        ngx_eventfd = -1;
 
370
    }
 
371
 
 
372
    ngx_aio_ctx = 0;
 
373
 
 
374
#endif
 
375
 
203
376
    ngx_free(event_list);
204
377
 
205
378
    event_list = NULL;
276
449
 
277
450
    /*
278
451
     * when the file descriptor is closed, the epoll automatically deletes
279
 
     * it from its queue, so we do not need to delete explicity the event
 
452
     * it from its queue, so we do not need to delete explicitly the event
280
453
     * before the closing the file descriptor
281
454
     */
282
455
 
355
528
 
356
529
    /*
357
530
     * when the file descriptor is closed the epoll automatically deletes
358
 
     * it from its queue so we do not need to delete explicity the event
 
531
     * it from its queue so we do not need to delete explicitly the event
359
532
     * before the closing the file descriptor
360
533
     */
361
534
 
393
566
    ngx_int_t          instance, i;
394
567
    ngx_uint_t         level;
395
568
    ngx_err_t          err;
396
 
    ngx_log_t         *log;
397
569
    ngx_event_t       *rev, *wev, **queue;
398
570
    ngx_connection_t  *c;
399
571
 
404
576
 
405
577
    events = epoll_wait(ep, event_list, (int) nevents, timer);
406
578
 
407
 
    if (events == -1) {
408
 
        err = ngx_errno;
409
 
    } else {
410
 
        err = 0;
411
 
    }
 
579
    err = (events == -1) ? ngx_errno : 0;
412
580
 
413
 
    if (flags & NGX_UPDATE_TIME) {
414
 
        ngx_time_update(0, 0);
 
581
    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
 
582
        ngx_time_update();
415
583
    }
416
584
 
417
585
    if (err) {
444
612
 
445
613
    ngx_mutex_lock(ngx_posted_events_mutex);
446
614
 
447
 
    log = cycle->log;
448
 
 
449
615
    for (i = 0; i < events; i++) {
450
616
        c = event_list[i].data.ptr;
451
617
 
466
632
            continue;
467
633
        }
468
634
 
469
 
#if (NGX_DEBUG0)
470
 
        log = c->log ? c->log : cycle->log;
471
 
#endif
472
 
 
473
635
        revents = event_list[i].events;
474
636
 
475
 
        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0,
 
637
        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
476
638
                       "epoll: fd:%d ev:%04XD d:%p",
477
639
                       c->fd, revents, event_list[i].data.ptr);
478
640
 
479
641
        if (revents & (EPOLLERR|EPOLLHUP)) {
480
 
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0,
 
642
            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
481
643
                           "epoll_wait() error on fd:%d ev:%04XD",
482
644
                           c->fd, revents);
483
645
        }
484
646
 
485
647
#if 0
486
648
        if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
487
 
            ngx_log_error(NGX_LOG_ALERT, log, 0,
 
649
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
488
650
                          "strange epoll_wait() events fd:%d ev:%04XD",
489
651
                          c->fd, revents);
490
652
        }
526
688
 
527
689
        if ((revents & EPOLLOUT) && wev->active) {
528
690
 
 
691
            if (c->fd == -1 || wev->instance != instance) {
 
692
 
 
693
                /*
 
694
                 * the stale event from a file descriptor
 
695
                 * that was just closed in this iteration
 
696
                 */
 
697
 
 
698
                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
 
699
                               "epoll: stale event %p", c);
 
700
                continue;
 
701
            }
 
702
 
529
703
            if (flags & NGX_POST_THREAD_EVENTS) {
530
704
                wev->posted_ready = 1;
531
705
 
548
722
}
549
723
 
550
724
 
 
725
#if (NGX_HAVE_FILE_AIO)
 
726
 
 
727
static void
 
728
ngx_epoll_eventfd_handler(ngx_event_t *ev)
 
729
{
 
730
    int               n, events;
 
731
    long              i;
 
732
    uint64_t          ready;
 
733
    ngx_err_t         err;
 
734
    ngx_event_t      *e;
 
735
    ngx_event_aio_t  *aio;
 
736
    struct io_event   event[64];
 
737
    struct timespec   ts;
 
738
 
 
739
    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler");
 
740
 
 
741
    n = read(ngx_eventfd, &ready, 8);
 
742
 
 
743
    err = ngx_errno;
 
744
 
 
745
    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n);
 
746
 
 
747
    if (n != 8) {
 
748
        if (n == -1) {
 
749
            if (err == NGX_EAGAIN) {
 
750
                return;
 
751
            }
 
752
 
 
753
            ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
 
754
            return;
 
755
        }
 
756
 
 
757
        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
 
758
                      "read(eventfd) returned only %d bytes", n);
 
759
        return;
 
760
    }
 
761
 
 
762
    ts.tv_sec = 0;
 
763
    ts.tv_nsec = 0;
 
764
 
 
765
    while (ready) {
 
766
 
 
767
        events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts);
 
768
 
 
769
        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
 
770
                       "io_getevents: %l", events);
 
771
 
 
772
        if (events > 0) {
 
773
            ready -= events;
 
774
 
 
775
            for (i = 0; i < events; i++) {
 
776
 
 
777
                ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
 
778
                               "io_event: %uXL %uXL %L %L",
 
779
                                event[i].data, event[i].obj,
 
780
                                event[i].res, event[i].res2);
 
781
 
 
782
                e = (ngx_event_t *) (uintptr_t) event[i].data;
 
783
 
 
784
                e->complete = 1;
 
785
                e->active = 0;
 
786
                e->ready = 1;
 
787
 
 
788
                aio = e->data;
 
789
                aio->res = event[i].res;
 
790
 
 
791
                ngx_post_event(e, &ngx_posted_events);
 
792
            }
 
793
 
 
794
            continue;
 
795
        }
 
796
 
 
797
        if (events == 0) {
 
798
            return;
 
799
        }
 
800
 
 
801
        /* events == -1 */
 
802
        ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
 
803
                      "io_getevents() failed");
 
804
        return;
 
805
    }
 
806
}
 
807
 
 
808
#endif
 
809
 
 
810
 
551
811
static void *
552
812
ngx_epoll_create_conf(ngx_cycle_t *cycle)
553
813
{
555
815
 
556
816
    epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t));
557
817
    if (epcf == NULL) {
558
 
        return NGX_CONF_ERROR;
 
818
        return NULL;
559
819
    }
560
820
 
561
821
    epcf->events = NGX_CONF_UNSET;
 
822
    epcf->aio_requests = NGX_CONF_UNSET;
562
823
 
563
824
    return epcf;
564
825
}
570
831
    ngx_epoll_conf_t *epcf = conf;
571
832
 
572
833
    ngx_conf_init_uint_value(epcf->events, 512);
 
834
    ngx_conf_init_uint_value(epcf->aio_requests, 32);
573
835
 
574
836
    return NGX_CONF_OK;
575
837
}