]> git.ipfire.org Git - people/ms/mstpd.git/blame - epoll_loop.c
driver hooks for creating/deleting new MSTI
[people/ms/mstpd.git] / epoll_loop.c
CommitLineData
1e6d2d09
VD
1/*****************************************************************************
2 Copyright (c) 2006 EMC Corporation.
3 Copyright (c) 2011 Factor-SPE
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2 of the License, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program; if not, write to the Free Software Foundation, Inc., 59
17 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 The full GNU General Public License is included in this distribution in the
20 file called LICENSE.
21
22 Authors: Srinivas Aji <Aji_Srinivas@emc.com>
23 Authors: Vitalii Demianets <vitas@nppfactor.kiev.ua>
24
25******************************************************************************/
26
27#include <stdio.h>
28#include <unistd.h>
29
30#include "epoll_loop.h"
31#include "bridge_ctl.h"
32
33/* globals */
34static int epoll_fd = -1;
35static struct timeval nexttimeout;
36
37int init_epoll(void)
38{
39 int r = epoll_create(128);
40 if(r < 0)
41 {
42 fprintf(stderr, "epoll_create failed: %m\n");
43 return -1;
44 }
45 epoll_fd = r;
46 return 0;
47}
48
49int add_epoll(struct epoll_event_handler *h)
50{
51 struct epoll_event ev =
52 {
53 .events = EPOLLIN,
54 .data.ptr = h,
55 };
56 h->ref_ev = NULL;
57 int r = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, h->fd, &ev);
58 if(r < 0)
59 {
60 fprintf(stderr, "epoll_ctl_add: %m\n");
61 return -1;
62 }
63 return 0;
64}
65
66int remove_epoll(struct epoll_event_handler *h)
67{
68 int r = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, h->fd, NULL);
69 if(r < 0)
70 {
71 fprintf(stderr, "epoll_ctl_del: %m\n");
72 return -1;
73 }
74 if(h->ref_ev && h->ref_ev->data.ptr == h)
75 {
76 h->ref_ev->data.ptr = NULL;
77 h->ref_ev = NULL;
78 }
79 return 0;
80}
81
82void clear_epoll(void)
83{
84 if(epoll_fd >= 0)
85 close(epoll_fd);
86}
87
88static inline int time_diff(struct timeval *second, struct timeval *first)
89{
90 return (second->tv_sec - first->tv_sec) * 1000
91 + (second->tv_usec - first->tv_usec) / 1000;
92}
93
94static inline void run_timeouts(void)
95{
96 bridge_one_second();
97 ++(nexttimeout.tv_sec);
98}
99
100int epoll_main_loop(void)
101{
102 gettimeofday(&nexttimeout, NULL);
103 ++(nexttimeout.tv_sec);
104#define EV_SIZE 8
105 struct epoll_event ev[EV_SIZE];
106
107 while(1)
108 {
109 int r, i;
110 int timeout;
111
112 struct timeval tv;
113 gettimeofday(&tv, NULL);
114 timeout = time_diff(&nexttimeout, &tv);
115 if(timeout < 0)
116 {
117 run_timeouts();
118 timeout = 0;
119 }
120
121 r = epoll_wait(epoll_fd, ev, EV_SIZE, timeout);
122 if(r < 0 && errno != EINTR)
123 {
124 fprintf(stderr, "epoll_wait: %m\n");
125 return -1;
126 }
127 for(i = 0; i < r; ++i)
128 {
129 struct epoll_event_handler *p = ev[i].data.ptr;
130 if(p != NULL)
131 p->ref_ev = &ev[i];
132 }
133 for (i = 0; i < r; ++i)
134 {
135 struct epoll_event_handler *p = ev[i].data.ptr;
136 if(p && p->handler)
137 p->handler(ev[i].events, p);
138 }
139 for (i = 0; i < r; ++i)
140 {
141 struct epoll_event_handler *p = ev[i].data.ptr;
142 if(p != NULL)
143 p->ref_ev = NULL;
144 }
145 }
146
147 return 0;
148}