Index: winsup/cygwin/dcrt0.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v retrieving revision 1.392 diff -u -r1.392 dcrt0.cc --- winsup/cygwin/dcrt0.cc 22 Feb 2011 09:17:57 -0000 1.392 +++ winsup/cygwin/dcrt0.cc 6 Mar 2011 12:55:23 -0000 @@ -691,10 +691,14 @@ windows_system_directory[windows_system_directory_length++] = L'\\'; windows_system_directory[windows_system_directory_length] = L'\0'; } - +extern "C" { +void _monstartup2 (void); +void _mcleanup (void); +} void __stdcall dll_crt0_0 () { + _monstartup2(); init_windows_system_directory (); init_global_security (); initial_env (); @@ -720,7 +724,6 @@ device::init (); do_global_ctors (&__CTOR_LIST__, 1); cygthread::init (); - child_proc_info = get_cygwin_startup_info (); if (!child_proc_info) memory_init (true); @@ -738,6 +741,7 @@ break; } } + atexit (&_mcleanup); user_data->threadinterface->Init (); Index: winsup/cygwin/gmon.c =================================================================== RCS file: /cvs/src/src/winsup/cygwin/gmon.c,v retrieving revision 1.7 diff -u -r1.7 gmon.c --- winsup/cygwin/gmon.c 30 Aug 2010 01:57:36 -0000 1.7 +++ winsup/cygwin/gmon.c 6 Mar 2011 12:55:25 -0000 @@ -49,7 +49,7 @@ struct gmonparam _gmonparam = { GMON_PROF_OFF }; -static int s_scale; +int s_scale; /* see profil(2) where this is describe (incorrectly) */ #define SCALE_1_TO_1 0x10000L @@ -60,7 +60,7 @@ static void * fake_sbrk(int size) { - void *rv = malloc(size); + void *rv = LocalAlloc(0,size); if (rv) return rv; else @@ -204,8 +204,10 @@ } #else { - char gmon_out[] = "gmon.out"; + char gmon_out[100]; + sprintf(gmon_out,"gmon.%d.out",(int)GetCurrentThreadId()); proffile = gmon_out; + } #endif Index: winsup/cygwin/init.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/init.cc,v retrieving revision 1.80 diff -u -r1.80 init.cc --- winsup/cygwin/init.cc 12 Dec 2010 05:48:29 -0000 1.80 +++ winsup/cygwin/init.cc 6 Mar 2011 12:55:25 -0000 @@ -116,7 +116,9 @@ dll_entry (HANDLE h, DWORD reason, void *static_load) { BOOL wow64_test_stack_marker; - + extern void __attribute__ ((no_instrument_function)) + __cyg_profile_func_ctor(); + __cyg_profile_func_ctor(); switch (reason) { case DLL_PROCESS_ATTACH: @@ -147,6 +149,9 @@ case DLL_THREAD_ATTACH: if (dll_finished_loading) munge_threadfunc (); + void __attribute__ ((no_instrument_function)) + __cyg_profile_tls_ctor(); + __cyg_profile_tls_ctor(); break; case DLL_THREAD_DETACH: if (dll_finished_loading && (void *) &_my_tls > (void *) &wow64_test_stack_marker Index: winsup/cygwin/profil.c =================================================================== RCS file: /cvs/src/src/winsup/cygwin/profil.c,v retrieving revision 1.8 diff -u -r1.8 profil.c --- winsup/cygwin/profil.c 30 Aug 2010 01:57:36 -0000 1.8 +++ winsup/cygwin/profil.c 6 Mar 2011 12:55:26 -0000 @@ -17,7 +17,7 @@ #define SLEEPTIME (1000 / PROF_HZ) /* global profinfo for profil() call */ -static struct profinfo prof; +struct profinfo prof; /* Get the pc for thread THR */ @@ -65,6 +65,7 @@ for (;;) { pc = (u_long) get_thrpc (p->targthr); + if (pc==(u_long)-1) break; if (pc >= p->lowpc && pc < p->highpc) { idx = PROFIDX (pc, p->lowpc, p->scale); @@ -108,8 +109,8 @@ errno = ESRCH; return -1; } - - p->profthr = CreateThread (0, 0, profthr_func, (void *) p, 0, &thrid); + boundbuffer_ctor(&prof.queue); + p->profthr = CreateThread (0, 0, worker_consumer, (void *) p, 0, &thrid); if (!p->profthr) { CloseHandle (p->targthr); Index: winsup/cygwin/profil.h =================================================================== RCS file: /cvs/src/src/winsup/cygwin/profil.h,v retrieving revision 1.4 diff -u -r1.4 profil.h --- winsup/cygwin/profil.h 28 Apr 2003 20:10:53 -0000 1.4 +++ winsup/cygwin/profil.h 6 Mar 2011 12:55:26 -0000 @@ -10,7 +10,7 @@ /* profiling frequency. (No larger than 1000) */ #define PROF_HZ 100 - +#include "boundbuffer.h" /* convert an addr to an index */ #define PROFIDX(pc, base, scale) \ ({ \ @@ -37,8 +37,16 @@ u_short *counter; /* profiling counters */ u_long lowpc, highpc; /* range to be profiled */ u_int scale; /* scale value of bins */ + struct boundbuffer queue; }; - +extern struct profinfo prof; int profile_ctl(struct profinfo *, char *, size_t, u_long, u_int); int profil(char *, size_t, u_long, u_int); +struct clk +{ + int use; + unsigned idx; + void* pc[0x10000]; + unsigned long long tsc[0x10000]; +}; --- /dev/null 2011-03-06 21:54:49.000000000 +0900 +++ winsup/cygwin/boundbuffer.c 2011-03-06 20:32:31.015625000 +0900 @@ -0,0 +1,60 @@ +#include "winlean.h" +#include "profil.h" +void spawn_consumer_thread(){ +if (!prof.queue.spawned) + { + DWORD id; + CreateThread(0,0,worker_consumer,0,0,&id); + } +} +DWORD __stdcall worker_consumer(void* arg) +{ + struct profinfo *p = &prof; + message msg; + p->queue.spawned=1; + while(1) + { + boundbuffer_dequeue(&p->queue,&msg); + unsigned idx = PROFIDX ((unsigned)msg.pv, p->lowpc, p->scale); + p->counter[idx]+=msg.ival/100000; + } + return 0; +} +#define buffermethod(x) boundbuffer_##x +void buffermethod(ctor)(struct boundbuffer* this){ + this->spawned=0; + this->member[FRONT].i=this->member[BACK].i=0; +this->member[MUTEX].h=CreateSemaphoreA(0, 1, 1, 0); +this->member[EMPTY].h=CreateSemaphoreA(0, SZBUF, SZBUF, 0); +this->member[FILL].h=CreateSemaphoreA(0, 0, SZBUF, 0); +} +void buffermethod(dtor)(struct boundbuffer* this){ +CloseHandle(this->member[MUTEX].h); +CloseHandle(this->member[EMPTY].h); +CloseHandle(this->member[FILL].h); +} +static void buffermethod(check)(struct boundbuffer* this){ + if (!((this->member[FRONT].i>-1) &&(this->member[FRONT].imember[BACK].i>-1) &&(this->member[BACK].imember[EMPTY].h, INFINITE); + WaitForSingleObject(this->member[MUTEX].h, INFINITE); + boundbuffer_check(this); + this->buffer[this->member[BACK].i] = obj; + this->member[BACK].i = (this->member[BACK].i + 1) % SZBUF; + ReleaseSemaphore(this->member[MUTEX].h, 1, 0); + ReleaseSemaphore(this->member[FILL].h, 1, 0); +} +void buffermethod(dequeue)(struct boundbuffer* this,message* result){ + WaitForSingleObject(this->member[FILL].h, INFINITE); + WaitForSingleObject(this->member[MUTEX].h, INFINITE); + boundbuffer_check(this); + (*result)=this->buffer[this->member[FRONT].i]; + this->member[FRONT].i = (this->member[FRONT].i + 1) % SZBUF; + ReleaseSemaphore(this->member[MUTEX].h, 1, 0); + ReleaseSemaphore(this->member[EMPTY].h, 1, 0); +} +#undef buffermethod --- /dev/null 2011-03-06 21:54:49.000000000 +0900 +++ winsup/cygwin/boundbuffer.h 2011-03-06 20:17:20.796875000 +0900 @@ -0,0 +1,47 @@ +#ifndef BOUNDBUFFER_H_ +#define BOUNDBUFFER_H_ +#include +#define assertion(x) if (!(x)) \ + { \ + asm volatile ("int $3");\ + } \ + else {}; + +struct message + { +#if 0 + unsigned long long ldata; + unsigned long idata[2]; +#endif + void* pv; + unsigned ival; + }; +typedef struct message message; +extern DWORD __stdcall worker_consumer(void* arg); +union avoidtypecheck +{ + HANDLE h; + int i; +}; +enum bconst{ + MUTEX,FILL,EMPTY,FRONT,BACK,SZMEMBER,SZBUF=50 + }; +struct boundbuffer +{ + union avoidtypecheck member[SZMEMBER]; + message buffer[SZBUF]; + int spawned; + /* + void (*ctor)(struct boundbuffer*); + void (*dtor)(struct boundbuffer*); + void (*enqueue)(struct boundbuffer*,union message*); + union message* (*dequeue)(struct boundbuffer*); + */ +}; +#define buffermethod(x) boundbuffer_##x +extern void buffermethod(ctor)(struct boundbuffer*); +extern void buffermethod(dtor)(struct boundbuffer*); +extern void buffermethod(enqueue)(struct boundbuffer*,message); +extern void buffermethod(dequeue)(struct boundbuffer*,message*); +#undef buffermethod +#endif /* BOUNDBUFFER_H_ */ --- /dev/null 2011-03-06 21:54:49.000000000 +0900 +++ winsup/cygwin/gcrt1.c 2011-03-01 23:38:39.437500000 +0900 @@ -0,0 +1,39 @@ +/* gcrt0.c + + Copyright 1998, 1999, 2000, 2001 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 +#include +#include +extern u_char etext asm ("etext"); +extern u_char eprol asm ("__eprol"); +extern void _mcleanup (void); +extern void monstartup (u_long, u_long); + +extern void _monstartup2 (void); + +/* startup initialization for -pg support */ + +void +_monstartup2 (void) +{ + static int called; + + /* Guard against multiple calls that may happen if DLLs are linked + with profile option set as well. Addede side benefit is that it + makes profiling backward compatible (GCC used to emit a call to + _monstartup when compiling main with profiling enabled). */ + if (called++) + return; + monstartup ((u_long) &eprol, (u_long) &etext); +} + +asm (".text"); +asm ("__eprol:"); + --- /dev/null 2011-03-06 21:54:50.000000000 +0900 +++ winsup/cygwin/instrument.c 2011-03-06 19:33:30.312500000 +0900 @@ -0,0 +1,80 @@ +/* + * instrument.c + * + * Created on: 2011. 3. 2. + * Author: Administrator + */ +#include +#include "winlean.h" +#include "profil.h" +#include "boundbuffer.h" +extern struct profinfo prof; +DWORD tlskey; +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_ctor() +{ + tlskey = TlsAlloc(); +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_tls_ctor() +{ + void * map = (void*) LocalAlloc(0x40, sizeof(struct clk)); + TlsSetValue(tlskey, map); + struct clk* clkinfo = (struct clk*) map; + clkinfo->idx = 0; + clkinfo->use = 1; +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_dtor() +{ + struct clk* clkinfo = (struct clk*) TlsGetValue(tlskey); + clkinfo->use = 0; +} +extern int s_scale; +void __attribute__ ((no_instrument_function)) +__cyg_set_clk(struct clk* clkinfo,void *caller, int state) +{ + int idx; + message msg; + switch (state) + { + case 0: + if (!clkinfo->idx) goto skip; + idx = --clkinfo->idx; + dassert((idx>=0)&&clkinfo->pc[idx] == caller) + clkinfo->tsc[idx] -= __builtin_ia32_rdtsc(); + msg.pv = clkinfo->pc[idx]; + msg.ival = (unsigned)clkinfo->tsc[idx] & 0x00000000ffffffffULL; + if (prof.queue.spawned) + boundbuffer_enqueue(&prof.queue, msg); + break; + case 1: + clkinfo->pc[clkinfo->idx] = caller; + clkinfo->tsc[clkinfo->idx] = __builtin_ia32_rdtsc(); + clkinfo->idx++; + break; + default: + goto skip; + break; + }; + skip: do + { + } + while (0); +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_enter(void* caller, void* site) +{ + struct clk* clkinfo = (struct clk*) TlsGetValue(tlskey); + if (!clkinfo) return; + if (clkinfo->use) + __cyg_set_clk(clkinfo,caller, 1); +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_exit(void* caller, void* site) +{ + struct clk* clkinfo = (struct clk*) TlsGetValue(tlskey); + if (!clkinfo) return; + if (clkinfo->use) + __cyg_set_clk(clkinfo,caller, 0); +}