Date: Thu, 19 Sep 2013 04:48:26 +0000 (UTC) From: Peter Grehan <grehan@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r255690 - head/usr.sbin/bhyve Message-ID: <201309190448.r8J4mQP8003412@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: grehan Date: Thu Sep 19 04:48:26 2013 New Revision: 255690 URL: http://svnweb.freebsd.org/changeset/base/255690 Log: Add simplistic periodic timer support to mevent using kqueue's timer support. This should be enough for the emulation of h/w periodic timers (and no more) e.g. some of the 8254's more esoteric modes that happen to be used by non-FreeBSD o/s's. Approved by: re@ (blanket) Modified: head/usr.sbin/bhyve/mevent.c head/usr.sbin/bhyve/mevent.h head/usr.sbin/bhyve/mevent_test.c Modified: head/usr.sbin/bhyve/mevent.c ============================================================================== --- head/usr.sbin/bhyve/mevent.c Thu Sep 19 04:29:03 2013 (r255689) +++ head/usr.sbin/bhyve/mevent.c Thu Sep 19 04:48:26 2013 (r255690) @@ -59,12 +59,15 @@ __FBSDID("$FreeBSD$"); extern char *vmname; static pthread_t mevent_tid; +static int mevent_timid = 43; static int mevent_pipefd[2]; static pthread_mutex_t mevent_lmutex = PTHREAD_MUTEX_INITIALIZER; struct mevent { void (*me_func)(int, enum ev_type, void *); +#define me_msecs me_fd int me_fd; + int me_timid; enum ev_type me_type; void *me_param; int me_cq; @@ -129,6 +132,9 @@ mevent_kq_filter(struct mevent *mevp) if (mevp->me_type == EVF_WRITE) retval = EVFILT_WRITE; + if (mevp->me_type == EVF_TIMER) + retval = EVFILT_TIMER; + return (retval); } @@ -140,6 +146,8 @@ mevent_kq_flags(struct mevent *mevp) switch (mevp->me_state) { case MEV_ENABLE: ret = EV_ADD; + if (mevp->me_type == EVF_TIMER) + ret |= EV_ENABLE; break; case MEV_DISABLE: ret = EV_DISABLE; @@ -177,11 +185,16 @@ mevent_build(int mfd, struct kevent *kev */ close(mevp->me_fd); } else { - kev[i].ident = mevp->me_fd; + if (mevp->me_type == EVF_TIMER) { + kev[i].ident = mevp->me_timid; + kev[i].data = mevp->me_msecs; + } else { + kev[i].ident = mevp->me_fd; + kev[i].data = 0; + } kev[i].filter = mevent_kq_filter(mevp); kev[i].flags = mevent_kq_flags(mevp); kev[i].fflags = mevent_kq_fflags(mevp); - kev[i].data = 0; kev[i].udata = mevp; i++; } @@ -219,12 +232,12 @@ mevent_handle(struct kevent *kev, int nu } struct mevent * -mevent_add(int fd, enum ev_type type, +mevent_add(int tfd, enum ev_type type, void (*func)(int, enum ev_type, void *), void *param) { struct mevent *lp, *mevp; - if (fd < 0 || func == NULL) { + if (tfd < 0 || func == NULL) { return (NULL); } @@ -236,13 +249,15 @@ mevent_add(int fd, enum ev_type type, * Verify that the fd/type tuple is not present in any list */ LIST_FOREACH(lp, &global_head, me_list) { - if (lp->me_fd == fd && lp->me_type == type) { + if (type != EVF_TIMER && lp->me_fd == tfd && + lp->me_type == type) { goto exit; } } LIST_FOREACH(lp, &change_head, me_list) { - if (lp->me_fd == fd && lp->me_type == type) { + if (type != EVF_TIMER && lp->me_fd == tfd && + lp->me_type == type) { goto exit; } } @@ -256,7 +271,11 @@ mevent_add(int fd, enum ev_type type, } memset(mevp, 0, sizeof(struct mevent)); - mevp->me_fd = fd; + if (type == EVF_TIMER) { + mevp->me_msecs = tfd; + mevp->me_timid = mevent_timid++; + } else + mevp->me_fd = tfd; mevp->me_type = type; mevp->me_func = func; mevp->me_param = param; Modified: head/usr.sbin/bhyve/mevent.h ============================================================================== --- head/usr.sbin/bhyve/mevent.h Thu Sep 19 04:29:03 2013 (r255689) +++ head/usr.sbin/bhyve/mevent.h Thu Sep 19 04:48:26 2013 (r255690) @@ -31,7 +31,8 @@ enum ev_type { EVF_READ, - EVF_WRITE + EVF_WRITE, + EVF_TIMER }; struct mevent; Modified: head/usr.sbin/bhyve/mevent_test.c ============================================================================== --- head/usr.sbin/bhyve/mevent_test.c Thu Sep 19 04:29:03 2013 (r255689) +++ head/usr.sbin/bhyve/mevent_test.c Thu Sep 19 04:48:26 2013 (r255690) @@ -34,12 +34,16 @@ */ #include <sys/types.h> +#include <sys/stdint.h> +#include <sys/sysctl.h> #include <sys/socket.h> #include <netinet/in.h> +#include <machine/cpufunc.h> #include <stdio.h> #include <stdlib.h> #include <pthread.h> +#include <unistd.h> #include "mevent.h" @@ -48,8 +52,62 @@ static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t accept_condvar = PTHREAD_COND_INITIALIZER; +static struct mevent *tevp; + +char *vmname = "test vm"; + + #define MEVENT_ECHO +/* Number of timer events to capture */ +#define TEVSZ 4096 +uint64_t tevbuf[TEVSZ]; + +static void +timer_print(void) +{ + uint64_t min, max, diff, sum, tsc_freq; + size_t len; + int j; + + min = UINT64_MAX; + max = 0; + sum = 0; + + len = sizeof(tsc_freq); + sysctlbyname("machdep.tsc_freq", &tsc_freq, &len, NULL, 0); + + for (j = 1; j < TEVSZ; j++) { + /* Convert a tsc diff into microseconds */ + diff = (tevbuf[j] - tevbuf[j-1]) * 1000000 / tsc_freq; + sum += diff; + if (min > diff) + min = diff; + if (max < diff) + max = diff; + } + + printf("timers done: usecs, min %ld, max %ld, mean %ld\n", min, max, + sum/(TEVSZ - 1)); +} + +static void +timer_callback(int fd, enum ev_type type, void *param) +{ + static int i; + + if (i >= TEVSZ) + abort(); + + tevbuf[i++] = rdtsc(); + + if (i == TEVSZ) { + mevent_delete(tevp); + timer_print(); + } +} + + #ifdef MEVENT_ECHO struct esync { pthread_mutex_t e_mt; @@ -101,6 +159,8 @@ echoer(void *param) pthread_mutex_unlock(&sync.e_mt); pthread_mutex_destroy(&sync.e_mt); pthread_cond_destroy(&sync.e_cond); + + return (NULL); } #else @@ -115,6 +175,8 @@ echoer(void *param) while ((len = read(fd, buf, sizeof(buf))) > 0) { write(1, buf, len); } + + return (NULL); } #endif /* MEVENT_ECHO */ @@ -133,6 +195,7 @@ acceptor(void *param) pthread_t tid; int news; int s; + static int first; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); @@ -163,11 +226,24 @@ acceptor(void *param) 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); } main()
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309190448.r8J4mQP8003412>