1
/* profil.c -- win32 profil.c equivalent
3
Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
5
This file is part of Cygwin.
7
This software is a copyrighted work licensed under the terms of the
8
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12
* This file is taken from Cygwin distribution. Please keep it in sync.
13
* The differences should be within __MINGW32__ guard.
16
#ifndef WIN32_LEAN_AND_MEAN
17
#define WIN32_LEAN_AND_MEAN
21
#include <sys/types.h>
26
#define SLEEPTIME (1000 / PROF_HZ)
28
/* global profinfo for profil() call */
29
static struct profinfo prof;
31
/* Get the pc for thread THR */
34
get_thrpc (HANDLE thr)
40
res = SuspendThread (thr);
43
ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
45
if (GetThreadContext (thr, &ctx)) {
56
/* Display cell of profile buffer */
59
print_prof (struct profinfo *p)
61
printf ("profthr %x\ttarget thr %x\n", p->profthr, p->targthr);
62
printf ("pc: %x - %x\n", p->lowpc, p->highpc);
63
printf ("scale: %x\n", p->scale);
68
/* Everytime we wake up use the main thread pc to hash into the cell in the
69
profile buffer ARG. */
71
static void CALLBACK profthr_func (LPVOID);
74
profthr_func (LPVOID arg)
76
struct profinfo *p = (struct profinfo *) arg;
81
pc = (size_t) get_thrpc (p->targthr);
82
if (pc >= p->lowpc && pc < p->highpc)
84
idx = PROFIDX (pc, p->lowpc, p->scale);
90
/* Check quit condition, WAIT_OBJECT_0 or WAIT_TIMEOUT */
91
if (WaitForSingleObject (p->quitevt, SLEEPTIME) == WAIT_OBJECT_0)
96
/* Stop profiling to the profiling buffer pointed to by P. */
99
profile_off (struct profinfo *p)
103
SignalObjectAndWait (p->quitevt, p->profthr, INFINITE, FALSE);
104
CloseHandle (p->quitevt);
105
CloseHandle (p->profthr);
108
CloseHandle (p->targthr);
112
/* Create a timer thread and pass it a pointer P to the profiling buffer. */
115
profile_on (struct profinfo *p)
119
/* get handle for this thread */
120
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
121
GetCurrentProcess (), &p->targthr, 0, FALSE,
122
DUPLICATE_SAME_ACCESS))
128
p->quitevt = CreateEvent (NULL, TRUE, FALSE, NULL);
132
CloseHandle (p->quitevt);
138
p->profthr = CreateThread (0, 0, (DWORD (WINAPI *)(LPVOID)) profthr_func,
139
(void *) p, 0, &thrid);
143
CloseHandle (p->targthr);
144
CloseHandle (p->quitevt);
150
/* Set profiler thread priority to highest to be sure that it gets the
151
processor as soon it request it (i.e. when the Sleep terminate) to get
152
the next data out of the profile. */
154
SetThreadPriority (p->profthr, THREAD_PRIORITY_TIME_CRITICAL);
160
* start or stop profiling
162
* profiling goes into the SAMPLES buffer of size SIZE (which is treated
163
* as an array of u_shorts of size size/2)
165
* each bin represents a range of pc addresses from OFFSET. The number
166
* of pc addresses in a bin depends on SCALE. (A scale of 65536 maps
167
* each bin to two addresses, A scale of 32768 maps each bin to 4 addresses,
168
* a scale of 1 maps each bin to 128k addreses). Scale may be 1 - 65536,
169
* or zero to turn off profiling
172
profile_ctl (struct profinfo * p, char *samples, size_t size,
173
size_t offset, u_int scale)
186
memset (samples, 0, size);
187
memset (p, 0, sizeof *p);
189
prof.counter = (u_short *) samples;
191
prof.highpc = PROFADDR (maxbin, offset, scale);
194
return profile_on (p);
199
/* Equivalent to unix profil()
200
Every SLEEPTIME interval, the user's program counter (PC) is examined:
201
offset is subtracted and the result is multiplied by scale.
202
The word pointed to by this address is incremented. Buf is unused. */
205
profil (char *samples, size_t size, size_t offset, u_int scale)
207
return profile_ctl (&prof, samples, size, offset, scale);