--- /dev/null 2011-07-31 17:41:38.000000000 +0900 +++ winsup/cygwin/boundbuffer.c 2011-07-13 02:28:19.140625000 +0900 @@ -0,0 +1,143 @@ +#include "winsup.h" +#include "winlean.h" +#include "profil.h" +#include "gmon.h" +#include +#include +#include +#include "boundbuffer.h" +extern bool NO_COPY in_forkee; +extern SECURITY_ATTRIBUTES sec_none_nih; +void sanity_check_profile_thread() { + /* + if(!__sync_fetch_and_add(&prof.queue.worker_enabled,0)) + { + void moncontrol(int); + moncontrol(0); + moncontrol(1); + WaitForSingleObject(prof.operational,INFINITE); + } + */ +} +static const char hex_str[] = "0123456789ABCDEF"; +void wf(int var) { + int a; + while (var != 0) { + WriteFile(GetStdHandle(STD_ERROR_HANDLE), &hex_str[var & 0xf], 1, &a, + 0); + var = var >> 4; + } + char buf = '\n'; + WriteFile(GetStdHandle(STD_ERROR_HANDLE), &buf, 1, &a, 0); + FlushFileBuffers(GetStdHandle(STD_ERROR_HANDLE)); +} +DWORD __stdcall +worker_consumer(void* arg) { +//wf(16); +//wf(GetCurrentProcessId()); +//wf(GetCurrentThreadId()); + //WaitForSingleObject(prof.queue.member[MUTEX].h, INFINITE); + if (prof.queue.initial) { + boundbuffer_ctor(&prof.queue); + prof.queue.initial = 0; + } + EnterCriticalSection(&prof.queue.member[MUTEX].s); + prof.queue.worker_enabled = 1; + ReleaseSemaphore(prof.operational, 1, 0); + //ReleaseMutex(prof.queue.member[MUTEX].h); + LeaveCriticalSection(&prof.queue.member[MUTEX].s); + while (prof.queue.worker_enabled) { + message msg; + if (!boundbuffer_dequeue(&prof.queue, &msg)) + continue; + unsigned idx = PROFIDX ((unsigned)msg.pv, prof.lowpc, prof. + scale); + if (!msg.ullval) + continue; + _gmonparam.comm_kcount[idx] += msg.ullval; + } + return 0; +} +#define buffermethod(x) boundbuffer_##x +void buffermethod(ctor)(struct boundbuffer* this) { + this->member[FRONT].i = this->member[BACK].i = 0; + InitializeCriticalSectionAndSpinCount(&this->member[MUTEX].s, 0x40000000); + //this->member[MUTEX].h = CreateMutexA(&sec_none_nih, 0, 0); + this->member[EMPTY].h = CreateSemaphoreA(&sec_none_nih, SZBUF, SZBUF, 0); + this->member[FILL].h = CreateSemaphoreA(&sec_none_nih, 0, SZBUF, 0); +} +void buffermethod(initial)(struct boundbuffer* this) { + this->initial=1; + this->member[MUTEX].i = this->member[EMPTY].i = this->member[FILL].i = -3; +} +void buffermethod(dtor)(struct boundbuffer* this) { + CloseHandle(this->member[MUTEX].h); + CloseHandle(this->member[EMPTY].h); + CloseHandle(this->member[FILL].h); + this->member[MUTEX].i = this->member[EMPTY].i = this->member[FILL].i = -3; +} +static __attribute__((used)) void buffermethod(check)(struct boundbuffer* this) { + if (!((this->member[FRONT].i > -1) && (this->member[FRONT].i < SZBUF))) + asm volatile("int $3\t\n"); + if (!((this->member[BACK].i > -1) && (this->member[BACK].i < SZBUF))) + asm volatile("int $3\t\n"); +} +int buffermethod(enqueue)(struct boundbuffer* this, message obj) { + if (prof.queue.initial) { + buffermethod(enqueue_nolock)(this, obj); + return 1; + } + int ret = WaitForSingleObject(this->member[EMPTY].h, 100); + if (ret != WAIT_OBJECT_0 + ) + return 0; + /*ret = WaitForSingleObject(this->member[MUTEX].h, 100); + if (ret != WAIT_OBJECT_0 + ) + return 0; + */ + EnterCriticalSection(&prof.queue.member[MUTEX].s); + __attribute__((always_inline)) void buffermethod(enqueue_nolock)( + struct boundbuffer*, message); + buffermethod(enqueue_nolock)(this, obj); + //ReleaseMutex(this->member[MUTEX].h); + LeaveCriticalSection(&prof.queue.member[MUTEX].s); + ReleaseSemaphore(this->member[FILL].h, 1, 0); + return 1; +} + +int buffermethod(empty)(struct boundbuffer* this) { + //if(WaitForSingleObject(this->member[MUTEX].h, 0)!=WAIT_OBJECT_0) return -1; + int ret = this->member[FRONT].i == this->member[BACK].i; + //ReleaseSemaphore(this->member[MUTEX].h, 1, 0); + return ret; +} +int buffermethod(dequeue)(struct boundbuffer* this, message* result) { + if (prof.queue.initial) { + buffermethod(dequeue_nolock)(this, result); + return 1; + } + int ret = WaitForSingleObject(this->member[FILL].h, 100); + if (ret != WAIT_OBJECT_0 + ) + return 0; + //WaitForSingleObject(this->member[MUTEX].h, INFINITE); + EnterCriticalSection(&prof.queue.member[MUTEX].s); + buffermethod(dequeue_nolock)(this, result); + //ReleaseMutex(this->member[MUTEX].h); + LeaveCriticalSection(&prof.queue.member[MUTEX].s); + ReleaseSemaphore(this->member[EMPTY].h, 1, 0); + return 1; +} +__attribute__((always_inline)) void buffermethod(enqueue_nolock)( + struct boundbuffer* this, message obj) { + this->buffer[this->member[BACK].i] = obj; + this->member[BACK].i = (this->member[BACK].i + 1) % SZBUF; +} +__attribute__((always_inline)) void buffermethod(dequeue_nolock)( + struct boundbuffer* this, message* result) { + /*boundbuffer_check(this);*/ + (*result) = this->buffer[this->member[FRONT].i]; + this->member[FRONT].i = (this->member[FRONT].i + 1) % SZBUF; +} +#undef buffermethod --- /dev/null 2011-07-31 17:41:38.000000000 +0900 +++ winsup/cygwin/boundbuffer.h 2011-07-13 02:22:21.625000000 +0900 @@ -0,0 +1,64 @@ +#ifndef BOUNDBUFFER_H_ +#define BOUNDBUFFER_H_ +#include +#ifdef __cplusplus +extern "C"{ +#endif +#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 long long ullval; + }; +typedef struct message message; +extern +#if __cplusplus +"C" +#endif +void sanity_check_profile_thread(); +extern DWORD __stdcall worker_consumer(void* arg); +union avoidtypecheck +{ + HANDLE h; + CRITICAL_SECTION s; + int i; +}; +enum bconst{ + MUTEX,FILL,EMPTY,FRONT,BACK,SZMEMBER,SZBUF=16384 + }; +struct boundbuffer +{ + union avoidtypecheck member[SZMEMBER]; + message buffer[SZBUF]; + int worker_enabled; + int initial; + + /* + 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(initial)(struct boundbuffer*); +extern void buffermethod(dtor)(struct boundbuffer*); +extern int buffermethod(enqueue)(struct boundbuffer*,message); +extern int buffermethod(dequeue)(struct boundbuffer*,message*); +extern void buffermethod(dequeue_nolock)(struct boundbuffer*,message*); +extern int buffermethod(empty)(struct boundbuffer*); +#undef buffermethod +#ifdef __cplusplus +} +#endif +#endif /* BOUNDBUFFER_H_ */ --- /dev/null 2011-07-31 17:41:38.000000000 +0900 +++ winsup/cygwin/gcrt1.c 2011-07-12 08:01:49.281250000 +0900 @@ -0,0 +1,42 @@ +/* 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 "winsup.h" +#include "winlean.h" +#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 NO_COPY_INIT int called=0; + + /* 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; + extern void wf(int); + //wf(64); + monstartup ((u_long) &eprol, (u_long) &etext); +} + +asm (".text"); +asm ("__eprol:"); + --- /dev/null 2011-07-31 17:41:38.000000000 +0900 +++ winsup/cygwin/instrument.c 2011-07-19 22:29:53.156250000 +0900 @@ -0,0 +1,118 @@ +/* + * instrument.c + * + * Created on: 2011. 3. 2. + * Author: Administrator + */ +#include +#include "winsup.h" +#include "winlean.h" +#include "profil.h" +#include "boundbuffer.h" +#include "gmon.h" +DWORD NO_COPY tlskey; +extern DWORD WINAPI GetLastError (void); +void WINAPI SetLastError(DWORD); +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)); +#if 0 + assertion(map) +#endif + TlsSetValue(tlskey, map); + struct clk* clkinfo = (struct clk*) map; + clkinfo->idx = 0; +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_tls_dtor() +{ + void * map = TlsGetValue(tlskey); + if (map) + LocalFree(map); + TlsSetValue(tlskey, 0); + +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_dtor() +{ + TlsFree(tlskey); + tlskey=-1; +} +extern int s_scale; +static void __attribute__ ((always_inline,no_instrument_function)) +__cyg_set_clk(struct clk* clkinfo, void *caller, int state) +{ + register int idx; + message msg; + switch (state) + { + case 0: + if (!clkinfo->idx) + goto skip; + idx = --clkinfo->idx; +#if 0 + assertion((idx>=0)&&(idx<0xffff)) + assertion(clkinfo->pc[idx] == caller) +#endif + clkinfo->tsc[idx] = __builtin_ia32_rdtsc() - clkinfo->tsc[idx]; + msg.pv = clkinfo->pc[idx]; + msg.ullval = clkinfo->tsc[idx]; + if (&prof.queue.worker_enabled) + boundbuffer_enqueue(&prof.queue, msg); + break; + case 1: + idx = clkinfo->idx; +#if 0 + assertion((idx>=0)&&(idx<0xffff)) +#endif + clkinfo->pc[idx] = caller; + clkinfo->tsc[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) +{ + DWORD err=GetLastError(); + struct clk* clkinfo = (struct clk*) TlsGetValue(tlskey); + if (!clkinfo) + { +#if 0 + assertion(clkinfo); +#endif + goto trap; + } + __cyg_set_clk(clkinfo, caller, 1); + trap: + SetLastError(err); +} +void __attribute__ ((no_instrument_function)) +__cyg_profile_func_exit(void* caller, void* site) +{ + DWORD err=GetLastError(); + struct clk* clkinfo = (struct clk*) TlsGetValue(tlskey); + if (!clkinfo) + { +#if 0 + assertion(clkinfo); +#endif + goto trap; + } + __cyg_set_clk(clkinfo, caller, 0); + trap: + SetLastError(err); +} --- /dev/null 2011-07-31 17:41:38.000000000 +0900 +++ winsup/cygwin/instrument.h 2011-03-18 18:13:39.031250000 +0900 @@ -0,0 +1,24 @@ +/* + * instrument.h + * + * Created on: 2011. 3. 18. + * Author: Administrator + */ + +#ifndef INSTRUMENT_H_ +#define INSTRUMENT_H_ +#ifdef __cplusplus +extern "C"{ +#endif + void __attribute__ ((no_instrument_function)) + __cyg_profile_func_ctor(); + void __attribute__ ((no_instrument_function)) + __cyg_profile_func_dtor(); + void __attribute__ ((no_instrument_function)) + __cyg_profile_tls_ctor(); + void __attribute__ ((no_instrument_function)) + __cyg_profile_tls_dtor(); +#ifdef __cplusplus +} +#endif +#endif /* INSTRUMENT_H_ */