On 2011-07-31 PM 5:26, Corinna Vinschen wrote:
Erm, I tested on 32 bit.  The slowdown occured on all platforms, not
only 64 bit.  64 bit is still only half as fast in the date loop for
reason or reasons unknown.


Corinna

I used this code to profile every source compiled with -pg -finstrument-functions. It had no documentation. because it existed solely for the purpose to breakdown the cause of slow start. Existing profiling code has ability to profile single-thread.so it had rare useful when the target is cygwin.(it spawns thread.) so i tried gaving them to consider threaded environment. And modified profiling code uses instrument function to profile every function enter/exit. eventually, it resulted in terrible performance (2.42x slowdown at least) when the profiling worker is forced to terminated( ExitProcess,abort,exit.. ) it notifies worker thread and joins the thread.
Also, i modified initial startup a little bit.

and here is instruction.
# apply patch
for i in thread_profile_stuff.diff thread_profile_core.diff; do patch -p0 <$i;done;
# pass configure parameter to build cygwin if you didn't configured it.
# make sure that cygwin is configured and can be built. from now i copy-paste some bunch of code. # in i686-pc-cygwin/winsup/cygwin/Makefile, you should add CFLAGS '-pg -finstrument-functions' , to make new profiling code effective. and comment out ifneq "${filter -O%,$(CFLAGS)}" "" too. it would make profiling code functional ( in cases you need to profile cygheap thread etc...)
#and use following snippet code to build new cygwin1.dll
s='';for i in boundbuffer pthread instrument kernel32 malloc_wrapper pseudo-reloc libstdcxx_wrapper cxx gcrt1 gmon profil mcount; do rm $i.o; s="${s} ${i}.o";done; make CFLAGS='-march=-O2 -g -mfpmath=sse -Wno-error=unused-but-set-variable' $s -j 4;make;
#there would be no -pg -finstrument-functions in CFLAGS.
#what this does is, keep some source code from to be profiled.
and done. you got new-cygwin1.dll. rename it and try to discover what is the problem. because it gave gmon out like gmon.%pid.%tid.out when exited. you would use gprof to see report.
Regards.
? .cproject
? .project
? bc
? bfd
? bootstrap
? build
? conf1732
? conf1732.file
? config.cache
? config.log
? ctype_.i
? erfetch
? fastfetch
? i686-pc-cygwin
? outdiff
? outdiff-onlyprofile
? outdiff-patch
? outdiff-profile
? perl.exe.stackdump
? profile-self
? serdep.tmp
? test
? wincap.h.diff.txt
? winsup.diff
? etc/Makefile
? etc/conf1684subs.awk
? etc/conf1684subs.sh
? etc/config.cache
? etc/config.log
? etc/config.status
? etc/configure.info
? etc/standards.info
? winsup/cygwin/boundbuffer.c
? winsup/cygwin/boundbuffer.h
? winsup/cygwin/config.log
? winsup/cygwin/cppcheck.exe.stackdump
? winsup/cygwin/gcrt1.c
? winsup/cygwin/instrument.c
? winsup/cygwin/instrument.h
? winsup/cygwin/sigfe_base.cc
Index: winsup/cygwin/dcrt0.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v
retrieving revision 1.404
diff -u -r1.404 dcrt0.cc
--- winsup/cygwin/dcrt0.cc      4 Jul 2011 15:25:36 -0000       1.404
+++ winsup/cygwin/dcrt0.cc      28 Jul 2011 01:49:58 -0000
@@ -37,7 +37,7 @@
 #include "cygxdr.h"
 #include "fenv.h"
 #include "ntdll.h"
-
+#include "profil.h"
 #define MAX_AT_FILE_LEVEL 10
 
 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof 
(user_data->premain[0]))
@@ -648,14 +648,17 @@
   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 ()
 {
   init_windows_system_directory ();
   init_global_security ();
+  _monstartup2();
   initial_env ();
-
   SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
 
   lock_process::init ();
@@ -677,7 +680,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);
@@ -695,6 +697,7 @@
            break;
        }
     }
