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); }
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; }
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); }
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); }
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); }
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); }
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); }