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