newlib/winsup/cygwin/profil.c
Christopher Faylor 66a83f3eac Remove unneeded header files from source files throughout. Update copyrights
where appropriate.
* globals.cc: New file for generic global variables.
* mkglobals_h: New file to generate globals.h.
* mkstatic: New Script used to build a (currently non-working) static
libcygwin_s.a.
* Makefile.in: Add unused rule to build a non-working libcygwin_s.a.
(DLL_OFILES): Add globals.o.  Make all objects rely on globals.h.
(globals.h): New target.  Generate globals.h.
* cygtls.h: Honor new CYGTLS_HANDLE define to control when the HANDLE operator
is allowed in _cygtls.
* dcrt0.cc: Move most globals to globals.cc.
* init.cc: Ditto.
* environ.cc (strip_title_path): Remove now-unneeded extern.
* fhandler_serial.cc (fhandler_serial::open): Ditto.
* pinfo.cc: Ditto.
(commune_process): Ditto.
* shared.cc: Ditto.
* glob.cc: Ditto.
* strace.cc: Ditto.
* exceptions.cc: Define CYGTLS_HANDLE before including winsup.h.
* path.cc (stat_suffixes): Move here.
* security.h: Add forward class path_conv declaration.
* smallprint.cc (__small_vsprintf): Make a true c++ function.
(__small_sprintf): Ditto.
(small_printf): Ditto.
(console_printf): Ditto.
(__small_vswprintf): Ditto.
(__small_swprintf): Ditto.
* spawn.cc (spawn_guts): Remove _stdcall decoration in favor of regparm.
(hExeced): Move to globals.cc
* strfuncs.cc (current_codepage): Ditto.
(active_codepage): Ditto.
* sync.cc (lock_process::locker): Move here from dcrt0.cc.
* syscalls.cc (stat_suffixes): Move to path.cc.
* tty.cc (tty::create_master): Uncapitalize fatal warning for consistency.
* winsup.h: Include globals.h to declare most of the grab bag list of globals
which were previously defined here.
* mount.h: Move USER_* defines back to shared_info.h.
* speclib: Force temporary directory cleanup.
2009-01-03 05:12:22 +00:00

174 lines
3.8 KiB
C

/* profil.c -- win32 profil.c equivalent
Copyright 1998, 1999, 2000, 2001, 2003, 2009 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include <windows.h>
#include <sys/types.h>
#include <errno.h>
#include <profil.h>
#define SLEEPTIME (1000 / PROF_HZ)
/* global profinfo for profil() call */
static struct profinfo prof;
/* Get the pc for thread THR */
static u_long
get_thrpc (HANDLE thr)
{
CONTEXT ctx;
u_long pc;
int res;
res = SuspendThread (thr);
if (res == -1)
return (u_long) - 1;
ctx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
pc = (u_long) - 1;
if (GetThreadContext (thr, &ctx))
pc = ctx.Eip;
ResumeThread (thr);
return pc;
}
/* Display cell of profile buffer */
#if 0
static void
print_prof (struct profinfo *p)
{
printf ("profthr %x\ttarget thr %x\n", p->profthr, p->targthr);
printf ("pc: %x - %x\n", p->lowpc, p->highpc);
printf ("scale: %x\n", p->scale);
return;
}
#endif
/* Everytime we wake up use the main thread pc to hash into the cell in the
profile buffer ARG. */
static DWORD CALLBACK
profthr_func (LPVOID arg)
{
struct profinfo *p = (struct profinfo *) arg;
u_long pc, idx;
SetThreadPriority(p->profthr, THREAD_PRIORITY_TIME_CRITICAL);
for (;;)
{
pc = (u_long) get_thrpc (p->targthr);
if (pc >= p->lowpc && pc < p->highpc)
{
idx = PROFIDX (pc, p->lowpc, p->scale);
p->counter[idx]++;
}
#if 0
print_prof (p);
#endif
Sleep (SLEEPTIME);
}
return 0;
}
/* Stop profiling to the profiling buffer pointed to by P. */
static int
profile_off (struct profinfo *p)
{
if (p->profthr)
{
TerminateThread (p->profthr, 0);
CloseHandle (p->profthr);
}
if (p->targthr)
CloseHandle (p->targthr);
return 0;
}
/* Create a timer thread and pass it a pointer P to the profiling buffer. */
static int
profile_on (struct profinfo *p)
{
DWORD thrid;
/* get handle for this thread */
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
GetCurrentProcess (), &p->targthr, 0, FALSE,
DUPLICATE_SAME_ACCESS))
{
errno = ESRCH;
return -1;
}
p->profthr = CreateThread (0, 0, profthr_func, (void *) p, 0, &thrid);
if (!p->profthr)
{
CloseHandle (p->targthr);
p->targthr = 0;
errno = EAGAIN;
return -1;
}
return 0;
}
/*
* start or stop profiling
*
* profiling goes into the SAMPLES buffer of size SIZE (which is treated
* as an array of u_shorts of size size/2)
*
* each bin represents a range of pc addresses from OFFSET. The number
* of pc addresses in a bin depends on SCALE. (A scale of 65536 maps
* each bin to two addresses, A scale of 32768 maps each bin to 4 addresses,
* a scale of 1 maps each bin to 128k addreses). Scale may be 1 - 65536,
* or zero to turn off profiling
*/
int
profile_ctl (struct profinfo * p, char *samples, size_t size,
u_long offset, u_int scale)
{
u_long maxbin;
if (scale > 65536)
{
errno = EINVAL;
return -1;
}
profile_off (p);
if (scale)
{
memset (samples, 0, size);
memset (p, 0, sizeof *p);
maxbin = size >> 1;
prof.counter = (u_short *) samples;
prof.lowpc = offset;
prof.highpc = PROFADDR (maxbin, offset, scale);
prof.scale = scale;
return profile_on (p);
}
return 0;
}
/* Equivalent to unix profil()
Every SLEEPTIME interval, the user's program counter (PC) is examined:
offset is subtracted and the result is multiplied by scale.
The word pointed to by this address is incremented. Buf is unused. */
int
profil (char *samples, size_t size, u_long offset, u_int scale)
{
return profile_ctl (&prof, samples, size, offset, scale);
}