Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (c) 2010-2012 Niels Provos and Nick Mathewson
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  * 3. The name of the author may not be used to endorse or promote products
     13  *    derived from this software without specific prior written permission.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "event2/event-config.h"
     28 
     29 #ifdef _WIN32
     30 #include <winsock2.h>
     31 #include <windows.h>
     32 #else
     33 #include <unistd.h>
     34 #endif
     35 #include <sys/types.h>
     36 #include <sys/stat.h>
     37 #ifdef EVENT__HAVE_SYS_TIME_H
     38 #include <sys/time.h>
     39 #endif
     40 
     41 #ifdef EVENT__HAVE_SYS_SOCKET_H
     42 #include <sys/socket.h>
     43 #endif
     44 #include <fcntl.h>
     45 #include <stdlib.h>
     46 #include <stdio.h>
     47 #include <string.h>
     48 #include <errno.h>
     49 
     50 #include "event2/event.h"
     51 #include "event2/util.h"
     52 #include <time.h>
     53 
     54 struct cpu_usage_timer {
     55 #ifdef _WIN32
     56 	HANDLE thread;
     57 	FILETIME usertimeBegin;
     58 	FILETIME kerneltimeBegin;
     59 #else
     60 	clock_t ticksBegin;
     61 #endif
     62 	struct timeval timeBegin;
     63 };
     64 static void
     65 start_cpu_usage_timer(struct cpu_usage_timer *timer)
     66 {
     67 #ifdef _WIN32
     68 	int r;
     69 	FILETIME createtime, exittime;
     70 	timer->thread = GetCurrentThread();
     71 	r = GetThreadTimes(timer->thread, &createtime, &exittime,
     72 	    &timer->usertimeBegin, &timer->kerneltimeBegin);
     73 	if (r==0) printf("GetThreadTimes failed.");
     74 #else
     75 	timer->ticksBegin = clock();
     76 #endif
     77 
     78 	evutil_gettimeofday(&timer->timeBegin, NULL);
     79 }
     80 #ifdef _WIN32
     81 static ev_int64_t
     82 filetime_to_100nsec(const FILETIME *ft)
     83 {
     84 	/* Number of 100-nanosecond units */
     85 	ev_int64_t n = ft->dwHighDateTime;
     86 	n <<= 32;
     87 	n += ft->dwLowDateTime;
     88 	return n;
     89 }
     90 static double
     91 filetime_diff(const FILETIME *ftStart, const FILETIME *ftEnd)
     92 {
     93 	ev_int64_t s, e, diff;
     94 	double r;
     95 	s = filetime_to_100nsec(ftStart);
     96 	e = filetime_to_100nsec(ftEnd);
     97 	diff = e - s;
     98 	r = (double) diff;
     99 	return r / 1.0e7;
    100 }
    101 #endif
    102 
    103 static void
    104 get_cpu_usage(struct cpu_usage_timer *timer, double *secElapsedOut,
    105     double *secUsedOut, double *usageOut)
    106 {
    107 #ifdef _WIN32
    108 	double usertime_seconds, kerneltime_seconds;
    109 	FILETIME createtime, exittime, usertimeEnd, kerneltimeEnd;
    110 	int r;
    111 #else
    112 	clock_t ticksEnd;
    113 #endif
    114 	struct timeval timeEnd, timeDiff;
    115 	double secondsPassed, secondsUsed;
    116 
    117 #ifdef _WIN32
    118 	r = GetThreadTimes(timer->thread, &createtime, &exittime,
    119 	    &usertimeEnd, &kerneltimeEnd);
    120 	if (r==0) printf("GetThreadTimes failed.");
    121 	usertime_seconds = filetime_diff(&timer->usertimeBegin, &usertimeEnd);
    122 	kerneltime_seconds = filetime_diff(&timer->kerneltimeBegin, &kerneltimeEnd);
    123 	secondsUsed = kerneltime_seconds + usertime_seconds;
    124 #else
    125 	ticksEnd = clock();
    126 	secondsUsed = (ticksEnd - timer->ticksBegin) / (double)CLOCKS_PER_SEC;
    127 #endif
    128 	evutil_gettimeofday(&timeEnd, NULL);
    129 	evutil_timersub(&timeEnd, &timer->timeBegin, &timeDiff);
    130 	secondsPassed = timeDiff.tv_sec + (timeDiff.tv_usec / 1.0e6);
    131 
    132 	*secElapsedOut = secondsPassed;
    133 	*secUsedOut = secondsUsed;
    134 	*usageOut = secondsUsed / secondsPassed;
    135 }
    136 
    137 static void
    138 write_cb(evutil_socket_t fd, short event, void *arg)
    139 {
    140 	printf("write callback. should only see this once\n");
    141 
    142 	/* got what we want remove the event */
    143 	event_del(*(struct event**)arg);
    144 
    145 	/* opps changed my mind add it back again */
    146 	event_add(*(struct event**)arg,NULL);
    147 
    148 	/* not a good day for decisiveness, I really didn't want it after all */
    149 	event_del(*(struct event**)arg);
    150 
    151 }
    152 
    153 static void
    154 timeout_cb(evutil_socket_t fd, short event, void *arg)
    155 {
    156 	printf("timeout fired, time to end test\n");
    157 	event_del(*(struct event**)arg);
    158 	return;
    159 }
    160 
    161 int
    162 main(int argc, char **argv)
    163 {
    164 	struct event* ev;
    165 	struct event* timeout;
    166 	struct event_base* base;
    167 
    168 	evutil_socket_t pair[2];
    169 	struct timeval tv;
    170 	struct cpu_usage_timer timer;
    171 
    172 	double usage, secPassed, secUsed;
    173 
    174 #ifdef _WIN32
    175 	WORD wVersionRequested;
    176 	WSADATA wsaData;
    177 
    178 	wVersionRequested = MAKEWORD(2, 2);
    179 
    180 	(void) WSAStartup(wVersionRequested, &wsaData);
    181 #endif
    182 	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
    183 		return (1);
    184 
    185 	/* Initalize the event library */
    186 	if (!(base = event_base_new()))
    187 		return (1);
    188 
    189 	/* Initalize a timeout to terminate the test */
    190 	timeout = evtimer_new(base,timeout_cb,&timeout);
    191 	/* and watch for writability on one end of the pipe */
    192 	ev = event_new(base,pair[1],EV_WRITE | EV_PERSIST, write_cb, &ev);
    193 
    194 	tv.tv_sec  = 1;
    195 	tv.tv_usec = 500*1000;
    196 
    197 	evtimer_add(timeout, &tv);
    198 
    199 	event_add(ev, NULL);
    200 
    201 	start_cpu_usage_timer(&timer);
    202 
    203 	event_base_dispatch(base);
    204 
    205 	event_free(ev);
    206 	event_free(timeout);
    207 	event_base_free(base);
    208 
    209 	get_cpu_usage(&timer, &secPassed, &secUsed, &usage);
    210 
    211 	/* attempt to calculate our cpu usage over the test should be
    212 	   virtually nil */
    213 
    214 	printf("usec used=%d, usec passed=%d, cpu usage=%.2f%%\n",
    215 	    (int)(secUsed*1e6),
    216 	    (int)(secPassed*1e6),
    217 	    usage*100);
    218 
    219 	if (usage > 50.0) /* way too high */
    220 	  return 1;
    221 
    222 	return 0;
    223 }
    224 
    225