static void *
acceptor(void *param)
{
	struct sockaddr_in sin;
	pthread_t tid;
	int news;
	int s;
	static int first;

	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("cannot create socket");
		exit(4);
	}

	sin.sin_len = sizeof(sin);
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = htonl(INADDR_ANY);
	sin.sin_port = htons(TEST_PORT);

	if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
		perror("cannot bind socket");
		exit(4);
	}

	if (listen(s, 1) < 0) {
		perror("cannot listen socket");
		exit(4);
	}

	(void) mevent_add(s, EVF_READ, acceptor_callback, NULL);

	pthread_mutex_lock(&accept_mutex);

	while (!pthread_cond_wait(&accept_condvar, &accept_mutex)) {
		news = accept(s, NULL, NULL);
		if (news < 0) {
			perror("accept error");
		} else {
			static int first = 1;

			if (first) {
				/*
				 * Start a timer
				 */
				first = 0;
				tevp = mevent_add(1, EVF_TIMER, timer_callback,
						  NULL);
			}

			printf("incoming connection, spawning thread\n");
			pthread_create(&tid, NULL, echoer,
				       (void *)(uintptr_t)news);
		}
	}

	return (NULL);
}
Beispiel #2
0
int32_t
acrn_timer_init(struct acrn_timer *timer, void (*cb)(void *, uint64_t),
		void *param)
{
	if ((timer == NULL) || (cb == NULL)) {
		return -1;
	}

	timer->fd = -1;
	if ((timer->clockid == CLOCK_REALTIME) ||
			(timer->clockid == CLOCK_MONOTONIC)) {
		timer->fd = timerfd_create(timer->clockid,
					TFD_NONBLOCK | TFD_CLOEXEC);
	} else {
		perror("acrn_timer clockid is not supported.\n");
	}

	if (timer->fd <= 0) {
		perror("acrn_timer create failed.\n");
		return -1;
	}

	timer->mevp = mevent_add(timer->fd, EVF_READ, timer_handler, timer, NULL, NULL);
	if (timer->mevp == NULL) {
		close(timer->fd);
		perror("acrn_timer mevent add failed.\n");
		return -1;
	}

	timer->callback = cb;
	timer->callback_param = param;

	return 0;
}
Beispiel #3
0
static void
uart_opentty(struct uart_softc *sc)
{

	ttyopen(&sc->tty);
	sc->mev = mevent_add(sc->tty.fd, EVF_READ, uart_drain, sc);
	assert(sc->mev != NULL);
}
Beispiel #4
0
static void
pci_uart_opentty(struct pci_uart_softc *sc)
{
	struct mevent *mev;

	assert(sc->opened == 0);
	assert(sc->stdio);

	ttyopen();
	mev = mevent_add(STDIN_FILENO, EVF_READ, pci_uart_drain, sc);
	assert(mev);
}
Beispiel #5
0
static void
pit_timer_start(struct vmctx *ctx, struct counter *c)
{
	int msecs;

	if (c->initial != 0) {
		msecs = c->initial * nsecs_per_tick / 1000000;
		if (msecs == 0)
			msecs = 1;

		if (c->tevp == NULL)
			c->tevp = mevent_add(msecs, EVF_TIMER, pit_mevent_cb,
			    c);
	}
}
static void
pci_vtnet_tap_setup(struct pci_vtnet_softc *sc, char *devname)
{
	char tbuf[80];
#ifndef WITHOUT_CAPSICUM
	cap_rights_t rights;
#endif

	strcpy(tbuf, "/dev/");
	strlcat(tbuf, devname, sizeof(tbuf));

	sc->pci_vtnet_rx = pci_vtnet_tap_rx;
	sc->pci_vtnet_tx = pci_vtnet_tap_tx;

	sc->vsc_tapfd = open(tbuf, O_RDWR);
	if (sc->vsc_tapfd == -1) {
		WPRINTF(("open of tap device %s failed\n", tbuf));
		return;
	}

	/*
	 * Set non-blocking and register for read
	 * notifications with the event loop
	 */
	int opt = 1;
	if (ioctl(sc->vsc_tapfd, FIONBIO, &opt) < 0) {
		WPRINTF(("tap device O_NONBLOCK failed\n"));
		close(sc->vsc_tapfd);
		sc->vsc_tapfd = -1;
	}

#ifndef WITHOUT_CAPSICUM
	cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE);
	if (caph_rights_limit(sc->vsc_tapfd, &rights) == -1)
		errx(EX_OSERR, "Unable to apply rights for sandbox");
