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