コード例 #1
0
static void
handlecompletion(G **gpp, net_op *op, int32 errno, uint32 qty)
{
	int32 mode;

	if(op == nil)
		runtime·throw("netpoll: GetQueuedCompletionStatus returned op == nil");
	mode = op->mode;
	if(mode != 'r' && mode != 'w') {
		runtime·printf("netpoll: GetQueuedCompletionStatus returned invalid mode=%d\n", mode);
		runtime·throw("netpoll: GetQueuedCompletionStatus returned invalid mode");
	}
	op->errno = errno;
	op->qty = qty;
	runtime·netpollready(gpp, op->pd, mode);
}
コード例 #2
0
ファイル: netpoll_kqueue.c プロジェクト: gnanderson/go
runtime·netpoll(bool block)
{
	static int32 lasterr;
	Kevent events[64], *ev;
	Timespec ts, *tp;
	int32 n, i, mode;
	G *gp;

	if(kq == -1)
		return nil;
	tp = nil;
	if(!block) {
		ts.tv_sec = 0;
		ts.tv_nsec = 0;
		tp = &ts;
	}
	gp = nil;
retry:
	n = runtime·kevent(kq, nil, 0, events, nelem(events), tp);
	if(n < 0) {
		if(n != -EINTR && n != lasterr) {
			lasterr = n;
			runtime·printf("runtime: kevent on fd %d failed with %d\n", kq, -n);
		}
		goto retry;
	}
	for(i = 0; i < n; i++) {
		ev = &events[i];
		mode = 0;
		if(ev->filter == EVFILT_READ)
			mode += 'r';
		if(ev->filter == EVFILT_WRITE)
			mode += 'w';
		if(mode)
			runtime·netpollready(&gp, (PollDesc*)ev->udata, mode);
	}
	if(block && gp == nil)
		goto retry;
	return gp;
}
コード例 #3
0
runtime·netpoll(bool block)
{
	static int32 lasterr;
	EpollEvent events[128], *ev;
	int32 n, i, waitms, mode;
	G *gp;

	if(epfd == -1)
		return nil;
	waitms = -1;
	if(!block)
		waitms = 0;
retry:
	n = runtime·epollwait(epfd, events, nelem(events), waitms);
	if(n < 0) {
		if(n != -EINTR && n != lasterr) {
			lasterr = n;
			runtime·printf("runtime: epollwait on fd %d failed with %d\n", epfd, -n);
		}
		goto retry;
	}
	gp = nil;
	for(i = 0; i < n; i++) {
		ev = &events[i];
		if(ev->events == 0)
			continue;
		mode = 0;
		if(ev->events & (EPOLLIN|EPOLLRDHUP|EPOLLHUP|EPOLLERR))
			mode += 'r';
		if(ev->events & (EPOLLOUT|EPOLLHUP|EPOLLERR))
			mode += 'w';
		if(mode)
			runtime·netpollready(&gp, (void*)ev->data, mode);
	}
	if(block && gp == nil)
		goto retry;
	return gp;
}
コード例 #4
0
runtime·netpoll(bool block)
{
	static int32 lasterr;
	PortEvent events[128], *ev;
	PollDesc *pd;
	int32 i, mode, clear;
	uint32 n;
	Timespec *wait = nil, zero;
	G *gp;

	if(portfd == -1)
		return (nil);

	if(!block) {
		zero.tv_sec = 0;
		zero.tv_nsec = 0;
		wait = &zero;
	}

retry:
	n = 1;
	if(runtime·port_getn(portfd, events, nelem(events), &n, wait) < 0) {
		if(errno != EINTR && errno != lasterr) {
			lasterr = errno;
			runtime·printf("runtime: port_getn on fd %d failed with %d\n", portfd, errno);
		}
		goto retry;
	}

	gp = nil;
	for(i = 0; i < n; i++) {
		ev = &events[i];

		if(ev->portev_events == 0)
			continue;
		pd = (PollDesc *)ev->portev_user;

		mode = 0;
		clear = 0;
		if(ev->portev_events & (POLLIN|POLLHUP|POLLERR)) {
			mode += 'r';
			clear |= POLLIN;
		}
		if(ev->portev_events & (POLLOUT|POLLHUP|POLLERR)) {
			mode += 'w';
			clear |= POLLOUT;
		}
		// To effect edge-triggered events, we need to be sure to
		// update our association with whatever events were not
		// set with the event. For example if we are registered
		// for POLLIN|POLLOUT, and we get POLLIN, besides waking
		// the goroutine interested in POLLIN we have to not forget
		// about the one interested in POLLOUT.
		if(clear != 0) {
			runtime·netpolllock(pd);
			runtime·netpollupdate(pd, 0, clear);
			runtime·netpollunlock(pd);
		}

		if(mode)
			runtime·netpollready(&gp, pd, mode);
	}

	if(block && gp == nil)
		goto retry;
	return gp;
}