#endif

	sc->vsc_mevp = mevent_add(sc->vsc_tapfd,
				  EVF_READ,
				  pci_vtnet_rx_callback,
				  sc);
	if (sc->vsc_mevp == NULL) {
		WPRINTF(("Could not register event\n"));
		close(sc->vsc_tapfd);
		sc->vsc_tapfd = -1;
	}
}
static void
pci_vtcon_sock_accept(int fd __unused, enum ev_type t __unused, void *arg)
{
	struct pci_vtcon_sock *sock = (struct pci_vtcon_sock *)arg;
	int s;

	s = accept(sock->vss_server_fd, NULL, NULL);
	if (s < 0)
		return;

	if (sock->vss_open) {
		close(s);
		return;
	}

	sock->vss_open = true;
	sock->vss_conn_fd = s;
	sock->vss_conn_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_rx, sock);
	pci_vtcon_open_port(sock->vss_port, true);
}
static void
pci_vtnet_netmap_setup(struct pci_vtnet_softc *sc, char *ifname)
{
	sc->pci_vtnet_rx = pci_vtnet_netmap_rx;
	sc->pci_vtnet_tx = pci_vtnet_netmap_tx;

	sc->vsc_nmd = nm_open(ifname, NULL, 0, 0);
	if (sc->vsc_nmd == NULL) {
		WPRINTF(("open of netmap device %s failed\n", ifname));
		return;
	}

	sc->vsc_mevp = mevent_add(sc->vsc_nmd->fd,
				  EVF_READ,
				  pci_vtnet_rx_callback,
				  sc);
	if (sc->vsc_mevp == NULL) {
		WPRINTF(("Could not register event\n"));
		nm_close(sc->vsc_nmd);
		sc->vsc_nmd = NULL;
	}
}
static void *
echoer(void *param)
{
	struct esync sync;
	struct mevent *mev;
	char buf[128];
	int fd = (int)(uintptr_t) param;
	int len;

	pthread_mutex_init(&sync.e_mt, NULL);
	pthread_cond_init(&sync.e_cond, NULL);

	pthread_mutex_lock(&sync.e_mt);

	mev = mevent_add(fd, EVF_READ, echoer_callback, &sync);
	if (mev == NULL) {
		printf("Could not allocate echoer event\n");
		exit(4);
	}

	while (!pthread_cond_wait(&sync.e_cond, &sync.e_mt)) {
		len = read(fd, buf, sizeof(buf));
		if (len > 0) {
			write(fd, buf, len);
			write(0, buf, len);
		} else {
			break;
		}
	}

	mevent_delete_close(mev);

	pthread_mutex_unlock(&sync.e_mt);
	pthread_mutex_destroy(&sync.e_mt);
	pthread_cond_destroy(&sync.e_cond);

	return (NULL);
}
Beispiel #10
0
static int
pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
	MD5_CTX mdctx;
	unsigned char digest[16];
	char nstr[80];
	char tname[MAXCOMLEN + 1];
	struct pci_vtnet_softc *sc;
	char *devname;
	char *vtopts;
	int mac_provided;

	sc = calloc(1, sizeof(struct pci_vtnet_softc));

	pthread_mutex_init(&sc->vsc_mtx, NULL);

	vi_softc_linkup(&sc->vsc_vs, &vtnet_vi_consts, sc, pi, sc->vsc_queues);
	sc->vsc_vs.vs_mtx = &sc->vsc_mtx;

	sc->vsc_queues[VTNET_RXQ].vq_qsize = VTNET_RINGSZ;
	sc->vsc_queues[VTNET_RXQ].vq_notify = pci_vtnet_ping_rxq;
	sc->vsc_queues[VTNET_TXQ].vq_qsize = VTNET_RINGSZ;
	sc->vsc_queues[VTNET_TXQ].vq_notify = pci_vtnet_ping_txq;
