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