1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2001-2010, Eduardo Silva P. <edsiper@gmail.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/epoll.h>
38 #include "scheduler.h"
42 #define MAX_EVENTS 5000
44 mk_epoll_handlers
*mk_epoll_set_handlers(void (*read
) (int),
48 void (*timeout
) (int))
50 mk_epoll_handlers
*handler
;
52 handler
= malloc(sizeof(mk_epoll_handlers
));
53 handler
->read
= (void *) read
;
54 handler
->write
= (void *) write
;
55 handler
->error
= (void *) error
;
56 handler
->close
= (void *) close
;
57 handler
->timeout
= (void *) timeout
;
62 int mk_epoll_create(int max_events
)
66 efd
= epoll_create(max_events
);
68 perror("epoll_create");
74 void *mk_epoll_init(int efd
, mk_epoll_handlers
* handler
, int max_events
)
79 struct epoll_event events
[max_events
];
80 struct sched_list_node
*sched
;
83 sched
= mk_sched_get_thread_conf();
85 pthread_mutex_lock(&mutex_wait_register
);
86 pthread_mutex_unlock(&mutex_wait_register
);
88 fds_timeout
= log_current_utime
+ config
->timeout
;
91 num_fds
= epoll_wait(efd
, events
, max_events
, MK_EPOLL_WAIT_TIMEOUT
);
93 for (i
= 0; i
< num_fds
; i
++) {
94 fd
= events
[i
].data
.fd
;
96 // Case 1: Error condition
97 if (events
[i
].events
& (EPOLLHUP
| EPOLLERR
)) {
98 (*handler
->error
) (fd
);
100 MK_TRACE("EPoll Event, FD %i EPOLLHUP/EPOLLER", fd
);
105 if (events
[i
].events
& EPOLLIN
) {
107 MK_TRACE("EPoll Event, FD %i READ", fd
);
109 ret
= (*handler
->read
) (fd
);
111 else if (events
[i
].events
& EPOLLOUT
) {
113 MK_TRACE("EPoll Event, FD %i WRITE", fd
);
115 ret
= (*handler
->write
) (fd
);
120 MK_TRACE("Epoll Event, FD %i FORCE CLOSE | ret = %i", fd
, ret
);
122 (*handler
->close
) (fd
);
126 /* Check timeouts and update next one */
127 if (log_current_utime
>= fds_timeout
) {
128 mk_sched_check_timeouts(sched
);
129 fds_timeout
= log_current_utime
+ config
->timeout
;
134 int mk_epoll_add_client(int efd
, int socket
, int init_mode
, int behavior
)
137 struct epoll_event event
= { EPOLLERR
| EPOLLHUP
};
139 event
.data
.fd
= socket
;
141 if (behavior
== MK_EPOLL_BEHAVIOR_TRIGGERED
) {
142 event
.events
|= EPOLLET
;
147 event
.events
|= EPOLLIN
;
150 event
.events
|= EPOLLOUT
;
153 event
.events
|= EPOLLIN
| EPOLLOUT
;
157 ret
= epoll_ctl(efd
, EPOLL_CTL_ADD
, socket
, &event
);
164 int mk_epoll_socket_change_mode(int efd
, int socket
, int mode
)
167 struct epoll_event event
;
169 event
.events
= EPOLLET
| EPOLLERR
| EPOLLHUP
;
170 event
.data
.fd
= socket
;
175 MK_TRACE("EPoll, changing mode to READ");
177 event
.events
|= EPOLLIN
;
181 MK_TRACE("EPoll, changing mode to WRITE");
183 event
.events
|= EPOLLOUT
;
187 MK_TRACE("Epoll, changing mode to READ/WRITE");
189 event
.events
|= EPOLLIN
| EPOLLOUT
;
193 ret
= epoll_ctl(efd
, EPOLL_CTL_MOD
, socket
, &event
);
195 perror("\nepoll_ctl");