+  atexit (&_mcleanup);
 
   user_data->threadinterface->Init ();
 
@@ -723,7 +726,7 @@
 dll_crt0_1 (void *)
 {
   extern void initial_setlocale ();
-
+  sanity_check_profile_thread();
   if (wincap.has_buggy_thread_startup () || dynamically_loaded)
     sigproc_init ();
   check_sanity_and_sync (user_data);
Index: winsup/cygwin/exceptions.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/exceptions.cc,v
retrieving revision 1.359
diff -u -r1.359 exceptions.cc
--- winsup/cygwin/exceptions.cc 13 Jul 2011 17:53:21 -0000      1.359
+++ winsup/cygwin/exceptions.cc 28 Jul 2011 01:49:59 -0000
@@ -375,7 +375,7 @@
       return 0;
     }
 
-  __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId 
());
+  __small_sprintf (debugger_command, "gdb --pid=%u", GetCurrentProcessId ());
 
   LONG prio = GetThreadPriority (GetCurrentThread ());
   SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST);
@@ -924,7 +924,7 @@
     return true;
   return false;
 }
-
+extern "C" void profile_thread_off();
 /* Keyboard interrupt handler.  */
 static BOOL WINAPI
 ctrl_c_handler (DWORD type)
@@ -937,6 +937,7 @@
       if (myself->cygstarted)  /* Was this process created by a cygwin 
process? */
        return TRUE;            /* Yes.  Let the parent eventually handle 
CTRL-C issues. */
       debug_printf ("exiting with status %p", STATUS_CONTROL_C_EXIT);
+      profile_thread_off();
       ExitProcess (STATUS_CONTROL_C_EXIT);
     }
 
Index: winsup/cygwin/external.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/external.cc,v
retrieving revision 1.123
diff -u -r1.123 external.cc
--- winsup/cygwin/external.cc   1 Jun 2011 01:20:27 -0000       1.123
+++ winsup/cygwin/external.cc   28 Jul 2011 01:49:59 -0000
@@ -161,7 +161,7 @@
     }
   free (envblock);
 }
-
+extern "C" void profile_thread_off();
 /*
  * Cygwin-specific wrapper for win32 ExitProcess and TerminateProcess.
  * It ensures that the correct exit code, derived from the specified
@@ -180,6 +180,7 @@
 static void
 exit_process (UINT status, bool useTerminateProcess)
 {
+  profile_thread_off();
   pid_t pid = getpid ();
   external_pinfo * ep = fillout_pinfo (pid, 1);
   DWORD dwpid = ep ? ep->dwProcessId : pid;
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        28 Jul 2011 01:49:59 -0000
@@ -34,11 +34,12 @@
 #if !defined(lint) && defined(LIBC_SCCS)
 static char rcsid[] = "$OpenBSD: gmon.c,v 1.8 1997/07/23 21:11:27 kstailey Exp 
$";
 #endif
-
+#include "winsup.h"
 #include "winlean.h"
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <string.h>
 #include <gmon.h>
 #include <stdlib.h>
 
@@ -47,9 +48,9 @@
 /* XXX needed? */
 //extern char *minbrk __asm ("minbrk");
 
-struct gmonparam _gmonparam = { GMON_PROF_OFF };
+struct gmonparam NO_COPY_INIT _gmonparam = { GMON_PROF_OFF };
 
-static int     s_scale;
+int    NO_COPY_INIT s_scale;
 /* see profil(2) where this is describe (incorrectly) */
 #define                SCALE_1_TO_1    0x10000L
 
