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.
10 #include <sys/times.h>
11 #include <sys/types.h>
15 #ifdef HAVE_SYS_SELECT_H
16 #include <sys/select.h>
22 static Lock selectlock
;
26 static PollDesc
**data
;
30 runtime_netpollinit(void)
37 data
= runtime_mallocgc(allocated
* sizeof(PollDesc
*), 0,
38 FlagNoScan
|FlagNoProfiling
|FlagNoInvokeGC
);
41 runtime_throw("netpollinit: failed to create pipe");
45 fl
= fcntl(rdwake
, F_GETFL
);
47 runtime_throw("netpollinit: fcntl failed");
49 if(fcntl(rdwake
, F_SETFL
, fl
))
50 runtime_throw("netpollinit: fcntl failed");
51 fcntl(rdwake
, F_SETFD
, FD_CLOEXEC
);
53 fl
= fcntl(wrwake
, F_GETFL
);
55 runtime_throw("netpollinit: fcntl failed");
57 if(fcntl(wrwake
, F_SETFL
, fl
))
58 runtime_throw("netpollinit: fcntl failed");
59 fcntl(wrwake
, F_SETFD
, FD_CLOEXEC
);
65 runtime_netpollopen(uintptr fd
, PollDesc
*pd
)
69 runtime_lock(&selectlock
);
71 if((int)fd
>= allocated
) {
77 runtime_unlock(&selectlock
);
81 n
= runtime_mallocgc(c
* sizeof(PollDesc
*), 0,
82 FlagNoScan
|FlagNoProfiling
|FlagNoInvokeGC
);
84 runtime_lock(&selectlock
);
87 __builtin_memcpy(n
, data
, allocated
* sizeof(PollDesc
*));
95 runtime_unlock(&selectlock
);
98 write(wrwake
, &b
, sizeof b
);
104 runtime_netpollclose(uintptr fd
)
108 runtime_lock(&selectlock
);
113 runtime_unlock(&selectlock
);
116 write(wrwake
, &b
, sizeof b
);
121 /* Used to avoid using too much stack memory. */
123 static fd_set grfds
, gwfds
, gefds
, gtfds
;
126 runtime_netpoll(bool block
)
128 fd_set
*prfds
, *pwfds
, *pefds
, *ptfds
;
130 struct timeval timeout
;
139 runtime_lock(&selectlock
);
144 runtime_unlock(&selectlock
);
149 prfds
= runtime_SysAlloc(4 * sizeof fds
, &mstats
.other_sys
);
160 allocatedfds
= false;
163 __builtin_memcpy(prfds
, &fds
, sizeof fds
);
165 runtime_unlock(&selectlock
);
167 __builtin_memcpy(pwfds
, prfds
, sizeof fds
);
168 FD_CLR(rdwake
, pwfds
);
169 __builtin_memcpy(pefds
, pwfds
, sizeof fds
);
171 __builtin_memcpy(ptfds
, pwfds
, sizeof fds
);
173 __builtin_memset(&timeout
, 0, sizeof timeout
);
178 c
= select(max
, prfds
, pwfds
, pefds
, pt
);
181 // Some file descriptor has been closed.
182 // Check each one, and treat each closed
183 // descriptor as ready for read/write.
188 for(i
= 0; i
< max
; i
++) {
189 if(FD_ISSET(i
, ptfds
)
200 runtime_printf("runtime: select failed with %d\n", errno
);
205 for(i
= 0; i
< max
&& c
> 0; i
++) {
207 if(FD_ISSET(i
, prfds
)) {
211 if(FD_ISSET(i
, pwfds
)) {
215 if(FD_ISSET(i
, pefds
)) {
220 while(read(rdwake
, &b
, sizeof b
) > 0)
227 runtime_lock(&selectlock
);
229 runtime_unlock(&selectlock
);
231 runtime_netpollready(&gp
, pd
, mode
);
234 if(block
&& gp
== nil
)
238 runtime_SysFree(prfds
, 4 * sizeof fds
, &mstats
.other_sys
);
240 runtime_lock(&selectlock
);
242 runtime_unlock(&selectlock
);
249 runtime_netpoll_scan(struct Workbuf
** wbufp
, void (*enqueue1
)(struct Workbuf
**, Obj
))
251 enqueue1(wbufp
, (Obj
){(byte
*)&data
, sizeof data
, 0});