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