@@ -60,7 +61,7 @@
 static void *
 fake_sbrk(int size)
 {
-    void *rv = malloc(size);
+    void *rv = LocalAlloc(0x40,size);
     if (rv)
       return rv;
     else
@@ -93,7 +94,7 @@
                p->tolimit = MAXARCS;
        p->tossize = p->tolimit * sizeof(struct tostruct);
 
-       cp = fake_sbrk(p->kcountsize + p->fromssize + p->tossize);
+       cp = fake_sbrk(5*p->kcountsize + p->fromssize + p->tossize);
        if (cp == (char *)-1) {
                ERR("monstartup: out of memory\n");
                return;
@@ -105,6 +106,8 @@
        cp += p->tossize;
        p->kcount = (u_short *)cp;
        cp += p->kcountsize;
+       p->comm_kcount=(u_int64_t*)cp;
+       cp += 4*p->kcountsize;
        p->froms = (u_short *)cp;
 
        /* XXX minbrk needed? */
@@ -136,6 +139,7 @@
 void
 _mcleanup()
 {
+        unsigned i;
        int fd;
        int hz;
        int fromindex;
@@ -204,8 +208,12 @@
        }
 #else
        {
-         char gmon_out[] = "gmon.out";
-         proffile = gmon_out;
+         char gmon_out[1024];
+               char proc_modulename[1024];
+               GetModuleFileNameA(0, proc_modulename, 1024);
+               sprintf(gmon_out, "gmon.%s.%d.out", 
strrchr(proc_modulename,'\\')+1,
+                               (int) GetCurrentProcessId());
+               proffile = gmon_out;
        }
 #endif
 
@@ -230,6 +238,14 @@
        hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
        hdr->version = GMONVERSION;
        hdr->profrate = hz;
+       for (i=0;i<p->kcountsize/2;i++)
+         {
+           if (p->comm_kcount[i]<prof.perffreq) continue;
+           else
+             {
+               p->kcount[i]=p->comm_kcount[i]/prof.perffreq;
+             }
+         }
        write(fd, (char *)hdr, sizeof *hdr);
        write(fd, p->kcount, p->kcountsize);
        endfrom = p->fromssize / sizeof(*p->froms);
Index: winsup/cygwin/gmon.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/gmon.h,v
retrieving revision 1.2
diff -u -r1.2 gmon.h
--- winsup/cygwin/gmon.h        24 Jun 2001 22:26:51 -0000      1.2
+++ winsup/cygwin/gmon.h        28 Jul 2011 01:49:59 -0000
@@ -134,6 +134,7 @@
 struct gmonparam {
        int             state;
        u_short         *kcount;
+       u_int64_t       *comm_kcount;
        u_long          kcountsize;
        u_short         *froms;
        u_long          fromssize;
Index: winsup/cygwin/init.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/init.cc,v
retrieving revision 1.83
diff -u -r1.83 init.cc
--- winsup/cygwin/init.cc       25 May 2011 11:33:29 -0000      1.83
+++ winsup/cygwin/init.cc       28 Jul 2011 01:49:59 -0000
@@ -13,6 +13,8 @@
 #include "cygtls.h"
 #include "ntdll.h"
 #include "shared_info.h"
+#include "profil.h"
+#include "instrument.h"
 
 static DWORD _my_oldfunc;
 
@@ -29,7 +31,8 @@
   asm volatile ("andl $-16,%%esp" ::: "%esp");
   _cygtls::call ((DWORD (*)  (void *, void *)) TlsGetValue (_my_oldfunc), arg);
 }
-
+extern "C" DWORD __stdcall
+      worker_consumer(void* arg);
 /* If possible, redirect the thread entry point to a cygwin routine which
    adds tls stuff to the stack. */
 static void
@@ -63,7 +66,7 @@
        }
     }
 }
-
+extern "C" void profile_thread_off();
 inline static void
 respawn_wow64_process ()
 {
@@ -106,6 +109,7 @@
        api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
       GetExitCodeProcess (pi.hProcess, &ret);
       CloseHandle (pi.hProcess);
+      profile_thread_off();
       ExitProcess (ret);
     }
 }
