Esempio n. 1
0
// Polls for ready network connections.
// Returns list of goroutines that become runnable.
G*
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;
}
Esempio n. 2
0
// polls for ready network connections
// returns list of goroutines that become runnable
G*
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.ptr, mode);
	}
	if(block && gp == nil)
		goto retry;
	return gp;
}
Esempio n. 3
0
G*
runtime_netpoll(bool block)
{
	fd_set *prfds, *pwfds, *pefds, *ptfds;
	bool allocatedfds;
	struct timeval timeout;
	struct timeval *pt;
	int max, c, i;
	G *gp;
	int32 mode;
	byte b;
	struct stat st;

 retry:
	runtime_lock(&selectlock);

	max = allocated;

	if(max == 0) {
		runtime_unlock(&selectlock);
		return nil;
	}

	if(inuse) {
		prfds = runtime_SysAlloc(4 * sizeof fds, &mstats.other_sys);
		pwfds = prfds + 1;
		pefds = pwfds + 1;
		ptfds = pefds + 1;
		allocatedfds = true;
	} else {
		prfds = &grfds;
		pwfds = &gwfds;
		pefds = &gefds;
		ptfds = &gtfds;
		inuse = true;
		allocatedfds = false;
	}

	__builtin_memcpy(prfds, &fds, sizeof fds);

	runtime_unlock(&selectlock);

	__builtin_memcpy(pwfds, prfds, sizeof fds);
	FD_CLR(rdwake, pwfds);
	__builtin_memcpy(pefds, pwfds, sizeof fds);

	__builtin_memcpy(ptfds, pwfds, sizeof fds);

	__builtin_memset(&timeout, 0, sizeof timeout);
	pt = &timeout;
	if(block)
		pt = nil;

	c = select(max, prfds, pwfds, pefds, pt);
	if(c < 0) {
		if(errno == EBADF) {
			// Some file descriptor has been closed.
			// Check each one, and treat each closed
			// descriptor as ready for read/write.
			c = 0;
			FD_ZERO(prfds);
			FD_ZERO(pwfds);
			FD_ZERO(pefds);
			for(i = 0; i < max; i++) {
				if(FD_ISSET(i, ptfds)
				   && fstat(i, &st) < 0
				   && errno == EBADF) {
					FD_SET(i, prfds);
					FD_SET(i, pwfds);
					c += 2;
				}
			}
		}
		else {
			if(errno != EINTR)
				runtime_printf("runtime: select failed with %d\n", errno);
			goto retry;
		}
	}
	gp = nil;
	for(i = 0; i < max && c > 0; i++) {
		mode = 0;
		if(FD_ISSET(i, prfds)) {
			mode += 'r';
			--c;
		}
		if(FD_ISSET(i, pwfds)) {
			mode += 'w';
			--c;
		}
		if(FD_ISSET(i, pefds)) {
			mode = 'r' + 'w';
			--c;
		}
		if(i == rdwake) {
			while(read(rdwake, &b, sizeof b) > 0)
				;
			continue;
		}
		if(mode) {
			PollDesc *pd;

			runtime_lock(&selectlock);
			pd = data[i];
			runtime_unlock(&selectlock);
			if(pd != nil)
				runtime_netpollready(&gp, pd, mode);
		}
	}
	if(block && gp == nil)
		goto retry;

	if(allocatedfds) {
		runtime_SysFree(prfds, 4 * sizeof fds, &mstats.other_sys);
	} else {
		runtime_lock(&selectlock);
		inuse = false;
		runtime_unlock(&selectlock);
	}

	return gp;
}