#ifdef notyet
	sc->vsc_queues[VTNET_CTLQ].vq_qsize = VTNET_RINGSZ;
        sc->vsc_queues[VTNET_CTLQ].vq_notify = pci_vtnet_ping_ctlq;
#endif
 
	/*
	 * Attempt to open the tap device and read the MAC address
	 * if specified
	 */
	mac_provided = 0;
	sc->vsc_tapfd = -1;
	if (opts != NULL) {
		char tbuf[80];
		int err;

		devname = vtopts = strdup(opts);
		(void) strsep(&vtopts, ",");

		if (vtopts != NULL) {
			err = pci_vtnet_parsemac(vtopts, sc->vsc_config.mac);
			if (err != 0) {
				free(devname);
				return (err);
			}
			mac_provided = 1;
		}

		strcpy(tbuf, "/dev/");
		strlcat(tbuf, devname, sizeof(tbuf));

		free(devname);

		sc->vsc_tapfd = open(tbuf, O_RDWR);
		if (sc->vsc_tapfd == -1) {
			WPRINTF(("open of tap device %s failed\n", tbuf));
		} else {
			/*
			 * Set non-blocking and register for read
			 * notifications with the event loop
			 */
			int opt = 1;
			if (ioctl(sc->vsc_tapfd, FIONBIO, &opt) < 0) {
				WPRINTF(("tap device O_NONBLOCK failed\n"));
				close(sc->vsc_tapfd);
				sc->vsc_tapfd = -1;
			}

			sc->vsc_mevp = mevent_add(sc->vsc_tapfd,
						  EVF_READ,
						  pci_vtnet_tap_callback,
						  sc);
			if (sc->vsc_mevp == NULL) {
				WPRINTF(("Could not register event\n"));
				close(sc->vsc_tapfd);
				sc->vsc_tapfd = -1;
			}
		}		
	}

	/*
	 * The default MAC address is the standard NetApp OUI of 00-a0-98,
	 * followed by an MD5 of the PCI slot/func number and dev name
	 */
	if (!mac_provided) {
		snprintf(nstr, sizeof(nstr), "%d-%d-%s", pi->pi_slot,
		    pi->pi_func, vmname);

		MD5Init(&mdctx);
		MD5Update(&mdctx, nstr, strlen(nstr));
		MD5Final(digest, &mdctx);

		sc->vsc_config.mac[0] = 0x00;
		sc->vsc_config.mac[1] = 0xa0;
		sc->vsc_config.mac[2] = 0x98;
		sc->vsc_config.mac[3] = digest[0];
		sc->vsc_config.mac[4] = digest[1];
		sc->vsc_config.mac[5] = digest[2];
	}

	/* initialize config space */
	pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_NET);
	pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_NETWORK);
	pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_NET);

	pci_lintr_request(pi);

	/* link always up */
	sc->vsc_config.status = 1;
	
	/* use BAR 1 to map MSI-X table and PBA, if we're using MSI-X */
	if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix()))
		return (1);

	/* use BAR 0 to map config regs in IO space */
	vi_set_io_bar(&sc->vsc_vs, 0);

	sc->resetting = 0;

	sc->rx_merge = 1;
	sc->rx_vhdrlen = sizeof(struct virtio_net_rxhdr);
	sc->rx_in_progress = 0;
	pthread_mutex_init(&sc->rx_mtx, NULL); 

	/* 
	 * Initialize tx semaphore & spawn TX processing thread.
	 * As of now, only one thread for TX desc processing is
	 * spawned. 
	 */
	sc->tx_in_progress = 0;
	pthread_mutex_init(&sc->tx_mtx, NULL);
	pthread_cond_init(&sc->tx_cond, NULL);
	pthread_create(&sc->tx_tid, NULL, pci_vtnet_tx_thread, (void *)sc);
	snprintf(tname, sizeof(tname), "vtnet-%d:%d tx", pi->pi_slot,
	    pi->pi_func);
        pthread_set_name_np(sc->tx_tid, tname);

	return (0);
}
Beispiel #11
0
int
main(int argc, const char *argv[])
{
	int pipefds[2];
	struct mevent *timer;
	ssize_t written;
	char *msgs[] = { "first", "second" };
	char *msg;

	start_test(argv[0], 5);
	start_event_thread();

	if (pipe(pipefds) != 0) {
		FAIL_ERRNO("pipe");
	}
	if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) != 0) {
		FAIL_ERRNO("set pipe nonblocking");
	}

	/*
	 * First write
	 */
	msg = msgs[0];
	read_event = mevent_add(pipefds[0], EVF_READ, munch, msg);
	ASSERT_PTR_NEQ(("mevent_add pipefd"), read_event, NULL);

	pthread_mutex_lock(&mtx);
	written = write(pipefds[1], msg, strlen(msg));
	if (written < 0) {
		FAIL_ERRNO("bad write");
	}
	ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));

	/*
	 * Wait for it to be read
	 */
	pthread_cond_wait(&cv, &mtx);
	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_READ);
	pthread_mutex_unlock(&mtx);

	/*
	 * Add timer, second write.
	 */
	msg = msgs[1];
	timer = mevent_add(50, EVF_TIMER, tick, msg);
	ASSERT_PTR_NEQ(("mevent_add timer"), timer, NULL);

	pthread_mutex_lock(&mtx);
	written = write(pipefds[1], msg, strlen(msg));
	if (written < 0) {
		FAIL_ERRNO("bad write");
	}
	ASSERT_INT64_EQ(("write '%s' failed", msg), written, strlen(msg));

	/*
	 * Wait for timer to expire
	 */
	pthread_cond_wait(&cv, &mtx);
	ASSERT_INT_EQ(("wrong lastwake"), lastwake, CB_TIMER);
	pthread_mutex_unlock(&mtx);

	PASS();
}
static int
pci_vtcon_sock_add(struct pci_vtcon_softc *sc, const char *name,
    const char *path)
{
	struct pci_vtcon_sock *sock;
	struct sockaddr_un sun;
	char *pathcopy;
	int s = -1, fd = -1, error = 0;

	sock = calloc(1, sizeof(struct pci_vtcon_sock));
	if (sock == NULL) {
		error = -1;
		goto out;
	}

	s = socket(AF_UNIX, SOCK_STREAM, 0);
	if (s < 0) {
		error = -1;
		goto out;
	}

	pathcopy = strdup(path);
	if (pathcopy == NULL) {
		error = -1;
		goto out;
	}

	fd = open(dirname(pathcopy), O_RDONLY | O_DIRECTORY);
	if (fd < 0) {
		free(pathcopy);
		error = -1;
		goto out;
	}

	sun.sun_family = AF_UNIX;
	sun.sun_len = sizeof(struct sockaddr_un);
	strcpy(pathcopy, path);
	strncpy(sun.sun_path, basename(pathcopy), sizeof(sun.sun_path));
	free(pathcopy);

	if (bindat(fd, s, (struct sockaddr *)&sun, sun.sun_len) < 0) {
		error = -1;
		goto out;
	}

	if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
		error = -1;
		goto out;
	}

	if (listen(s, 1) < 0) {
		error = -1;
		goto out;
	}


	sock->vss_port = pci_vtcon_port_add(sc, name, pci_vtcon_sock_tx, sock);
	if (sock->vss_port == NULL) {
		error = -1;
		goto out;
	}

	sock->vss_open = false;
	sock->vss_conn_fd = -1;
	sock->vss_server_fd = s;
	sock->vss_server_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_accept,
	    sock);

	if (sock->vss_server_evp == NULL) {
		error = -1;
		goto out;
	}

out:
	if (fd != -1)
		close(fd);

	if (error != 0 && s != -1)
		close(s);

	return (error);
}