@@ -116,10 +120,11 @@
 dll_entry (HANDLE h, DWORD reason, void *static_load)
 {
   BOOL wow64_test_stack_marker;
-
   switch (reason)
     {
     case DLL_PROCESS_ATTACH:
+      __cyg_profile_func_ctor();
+      __cyg_profile_tls_ctor();
       wincap.init ();
       init_console_handler (false);
 
@@ -143,8 +148,11 @@
     case DLL_PROCESS_DETACH:
       if (dynamically_loaded)
        shared_destroy ();
+      __cyg_profile_tls_dtor();
+      __cyg_profile_func_dtor();
       break;
     case DLL_THREAD_ATTACH:
+      __cyg_profile_tls_ctor();
       if (dll_finished_loading)
        munge_threadfunc ();
       break;
@@ -153,6 +161,8 @@
          && (PVOID) &_my_tls > (PVOID) &wow64_test_stack_marker
          && _my_tls.isinitialized ())
        _my_tls.remove (0);
+    __cyg_profile_tls_dtor();
+
       /* Windows 2000 has a bug in NtTerminateThread.  Instead of releasing
         the stack at teb->DeallocationStack it uses the value of
         teb->Tib.StackLimit to evaluate the stack address.  So we just claim
Index: winsup/cygwin/pinfo.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/pinfo.cc,v
retrieving revision 1.277
diff -u -r1.277 pinfo.cc
--- winsup/cygwin/pinfo.cc      16 Jun 2011 23:00:00 -0000      1.277
+++ winsup/cygwin/pinfo.cc      28 Jul 2011 01:50:00 -0000
@@ -29,7 +29,7 @@
 #include "cygtls.h"
 #include "tls_pbuf.h"
 #include "child_info.h"
-
+#include "profil.h"
 class pinfo_basic: public _pinfo
 {
 public:
@@ -170,7 +170,7 @@
   sigproc_printf ("pid %d, exit value - old %p, windows %p, cygwin %p",
                  self->pid, oexitcode, x, self->exitcode);
 }
-
+extern "C" void profile_thread_off();
 void
 pinfo::exit (DWORD n)
 {
@@ -204,6 +204,7 @@
   if (!self->cygstarted)
     exitcode = ((exitcode & 0xff) << 8) | ((exitcode >> 8) & 0xff);
   sigproc_printf ("Calling ExitProcess n %p, exitcode %p", n, exitcode);
+  profile_thread_off();
   ExitProcess (exitcode);
 }
 # undef self
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      28 Jul 2011 01:50:00 -0000
@@ -7,17 +7,16 @@
    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 <sys/types.h>
 #include <errno.h>
-
+#include "gmon.h"
 #include <profil.h>
-
 #define SLEEPTIME (1000 / PROF_HZ)
-
+extern SECURITY_ATTRIBUTES sec_none_nih;
 /* global profinfo for profil() call */
-static struct profinfo prof;
+struct profinfo NO_COPY prof;
 
 /* Get the pc for thread THR */
 
@@ -80,16 +79,35 @@
 
 /* Stop profiling to the profiling buffer pointed to by P. */
 
-static int
+int
 profile_off (struct profinfo *p)
 {
   if (p->profthr)
     {
-      TerminateThread (p->profthr, 0);
+      if (prof.queue.worker_enabled)
+        {
+         extern void profile_thread_off();profile_thread_off();
+         boundbuffer_dtor(&p->queue);
+          while(boundbuffer_empty(&p->queue))
+             {
+                message msg;
+                boundbuffer_dequeue_nolock(&p->queue, &msg);
+                unsigned idx = PROFIDX ((unsigned)msg.pv, p->lowpc, p->scale);
+                if (!msg.ullval) continue;
+                _gmonparam.comm_kcount[idx] += msg.ullval;
+
+             }
+        }
       CloseHandle (p->profthr);
+      CloseHandle(prof.operational);
+      p->profthr=0;
+
     }
+ // else assertion(!prof.queue.worker_enabled)
+#if 0
   if (p->targthr)
     CloseHandle (p->targthr);
+#endif
   return 0;
 }
 
@@ -98,8 +116,7 @@
 static int
 profile_on (struct profinfo *p)
 {
-  DWORD thrid;
-
+#if 0
   /* get handle for this thread */
   if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
                        GetCurrentProcess (), &p->targthr, 0, FALSE,
@@ -108,12 +125,21 @@
       errno = ESRCH;
       return -1;
     }
-
-  p->profthr = CreateThread (0, 0, profthr_func, (void *) p, 0, &thrid);
+#endif
+  QueryPerformanceFrequency((PLARGE_INTEGER)&prof.perffreq);
+  prof.perffreq/=PROF_HZ;
+  boundbuffer_initial(&prof.queue);
+  //boundbuffer_ctor(&prof.queue);
+  prof.operational=CreateSemaphoreA(&sec_none_nih,0,1,0);
+  extern void wf(int);
+  //wf(80);
+  p->profthr = CreateThread (&sec_none_nih, 0, worker_consumer, (void *) p, 0, 
0);
   if (!p->profthr)
     {
+#if 0
       CloseHandle (p->targthr);
       p->targthr = 0;
+#endif
       errno = EAGAIN;
       return -1;
     }
@@ -170,4 +196,9 @@
 {
   return profile_ctl (&prof, samples, size, offset, scale);
 }
+void profile_thread_off() {
+       int enabled = __sync_fetch_and_and(&prof.queue.worker_enabled, 0);
+       if (enabled)
+               WaitForSingleObject(prof.profthr, INFINITE);
+}
 
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      28 Jul 2011 01:50:00 -0000
@@ -7,10 +7,14 @@
 This software is a copyrighted work licensed under the terms of the
 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
 details. */
-
+#ifndef PROFIL_H
+#define PROFIL_H
+#ifdef __cplusplus
+extern "C"{
+#endif
 /* profiling frequency.  (No larger than 1000) */
-#define PROF_HZ                        100
-
+#define PROF_HZ                        1000UL
+#include "boundbuffer.h"
 /* convert an addr to an index */
 #define PROFIDX(pc, base, scale)       \
   ({                                                                   \
@@ -37,8 +41,22 @@
     u_short *counter;                  /* profiling counters */
     u_long lowpc, highpc;              /* range to be profiled */
     u_int scale;                       /* scale value of bins */
+    u_int64_t perffreq;
+    struct boundbuffer queue;
+    _WINHANDLE operational;
 };
-
+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
+{
+  unsigned idx;
+  void* pc[0x10000];
+  unsigned long long tsc[0x10000];
+};
+extern void profile_thread_off();
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: winsup/cygwin/sigproc.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sigproc.cc,v
retrieving revision 1.339
diff -u -r1.339 sigproc.cc
--- winsup/cygwin/sigproc.cc    6 Jul 2011 12:39:36 -0000       1.339
+++ winsup/cygwin/sigproc.cc    28 Jul 2011 01:50:00 -0000
@@ -929,7 +929,7 @@
     ForceCloseHandle1 (h, childhProc);
   return exit_code;
 }
-
+extern "C" void profile_thread_off();
 bool
 child_info_fork::abort (const char *fmt, ...)
 {
@@ -938,10 +938,14 @@
       va_list ap;
       va_start (ap, fmt);
       strace_vprintf (SIGP, fmt, ap);
+      profile_thread_off();
       ExitProcess (EXITCODE_FORK_FAILED);
     }
   if (retry > 0)
+  {
+       profile_thread_off();
     ExitProcess (EXITCODE_RETRY);
+  }
   return false;
 }
 
Index: winsup/cygwin/strace.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/strace.cc,v
retrieving revision 1.72
diff -u -r1.72 strace.cc
--- winsup/cygwin/strace.cc     4 Jul 2011 15:25:36 -0000       1.72
+++ winsup/cygwin/strace.cc     28 Jul 2011 01:50:00 -0000
@@ -30,6 +30,10 @@
 class strace NO_COPY strace;
 
 #ifndef NOSTRACE
+extern "C" __attribute__((always_inline)) int strace_active()
+{
+  return strace.active();
+}
 
 void
 strace::activate ()
Index: winsup/cygwin/config/i386/profile.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/config/i386/profile.h,v
retrieving revision 1.3
diff -u -r1.3 profile.h
--- winsup/cygwin/config/i386/profile.h 14 Feb 2011 09:42:19 -0000      1.3
+++ winsup/cygwin/config/i386/profile.h 28 Jul 2011 01:50:00 -0000
@@ -57,9 +57,7 @@
         * Save registers, since this may be called from                \
         * the prologue of a regparm function.                          \
         */                                                             \
-       __asm __volatile__ ("pushl %eax\n\t"                            \
-                           "pushl %ecx\n\t"                            \
-                           "pushl %edx");                              \
+       __asm __volatile__ ("pushal");                          \
        /*                                                              \
         * find the return address for mcount,                          \
         * and the return address for mcount's caller.                  \
@@ -77,7 +75,5 @@
        /*                                                              \
         * Restore registers.                                           \
         */                                                             \
-       __asm __volatile__ ("popl %edx\n\t"                             \
-                           "popl %ecx\n\t"                             \
-                           "popl %eax");                               \
+       __asm __volatile__ ("popal");                           \
 }
