2014-07-29 Ed Smith-Rowland <3dw4rd@verizon.net>
[official-gcc.git] / libgo / runtime / netpoll_epoll.c
blob1281f45b085bbc4a36c744f6ff9af543ae58af58
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build linux
7 #include <errno.h>
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <sys/epoll.h>
12 #include "runtime.h"
13 #include "defs.h"
14 #include "malloc.h"
16 #ifndef EPOLLRDHUP
17 #define EPOLLRDHUP 0x2000
18 #endif
20 #ifndef EPOLL_CLOEXEC
21 #define EPOLL_CLOEXEC 02000000
22 #endif
24 #ifndef HAVE_EPOLL_CREATE1
25 extern int epoll_create1(int __flags);
26 #endif
28 typedef struct epoll_event EpollEvent;
30 static int32
31 runtime_epollcreate(int32 size)
33 int r;
35 r = epoll_create(size);
36 if(r >= 0)
37 return r;
38 return - errno;
41 static int32
42 runtime_epollcreate1(int32 flags)
44 int r;
46 r = epoll_create1(flags);
47 if(r >= 0)
48 return r;
49 return - errno;
52 static int32
53 runtime_epollctl(int32 epfd, int32 op, int32 fd, EpollEvent *ev)
55 int r;
57 r = epoll_ctl(epfd, op, fd, ev);
58 if(r >= 0)
59 return r;
60 return - errno;
63 static int32
64 runtime_epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout)
66 int r;
68 r = epoll_wait(epfd, ev, nev, timeout);
69 if(r >= 0)
70 return r;
71 return - errno;
74 static void
75 runtime_closeonexec(int32 fd)
77 fcntl(fd, F_SETFD, FD_CLOEXEC);
80 static int32 epfd = -1; // epoll descriptor
82 void
83 runtime_netpollinit(void)
85 epfd = runtime_epollcreate1(EPOLL_CLOEXEC);
86 if(epfd >= 0)
87 return;
88 epfd = runtime_epollcreate(1024);
89 if(epfd >= 0) {
90 runtime_closeonexec(epfd);
91 return;
93 runtime_printf("netpollinit: failed to create descriptor (%d)\n", -epfd);
94 runtime_throw("netpollinit: failed to create descriptor");
97 int32
98 runtime_netpollopen(uintptr fd, PollDesc *pd)
100 EpollEvent ev;
101 int32 res;
103 ev.events = EPOLLIN|EPOLLOUT|EPOLLRDHUP|EPOLLET;
104 ev.data.ptr = (void*)pd;
105 res = runtime_epollctl(epfd, EPOLL_CTL_ADD, (int32)fd, &ev);
106 return -res;
109 int32
110 runtime_netpollclose(uintptr fd)
112 EpollEvent ev;
113 int32 res;
115 res = runtime_epollctl(epfd, EPOLL_CTL_DEL, (int32)fd, &ev);
116 return -res;
119 void
120 runtime_netpollarm(PollDesc* pd, int32 mode)
122 USED(pd);
123 USED(mode);
124 runtime_throw("unused");
127 // polls for ready network connections
128 // returns list of goroutines that become runnable
130 runtime_netpoll(bool block)
132 static int32 lasterr;
133 EpollEvent events[128], *ev;
134 int32 n, i, waitms, mode;
135 G *gp;
137 if(epfd == -1)
138 return nil;
139 waitms = -1;
140 if(!block)
141 waitms = 0;
142 retry:
143 n = runtime_epollwait(epfd, events, nelem(events), waitms);
144 if(n < 0) {
145 if(n != -EINTR && n != lasterr) {
146 lasterr = n;
147 runtime_printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
149 goto retry;
151 gp = nil;
152 for(i = 0; i < n; i++) {
153 ev = &events[i];
154 if(ev->events == 0)
155 continue;
156 mode = 0;
157 if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
158 mode += 'r';
159 if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
160 mode += 'w';
161 if(mode)
162 runtime_netpollready(&gp, (void*)ev->data.ptr, mode);
164 if(block && gp == nil)
165 goto retry;
166 return gp;
169 void
170 runtime_netpoll_scan(struct Workbuf** wbufp, void (*enqueue1)(struct Workbuf**, Obj))
172 USED(wbufp);
173 USED(enqueue1);