Plan 9 from Bell Labs’s /usr/web/sources/contrib/cinap_lenrek/old/linuxemu.old/syspoll.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <ureg.h>
#include "linuxsys.h"
#include "linux.h"

SYSCALL(sys_epoll_create)
{
	int size;

	size = ARG1;
	RETURN(epoll_create(size));
}

SYSCALL(sys_epoll_ctl)
{
	int epfd;
	int op;
	int fd; 
	epoll_event *event;

	epfd = ARG1;
	op = ARG2;
	fd = ARG3;
	event = (epoll_event*)ARG4;

	RETURN(epoll_ctl(epfd, op, fd, event));
}

SYSCALL(sys_epoll_wait)
{
	int epfd;
	epoll_event *events;
	int maxevents;
	int timeout;

	epfd = ARG1;
	events = (epoll_event*)ARG2;
	maxevents = ARG3;
	timeout = ARG4;

	RETURN(epoll_wait(epfd, events, maxevents, timeout));
}

IOCTL(ioctl_FIONREAD)
{
	int *p;
	int r;

	USED(cmd);

	p = (int*)arg;
	if(p==nil)
		return -EINVAL;
	r = buffdionread(fd);
	if(r < 0){
		*p = 0;
		return r;
	}
	*p = r;
	return 0;
}

struct pollfd
{
	int			fd;
	short		events;
	short		revents;
};

SYSCALL(sys_poll)
{
	struct pollfd *fds;
	int nfds;
	long timeout;
	int epfd;
	int i, n;
	epoll_event *rev;

	fds = (struct pollfd*)ARG1;
	nfds = ARG2;
	timeout = ARG3;

	if(nfds <= 0)
		RETURN(-EINVAL);
	epfd = epoll_create(nfds);
	if(epfd < 0)
		RETURN(-EINVAL);
	for(i=0; i<nfds; i++){
		epoll_event ev;
		fds[i].revents = 0;
		ev.events = fds[i].events;
		ev.data = i;
		epoll_ctl(epfd, EPOLL_CTL_ADD, fds[i].fd, &ev);
	}
	rev = malloc(sizeof(epoll_event)*nfds);
	if(rev == nil){
		_close(epfd);
		RETURN(-ENOMEM);
	}
	n = epoll_wait(epfd, rev, nfds, timeout);
	_close(epfd);
	for(i=0; i<n; i++)
		fds[rev[i].data].revents = rev[i].events;
	free(rev);

	RETURN(n);
}


typedef ulong fdsetel;

enum
{
	FDSETBITS = 1024,
	FDSETELBYTES = sizeof(fdsetel),
	FDSETELBITS = 8*FDSETELBYTES,
	FDSETELMAX = FDSETBITS/FDSETELBITS,
};

struct fd_set
{
	fdsetel	el[FDSETELMAX];
};

struct timeval {
	long tv_sec;			/* seconds */
	long	tv_usec;			/* microseconds */
};

SYSCALL(sys_select)
{
	int nfds;
	struct fd_set *rfds;
	struct fd_set *wfds;
	struct fd_set *efds;
	struct timeval *tv;

	int i, n;
	int timeout;
	int epfd;
	vlong t;
	epoll_event *rev;

	nfds = ARG1;
	rfds = (struct fd_set*)ARG2;
	wfds = (struct fd_set*)ARG3;
	efds = (struct fd_set*)ARG4;
	tv = (struct timeval*)ARG5;

	DPRINT("select(%d, 0x%p, 0x%p, 0x%p, 0x%p)...", nfds, rfds, wfds, efds, tv);

	epfd = epoll_create(nfds);
	if(epfd < 0)
		RETURN(-EINVAL);
	n = 0;
	for(i=0; i<FDSETELMAX; i++){
		int j;

		if(!((rfds && rfds->el[i]) || (wfds && wfds->el[i]) || (efds && efds->el[i])))
			continue;

		for(j=0; j<FDSETELBITS; j++){
			epoll_event ev;	
			fdsetel bit;
			int fd;

			bit = (fdsetel)1<<j;
			fd = (i * FDSETELBITS) + j;

			if(fd >= nfds)
				goto start;			

			ev.events = 0;
			if(rfds && (rfds->el[i] & bit)){
				ev.events |= POLLIN;
				rfds->el[i] &= ~bit;
			}
			if(wfds && (wfds->el[i] & bit)){
				ev.events |= POLLOUT;
				wfds->el[i] &= ~bit;
			}
			if(efds && (efds->el[i] & bit)){
				ev.events |= POLLERR | POLLHUP | POLLRDHUP;
				efds->el[i] &= ~bit;
			}

			// no events selected, skip this fd
			if(ev.events == 0)
				continue;

			ev.data = fd;
			epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);

			n++;
		}
	}
start:
	// clear result fdsets
	if(n == 0){
		_close(epfd);
		RETURN(0);
	}

	rev = malloc(sizeof(epoll_event) * n);
	if(rev == nil){
		_close(epfd);
		RETURN(-ENOMEM);
	}

	if(tv==nil){
		timeout = -1;
	} else {
		t = nsec();
		timeout = (tv->tv_sec*1000) + (tv->tv_usec/1000);
		if(timeout < 0)
			timeout = 0;
	}
	n = epoll_wait(epfd, rev, n, timeout);
	_close(epfd);

	DPRINT("select ->\n");
	nfds = 0;
	for(i=0; i<n; i++){
		int j;
		fdsetel bit;
		int fd;

		fd = rev[i].data;
		j = fd / FDSETELBITS;
		bit = (fdsetel)1 << (fd % FDSETELBITS);

		DPRINT("%d=[", fd);
		if(rfds && (rev[i].events&POLLIN)){
			DPRINT("I");
			rfds->el[j] |= bit;
			nfds++;
		}
		if(wfds && (rev[i].events&POLLOUT)){
			DPRINT("O");
			wfds->el[j] |= bit;
			nfds++;
		}
		if(efds && (rev[i].events&(POLLERR|POLLHUP|POLLRDHUP))){
			DPRINT("E");
			efds->el[j] |= bit;
			nfds++;
		}
		DPRINT("]\n");
	}
	free(rev);

	DPRINT("got %d ready pollevents in total...", n);

	if(tv && timeout>=0){
		t = timeout*1000000 - (nsec() - t);
		if(t < 0)
			t = 0;
		tv->tv_sec = (long)(t/1000000000LL);
		tv->tv_usec = (long)((t%1000000000LL)/1000LL);
	}

	DPRINT("select returns %d\n", n);
	RETURN(nfds);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].