Index: winsup/cygwin/include/sys/strace.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/sys/strace.h,v
retrieving revision 1.27
diff -u -r1.27 strace.h
--- winsup/cygwin/include/sys/strace.h  17 Jun 2011 08:30:27 -0000      1.27
+++ winsup/cygwin/include/sys/strace.h  28 Jul 2011 01:50:00 -0000
@@ -51,8 +51,8 @@
   void vprntf (unsigned, const char *func, const char *, va_list ap) 
/*__attribute__ ((regparm(3)))*/;
   void wm (int message, int word, int lon) __attribute__ ((regparm(3)));
   void write_childpid (child_info&, unsigned long) __attribute__ ((regparm 
(2)));
-  bool attached () const {return _active == 3;}
-  bool active () const {return _active & 1;}
+  const bool inline attached () const {return _active == 3;}
+  const bool inline active () const {return _active & 1;}
   unsigned char& active_val () {return _active;}
 };
 
@@ -94,12 +94,12 @@
 
 void small_printf (const char *, ...);
 void strace_printf (unsigned, const char *func, const char *, ...);
-
+int strace_active();
 #ifdef __cplusplus
 }
 #endif
 
-#ifdef __cplusplus
+#if 1
 
 #ifdef NOSTRACE
 #define strace_printf_wrap(what, fmt, args...)
@@ -107,14 +107,14 @@
 #else
 #define strace_printf_wrap(what, fmt, args...) \
    ((void) ({\
-       if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active ()) \
-         strace.prntf(_STRACE_ ## what, __PRETTY_FUNCTION__, fmt, ## args); \
+       if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace_active ()) \
+         strace_printf(_STRACE_ ## what, __PRETTY_FUNCTION__, fmt, ## args); \
        0; \
     }))
 #define strace_printf_wrap1(what, fmt, args...) \
     ((void) ({\
-       if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace.active ()) \
-         strace.prntf((_STRACE_ ## what) | _STRACE_NOTALL, 
__PRETTY_FUNCTION__, fmt, ## args); \
+       if ((_STRACE_ ## what & _STRACE_SYSTEM) || strace_active ()) \
+         strace_printf((_STRACE_ ## what) | _STRACE_NOTALL, 
__PRETTY_FUNCTION__, fmt, ## args); \
        0; \
     }))
 #define strace_vprintf(what, fmt, arg) \
--- /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 <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#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 <stdio.h>
+#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 <sys/types.h>
+#include <stdlib.h>
+#include <stdbool.h>
+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 <stdint.h>
+#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_ */

Reply via email to