On 2011-08-30 AM 5:23, Christopher Faylor wrote:

  endif
...
...
+endif

+#if !defined(PROFILE)
      void *rv = malloc(size);
+#else
+    void *rv = LocalAlloc(LMEM_FIXED,size);
+#endif

Since the code is in gmon.c then I don't see a reason to #ifdef it but I
still don't understand the motivation for the change.  This is a major
amount of code and it is desperately missing comments.

Maybe Corinna will disagree but I think there is way too much code
change here for me to be comfortable with including it.  It looks like
it would be an ongoing maintenance issue, requiring constant vigilance
to avoid code rot.  And, it would have to be very carefully studied to
make sure there aren't more gotchas like 'if "" ""'.

Sorry, but I don't see us including this.

cgf

Yes, I see. but there would be months for the missing comments, and i have not enough time to test this patch for now.
and there were bugs in previous patch. so i attach the revised one.
Index: winsup/cygwin/Makefile.in
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/Makefile.in,v
retrieving revision 1.248
diff -u -p -r1.248 Makefile.in
--- winsup/cygwin/Makefile.in   2 May 2011 19:14:39 -0000       1.248
+++ winsup/cygwin/Makefile.in   29 Aug 2011 21:01:56 -0000
@@ -59,7 +59,11 @@ MT_SAFE:=@MT_SAFE@
 DEFS:=@DEFS@
 CCEXTRA:=
 CFLAGS?=@CFLAGS@
-override CFLAGS+=-MMD ${$(*F)_CFLAGS} -Werror -fmerge-constants -ftracer \
+ifeq '$(profile)' '1'
+CFLAGS_SAVE:=$(CFLAGS)
+CFLAGS=
+endif
+override CFLAGS+=-MMD ${$(*F)_CFLAGS} -fmerge-constants -ftracer \
   -mno-use-libstdc-wrappers $(CCEXTRA)
 CXX=@CXX@
 override CXXFLAGS=@CXXFLAGS@
@@ -234,6 +238,7 @@ INSTOBJS:=automode.o binmode.o textmode.
 TARGET_LIBS:=$(LIB_NAME) $(CYGWIN_START) $(GMON_START) $(LIBGMON_A) $(SUBLIBS) 
$(INSTOBJS) $(EXTRALIBS)
 
 ifneq "${filter -O%,$(CFLAGS)}" ""
+ifneq '$(profile)' '1'
 cygheap_CFLAGS:=-fomit-frame-pointer
 cygthread_CFLAGS:=-fomit-frame-pointer
 cygtls_CFLAGS:=-fomit-frame-pointer
@@ -286,6 +291,17 @@ syscalls_CFLAGS:=-fomit-frame-pointer
 sysconf_CFLAGS:=-fomit-frame-pointer
 uinfo_CFLAGS:=-fomit-frame-pointer
 endif
+endif
+EXTRA_DEPENDENCIES_1=gcrt1.o boundbuffer.o instrument.o gmon.o mcount.o 
profil.o
+EXTRA_LDFLAGS_1=../w32api/lib/libkernel32.a
+ifeq '$(profile)' '1'
+PROFILE_OPT_OUT=$(EXTRA_DEPENDENCIES_1:.o=) pthread kernel32 malloc_wrapper 
pseudo-reloc libstdcxx_wrapper cxx sync
+override CFLAGS+=-DPROFILE ${PROFILE_CFLAGS_${shell echo 
$(PROFILE_OPT_OUT)|grep -q "$(*F)";ret=$$?;echo $$ret;}}
+PROFILE_CFLAGS_1=$(subst -fomit-frame-pointer,,$(CFLAGS_SAVE)) -g -pg 
-finstrument-functions
+PROFILE_CFLAGS_0=$(subst -finstrument-functions,,$(subst -pg,,$(CFLAGS_SAVE))) 
-g -fomit-frame-pointer -Wno-error=unused-but-set-variable
+gcrt1.o: $(srcdir)/gcrt0.c
+       $(COMPILE_CC) -o $(@D)/$(*F)$o $<
+endif
 
 fhandler_proc_CFLAGS+=-DUSERNAME="\"$(USER)\"" -DHOSTNAME="\"$(HOSTNAME)\""
 fhandler_proc_CFLAGS+=-DGCC_VERSION="\"`$(CC) -v 2>&1 | tail -n 1`\""
@@ -393,12 +409,12 @@ maintainer-clean realclean: clean
 
 
 # Rule to build cygwin.dll
-$(TEST_DLL_NAME): $(LDSCRIPT) dllfixdbg $(DLL_OFILES) $(DLL_IMPORTS) 
$(LIBSERVER) $(LIBC) $(LIBM) $(API_VER) Makefile winver_stamp
+$(TEST_DLL_NAME): $(LDSCRIPT) dllfixdbg $(EXTRA_DEPENDENCIES_$(profile)) 
$(DLL_OFILES) $(DLL_IMPORTS) $(LIBSERVER) $(LIBC) $(LIBM) $(API_VER) Makefile 
winver_stamp
        $(CXX) $(CXXFLAGS) -Wl,--gc-sections $(nostdlib) -Wl,-T$(firstword $^) \
        -Wl,--heap=0 -Wl,--out-implib,cygdll.a -shared -o $@ \
-       -e $(DLL_ENTRY) $(DEF_FILE) $(DLL_OFILES) version.o winver.o \
+       -e $(DLL_ENTRY) $(DEF_FILE) $(EXTRA_DEPENDENCIES_$(profile)) 
$(DLL_OFILES) version.o winver.o \
        $(MALLOC_OBJ) $(LIBSERVER) $(LIBM) $(LIBC) \
-       -lgcc $(DLL_IMPORTS) -Wl,-Map,cygwin.map
+       -lgcc $(EXTRA_LDFLAGS_$(profile)) $(DLL_IMPORTS) -Wl,-Map,cygwin.map
        @$(word 2,$^) $(OBJDUMP) $(OBJCOPY) $@ ${patsubst %0.dll,%1.dbg,$@}
        @ln -f $@ new-$(DLL_NAME)
 
Index: winsup/cygwin/dcrt0.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/dcrt0.cc,v
retrieving revision 1.406
diff -u -p -r1.406 dcrt0.cc
--- winsup/cygwin/dcrt0.cc      18 Aug 2011 15:59:16 -0000      1.406
+++ winsup/cygwin/dcrt0.cc      29 Aug 2011 21:01:56 -0000
@@ -37,7 +37,9 @@ details. */
 #include "cygxdr.h"
 #include "fenv.h"
 #include "ntdll.h"
-
+#ifdef PROFILE
+#include "profil.h"
+#endif
 #define MAX_AT_FILE_LEVEL 10
 
 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof 
(user_data->premain[0]))
@@ -648,7 +650,11 @@ init_windows_system_directory ()
   windows_system_directory[windows_system_directory_length++] = L'\\';
   windows_system_directory[windows_system_directory_length] = L'\0';
 }
-
+#ifdef PROFILE
+extern "C" {
+  void _mcleanup (void);
+}
+#endif
 void
 dll_crt0_0 ()
 {
@@ -695,6 +701,10 @@ dll_crt0_0 ()
            break;
        }
     }
+#ifdef PROFILE
+  if (!in_forkee)
+       atexit(&_mcleanup);
+#endif
 
   user_data->threadinterface->Init ();
 
Index: winsup/cygwin/exceptions.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/exceptions.cc,v
retrieving revision 1.360
diff -u -p -r1.360 exceptions.cc
--- winsup/cygwin/exceptions.cc 3 Aug 2011 16:40:47 -0000       1.360
+++ winsup/cygwin/exceptions.cc 29 Aug 2011 21:01:56 -0000
@@ -31,7 +31,9 @@ details. */
 #include "child_info.h"
 #include "ntdll.h"
 #include "exception.h"
-
+#ifdef PROFILE
+#include "profil.h"
+#endif
 #define CALL_HANDLER_RETRY_OUTER 10
 #define CALL_HANDLER_RETRY_INNER 10
 
@@ -937,6 +939,9 @@ ctrl_c_handler (DWORD type)
       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);
+#ifdef PROFILE
+      profile_thread_off();
+#endif
       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 -p -r1.123 external.cc
--- winsup/cygwin/external.cc   1 Jun 2011 01:20:27 -0000       1.123
+++ winsup/cygwin/external.cc   29 Aug 2011 21:01:56 -0000
@@ -30,7 +30,9 @@ details. */
 #include <stdlib.h>
 #include <wchar.h>
 #include <iptypes.h>
-
+#ifdef PROFILE
+#include "profil.h"
+#endif
 child_info *get_cygwin_startup_info ();
 static void exit_process (UINT, bool) __attribute__((noreturn));
 
@@ -180,6 +182,9 @@ sync_winenv ()
 static void
 exit_process (UINT status, bool useTerminateProcess)
 {
+#ifdef PROFILE
+  profile_thread_off();
+#endif
   pid_t pid = getpid ();
   external_pinfo * ep = fillout_pinfo (pid, 1);
   DWORD dwpid = ep ? ep->dwProcessId : pid;
Index: winsup/cygwin/gcrt0.c
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/gcrt0.c,v
retrieving revision 1.5
diff -u -p -r1.5 gcrt0.c
--- winsup/cygwin/gcrt0.c       11 Sep 2001 20:01:00 -0000      1.5
+++ winsup/cygwin/gcrt0.c       29 Aug 2011 21:01:58 -0000
@@ -33,7 +33,9 @@ _monstartup (void)
     return;
 
   monstartup ((u_long) &eprol, (u_long) &etext);
+#ifndef PROFILE
   atexit (&_mcleanup);
+#endif
 }
 
 asm (".text");
Index: winsup/cygwin/gmon.c
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/gmon.c,v
retrieving revision 1.7
diff -u -p -r1.7 gmon.c
--- winsup/cygwin/gmon.c        30 Aug 2010 01:57:36 -0000      1.7
+++ winsup/cygwin/gmon.c        29 Aug 2011 21:01:58 -0000
@@ -34,11 +34,17 @@
 #if !defined(lint) && defined(LIBC_SCCS)
 static char rcsid[] = "$OpenBSD: gmon.c,v 1.8 1997/07/23 21:11:27 kstailey Exp 
$";
 #endif
-
+#ifdef PROFILE
+#include "winsup.h"
+#endif
 #include "winlean.h"
 #include <fcntl.h>
 #include <stdio.h>
 #include <unistd.h>
+#ifdef PROFILE
+#include <string.h>
+#include <math.h>
+#endif
 #include <gmon.h>
 #include <stdlib.h>
 
@@ -47,7 +53,11 @@ static char rcsid[] = "$OpenBSD: gmon.c,
 /* XXX needed? */
 //extern char *minbrk __asm ("minbrk");
 
-struct gmonparam _gmonparam = { GMON_PROF_OFF };
+struct gmonparam
+#ifdef PROFILE
+NO_COPY_INIT
+#endif
+_gmonparam = { GMON_PROF_OFF };
 
 static int     s_scale;
 /* see profil(2) where this is describe (incorrectly) */
@@ -60,7 +70,11 @@ void moncontrol __P((int));
 static void *
 fake_sbrk(int size)
 {
+#if !defined(PROFILE)
     void *rv = malloc(size);
+#else
+    void *rv = LocalAlloc(LMEM_FIXED,size);
+#endif
     if (rv)
       return rv;
     else
@@ -92,8 +106,11 @@ monstartup(lowpc, highpc)
        else if (p->tolimit > MAXARCS)
                p->tolimit = MAXARCS;
        p->tossize = p->tolimit * sizeof(struct tostruct);
-
+#ifdef PROFILE
+       cp = fake_sbrk(5 * p->kcountsize + p->fromssize + p->tossize);
+#else
        cp = fake_sbrk(p->kcountsize + p->fromssize + p->tossize);
+#endif
        if (cp == (char *)-1) {
                ERR("monstartup: out of memory\n");
                return;
@@ -105,6 +122,11 @@ monstartup(lowpc, highpc)
        cp += p->tossize;
        p->kcount = (u_short *)cp;
        cp += p->kcountsize;
+#ifdef PROFILE
+       p->comm_kcount=(u_int64_t*)cp;
+       cp += 4*p->kcountsize;
+       memset(p->comm_kcount,0,4*p->kcountsize);
+#endif
        p->froms = (u_short *)cp;
 
        /* XXX minbrk needed? */
@@ -136,6 +158,9 @@ monstartup(lowpc, highpc)
 void
 _mcleanup()
 {
+#ifdef PROFILE
+       unsigned i;
+#endif
        int fd;
        int hz;
        int fromindex;
@@ -204,8 +229,16 @@ _mcleanup()
        }
 #else
        {
+#ifdef PROFILE
+         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;
+#else
          char gmon_out[] = "gmon.out";
          proffile = gmon_out;
+#endif
        }
 #endif
 
@@ -224,6 +257,56 @@ _mcleanup()
            p->kcount, p->kcountsize);
        write(log, dbuf, len);
 #endif
+#ifdef PROFILE
+  u_int64_t maxcount = 1;
+  for (i = 0; i < p->kcountsize / 2; i++)
+       {
+         if (p->comm_kcount[i] > maxcount)
+               {
+                 maxcount = p->comm_kcount[i];
+               }
+       }
+  u_int64_t perffreq;
+  QueryPerformanceFrequency((PLARGE_INTEGER) &perffreq);
+
+  double logperffreq = log10(perffreq), logmaxcount = log10(maxcount);
+  double floorlogperffreq = floor(logperffreq);
+  double coeff_to_maximize_kcount = logmaxcount - logperffreq + 
floorlogperffreq;
+  /*
+   * To maximize kcount, we cover the case where upper bound is 9999.
+   */
+  if (coeff_to_maximize_kcount <= 3)
+       {
+         coeff_to_maximize_kcount = 0;
+       }
+  else if (coeff_to_maximize_kcount > 3)
+       {
+         /*
+          * and cover the case up to 65535.
+          */
+         coeff_to_maximize_kcount -= 3;
+         if ((logperffreq - floorlogperffreq) < log10(6.55))
+               coeff_to_maximize_kcount--;
+       }
+  else
+       {
+         coeff_to_maximize_kcount = 0;
+       }
+  hz = (int) pow(10, floor(floorlogperffreq - coeff_to_maximize_kcount));
+  perffreq /= hz;
+#if 0
+  printf("%d %d maxcount %lld logmaxcnt %f maxpreq %f hz %d perffreq %d\n", 
GetCurrentProcessId(), GetCurrentThreadId(), maxcount, logmaxcount, 
coeff_to_maximize_kcount, hz, perffreq);
+#endif
+  for (i = 0; i < p->kcountsize / 2; i++)
+       {
+         if (p->comm_kcount[i] < perffreq)
+               continue;
+         else
+               {
+                 p->kcount[i] = p->comm_kcount[i] / perffreq;
+               }
+       }
+#endif
        hdr = (struct gmonhdr *)&gmonhdr;
        hdr->lpc = p->lowpc;
        hdr->hpc = p->highpc;
Index: winsup/cygwin/gmon.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/gmon.h,v
retrieving revision 1.2
diff -u -p -r1.2 gmon.h
--- winsup/cygwin/gmon.h        24 Jun 2001 22:26:51 -0000      1.2
+++ winsup/cygwin/gmon.h        29 Aug 2011 21:01:58 -0000
@@ -134,6 +134,9 @@ struct rawarc {
 struct gmonparam {
        int             state;
        u_short         *kcount;
+#ifdef PROFILE
+       u_int64_t *comm_kcount;
+#endif
        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.84
diff -u -p -r1.84 init.cc
--- winsup/cygwin/init.cc       18 Aug 2011 15:59:16 -0000      1.84
+++ winsup/cygwin/init.cc       29 Aug 2011 21:01:58 -0000
@@ -13,6 +13,10 @@ details. */
 #include "cygtls.h"
 #include "ntdll.h"
 #include "shared_info.h"
+#ifdef PROFILE
+#include "profil.h"
+#include "instrument.h"
+#endif
 
 static DWORD _my_oldfunc;
 
@@ -106,6 +110,9 @@ respawn_wow64_process ()
        api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
       GetExitCodeProcess (pi.hProcess, &ret);
       CloseHandle (pi.hProcess);
+#ifdef PROFILE
+      profile_thread_off();
+#endif
       ExitProcess (ret);
     }
 }
@@ -120,6 +127,10 @@ dll_entry (HANDLE h, DWORD reason, void 
   switch (reason)
     {
     case DLL_PROCESS_ATTACH:
+#ifdef PROFILE
+      __cyg_profile_func_ctor();
+      __cyg_profile_tls_ctor();
+#endif
       wincap.init ();
       init_console_handler (false);
 
@@ -143,8 +154,15 @@ dll_entry (HANDLE h, DWORD reason, void 
     case DLL_PROCESS_DETACH:
       if (dynamically_loaded)
        shared_destroy ();
+#ifdef PROFILE
+      __cyg_profile_tls_dtor();
+      __cyg_profile_func_dtor();
+#endif
       break;
     case DLL_THREAD_ATTACH:
+#ifdef PROFILE
+      __cyg_profile_tls_ctor();
+#endif
       if (dll_finished_loading)
        munge_threadfunc ();
       break;
@@ -153,6 +171,9 @@ dll_entry (HANDLE h, DWORD reason, void 
          && (PVOID) &_my_tls > (PVOID) &wow64_test_stack_marker
          && _my_tls.isinitialized ())
        _my_tls.remove (0);
+#ifdef PROFILE
+       __cyg_profile_tls_dtor();
+#endif
       /* 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.279
diff -u -p -r1.279 pinfo.cc
--- winsup/cygwin/pinfo.cc      13 Aug 2011 10:28:15 -0000      1.279
+++ winsup/cygwin/pinfo.cc      29 Aug 2011 21:01:58 -0000
@@ -29,7 +29,9 @@ details. */
 #include "cygtls.h"
 #include "tls_pbuf.h"
 #include "child_info.h"
-
+#ifdef PROFILE
+#include "profil.h"
+#endif
 class pinfo_basic: public _pinfo
 {
 public:
@@ -204,6 +206,9 @@ pinfo::exit (DWORD n)
   if (!self->cygstarted)
     exitcode = ((exitcode & 0xff) << 8) | ((exitcode >> 8) & 0xff);
   sigproc_printf ("Calling ExitProcess n %p, exitcode %p", n, exitcode);
+#ifdef PROFILE
+  profile_thread_off();
+#endif
   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 -p -r1.8 profil.c
--- winsup/cygwin/profil.c      30 Aug 2010 01:57:36 -0000      1.8
+++ winsup/cygwin/profil.c      29 Aug 2011 21:01:58 -0000
@@ -7,18 +7,27 @@
    This software is a copyrighted work licensed under the terms of the
    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
    details. */
-
+#ifdef PROFILE
+#include "winsup.h"
+#endif
 #include "winlean.h"
 #include <sys/types.h>
 #include <errno.h>
-
+#ifdef PROFILE
+#include "gmon.h"
+#endif
 #include <profil.h>
 
 #define SLEEPTIME (1000 / PROF_HZ)
-
+#ifdef PROFILE
+extern SECURITY_ATTRIBUTES sec_none_nih;
+#endif
 /* global profinfo for profil() call */
+#ifdef PROFILE
+struct profinfo NO_COPY prof;
+#else
 static struct profinfo prof;
-
+#endif
 /* Get the pc for thread THR */
 
 static u_long
@@ -85,19 +94,50 @@ profile_off (struct profinfo *p)
 {
   if (p->profthr)
     {
+#ifdef PROFILE
+      if (prof.queue.worker_enabled)
+               {
+                 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
       TerminateThread (p->profthr, 0);
       CloseHandle (p->profthr);
+#endif
     }
+#if !defined(PROFILE)
   if (p->targthr)
     CloseHandle (p->targthr);
+#endif
   return 0;
 }
-
+#ifdef PROFILE
+static void __stdcall
+apc_spawnthread(unsigned long arg)
+{
+  struct profinfo* p = (struct profinfo*) arg;
+  p->profthr = CreateThread(&sec_none_nih, 0, worker_consumer, (void *) p, 0,
+         0);
+}
+#endif
 /* Create a timer thread and pass it a pointer P to the profiling buffer. */
 
 static int
 profile_on (struct profinfo *p)
 {
+#if !defined(PROFILE)
   DWORD thrid;
 
   /* get handle for this thread */
@@ -117,6 +157,13 @@ profile_on (struct profinfo *p)
       errno = EAGAIN;
       return -1;
     }
+#else
+  extern void init_global_security() asm("_Z20init_global_securityv");
+  init_global_security();
+  boundbuffer_initial(&prof.queue);
+  prof.operational = CreateSemaphoreA(&sec_none_nih, 0, 1, 0);
+  QueueUserAPC(apc_spawnthread, GetCurrentThread(), (ULONG_PTR) p);
+#endif
   return 0;
 }
 
Index: winsup/cygwin/profil.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/profil.h,v
retrieving revision 1.4
diff -u -p -r1.4 profil.h
--- winsup/cygwin/profil.h      28 Apr 2003 20:10:53 -0000      1.4
+++ winsup/cygwin/profil.h      29 Aug 2011 21:01:58 -0000
@@ -7,10 +7,16 @@ 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. */
-
+#ifndef PROFIL_H
+#define PROFIL_H
+#ifdef __cplusplus
+extern "C"{
+#endif
 /* profiling frequency.  (No larger than 1000) */
 #define PROF_HZ                        100
-
+#if defined(PROFILE)
+#include "boundbuffer.h"
+#endif
 /* convert an addr to an index */
 #define PROFIDX(pc, base, scale)       \
   ({                                                                   \
@@ -37,8 +43,17 @@ struct profinfo {
     u_short *counter;                  /* profiling counters */
     u_long lowpc, highpc;              /* range to be profiled */
     u_int scale;                       /* scale value of bins */
+#ifdef PROFILE
+    struct boundbuffer queue;
+    _WINHANDLE operational;
+#endif
 };
-
+#ifdef PROFILE
+extern struct profinfo prof;
+#endif
 int profile_ctl(struct profinfo *, char *, size_t, u_long, u_int);
 int profil(char *, size_t, u_long, u_int);
-
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: winsup/cygwin/sec_helper.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/sec_helper.cc,v
retrieving revision 1.93
diff -u -p -r1.93 sec_helper.cc
--- winsup/cygwin/sec_helper.cc 29 Apr 2011 10:38:12 -0000      1.93
+++ winsup/cygwin/sec_helper.cc 29 Aug 2011 21:01:58 -0000
@@ -476,6 +476,11 @@ get_null_sd ()
 void
 init_global_security ()
 {
+#ifdef PROFILE
+  static int called;
+  if (called++)
+       return;
+#endif
   sec_none.nLength = sec_none_nih.nLength =
   sec_all.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
   sec_none.bInheritHandle = sec_all.bInheritHandle = TRUE;
--- /dev/null   2011-08-28 23:29:31.000000000 +0900
+++ winsup/cygwin/boundbuffer.h 2011-08-25 01:33:21.943255000 +0900
@@ -0,0 +1,66 @@
+/* boundbuffer.h
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ This source code is offered for use in the public domain. You may
+ use, modify or distribute it freely.
+
+ This code is distributed in the hope that it will be useful but
+ WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
+ DISCLAMED. This includes but is not limited to warrenties of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#ifndef BOUNDBUFFER_H_
+#define BOUNDBUFFER_H_
+#include <stdio.h>
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+  extern void
+  profile_thread_off();
+  struct message
+  {
+#if 0
+       unsigned long long ldata;
+       unsigned long idata[2];
+#endif
+       void* pv;
+       unsigned long long ullval;
+  };
+  typedef struct message message;
+  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;
+  };
+#define reg(x) __attribute__((regparm((x))))
+#define buffermethod(x) boundbuffer_##x
+  extern void buffermethod(ctor)(struct boundbuffer*);
+  extern void buffermethod(initial)(struct boundbuffer*);
+  extern void buffermethod(dtor)(struct boundbuffer*);
+  extern reg(2) int buffermethod(enqueue)(struct boundbuffer*, message);
+  extern reg(2) int buffermethod(dequeue)(struct boundbuffer*, message*);
+  extern reg(2) void buffermethod(dequeue_nolock)(struct boundbuffer*, 
message*);
+  extern int buffermethod(empty)(struct boundbuffer*);
+  extern int buffermethod(full)(struct boundbuffer*);
+#undef buffermethod
+#undef reg
+#ifdef __cplusplus
+}
+#endif
+#endif /* BOUNDBUFFER_H_ */
--- /dev/null   2011-08-28 23:29:31.000000000 +0900
+++ winsup/cygwin/boundbuffer.c 2011-08-28 14:15:22.281250000 +0900
@@ -0,0 +1,179 @@
+/* boundbuffer.c
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ This source code is offered for use in the public domain. You may
+ use, modify or distribute it freely.
+
+ This code is distributed in the hope that it will be useful but
+ WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
+ DISCLAMED. This includes but is not limited to warrenties of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#include "winsup.h"
+#include "winlean.h"
+#include "profil.h"
+#include "gmon.h"
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "boundbuffer.h"
+/* Use
+ * 0: semaphore
+ * 1: event
+ */
+#define USE_EVENT 1
+/*
+ * There are cases where the bounded buffer is blocked and not operational.
+ * as a workaround, give maximum timeout to WFSO.
+ * as long as profile_thread_off is issued before every ExitProcess, it is 
okay if the timeout is INFINITE.
+ */
+#define WFSO_TIMEOUT_MS INFINITE
+/*
+ * http://msdn.microsoft.com/en-us/library/ms687032.aspx
+ *  Current thread and process handles are special cased
+ */
+#define INVALID_FOR_SURE -3
+extern SECURITY_ATTRIBUTES sec_none_nih;
+DWORD __stdcall
+worker_consumer(void* arg)
+{
+  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);
+  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;
+}
+#ifdef PROFILE
+void
+profile_thread_off()
+{
+  int enabled = __sync_fetch_and_and(&prof.queue.worker_enabled, 0);
+  if (enabled)
+       {
+         ReleaseSemaphore(prof.queue.member[FILL].h, 1, 0);
+         WaitForSingleObject(prof.profthr, INFINITE);
+       }
+}
+#endif
+#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, 0x08000000);
+#if USE_EVENT
+  this->member[EMPTY].h = CreateEventA(&sec_none_nih, 1, 1, 0);
+#else
+  this->member[EMPTY].h = CreateSemaphoreA(&sec_none_nih, SZBUF, SZBUF, 0);
+#endif
+  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 = 
INVALID_FOR_SURE;
+}
+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 = 
INVALID_FOR_SURE;
+}
+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");
+}
+__attribute__((always_inline,regparm(2))) void 
buffermethod(enqueue_nolock)(struct boundbuffer*, message);
+int __attribute__((regparm(2))) 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, WFSO_TIMEOUT_MS);
+  if ((ret != WAIT_OBJECT_0) || !this->worker_enabled)
+       return 0;
+  EnterCriticalSection(&prof.queue.member[MUTEX].s);
+  buffermethod(enqueue_nolock)(this, obj);
+#if USE_EVENT
+  long avail_to_dequeue;
+  ReleaseSemaphore(this->member[FILL].h, 0, &avail_to_dequeue);
+  avail_to_dequeue = avail_to_dequeue == (SZBUF - 1);
+#endif
+  LeaveCriticalSection(&prof.queue.member[MUTEX].s);
+#if USE_EVENT
+  if (avail_to_dequeue)
+       ResetEvent(this->member[EMPTY].h);
+#endif
+  ReleaseSemaphore(this->member[FILL].h, 1, 0);
+  return 1;
+}
+
+int buffermethod(empty)(struct boundbuffer* this)
+{
+  int ret = this->member[FRONT].i == this->member[BACK].i;
+  return ret;
+}
+int buffermethod(full)(struct boundbuffer* this)
+{
+  int ret = (this->member[FRONT].i + this->member[BACK].i) == (SZBUF - 1);
+  return ret;
+}
+int __attribute__((regparm(2))) 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, WFSO_TIMEOUT_MS);
+  if ((ret != WAIT_OBJECT_0) || !this->worker_enabled)
+       return 0;
+  EnterCriticalSection(&prof.queue.member[MUTEX].s);
+  buffermethod(dequeue_nolock)(this, result);
+#if USE_EVENT
+  long avail_to_enqueue;
+  ReleaseSemaphore(this->member[FILL].h, 0, &avail_to_enqueue);
+  avail_to_enqueue = avail_to_enqueue <= 0;
+#endif
+  LeaveCriticalSection(&prof.queue.member[MUTEX].s);
+#if USE_EVENT
+  if (avail_to_enqueue)
+       SetEvent(this->member[EMPTY].h);
+#else
+  ReleaseSemaphore(this->member[EMPTY].h, 1, 0);
+#endif
+  return 1;
+}
+__attribute__((always_inline,regparm(2))) 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,regparm(2))) void 
buffermethod(dequeue_nolock)(struct boundbuffer* this, message* result)
+{
+  (*result) = this->buffer[this->member[FRONT].i];
+  this->member[FRONT].i = (this->member[FRONT].i + 1) % SZBUF;
+}
+#undef buffermethod
--- /dev/null   2011-08-28 23:29:31.000000000 +0900
+++ winsup/cygwin/instrument.c  2011-08-26 05:45:15.234375000 +0900
@@ -0,0 +1,119 @@
+/* instrument.c
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ This source code is offered for use in the public domain. You may
+ use, modify or distribute it freely.
+
+ This code is distributed in the hope that it will be useful but
+ WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
+ DISCLAMED. This includes but is not limited to warrenties of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Created on: 2011. 3. 2.
+ */
+#include <stdint.h>
+#include "winsup.h"
+#include "winlean.h"
+#include "profil.h"
+#include "instrument.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(LMEM_ZEROINIT, sizeof(struct clk));
+  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;
+}
+/*
+ * It would be better if it does either bound checks and some assertion about 
caller.
+ * For the issue of bound check, it is assumed that cygwin's call stack grows 
less than CALLSTACKBOUND.
+ * For the issue of caller, it is belived that gcc does right thing so that we 
have matching enter/exit pair.
+ */
+static void __attribute__ ((always_inline,no_instrument_function,regparm(3)))
+__cyg_set_clk(struct clk* clkinfo, void *caller, int state)
+{
+  register int idx;
+  register message msg;
+  switch (state)
+       {
+  case 0:
+       if (!clkinfo->idx)
+         goto skip;
+       idx = --clkinfo->idx;
+       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;
+       clkinfo->pc[idx] = caller;
+       clkinfo->tsc[idx] = __builtin_ia32_rdtsc();
+       clkinfo->idx++;
+       break;
+  default:
+       goto skip;
+       break;
+       };
+  skip: do
+       {
+       }
+  while (0);
+}
+/*
+ * GetLastError / SetLastError is needed because Tls* alter last error code
+ */
+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)
+       {
+         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)
+       {
+         goto trap;
+       }
+  __cyg_set_clk(clkinfo, caller, 0);
+  trap: SetLastError(err);
+}
--- /dev/null   2011-08-28 23:29:32.000000000 +0900
+++ winsup/cygwin/instrument.h  2011-08-26 05:32:14.718375000 +0900
@@ -0,0 +1,42 @@
+/* instrument.c
+
+ THIS SOFTWARE IS NOT COPYRIGHTED
+
+ This source code is offered for use in the public domain. You may
+ use, modify or distribute it freely.
+
+ This code is distributed in the hope that it will be useful but
+ WITHOUT ANY WARRANTY. ALL WARRENTIES, EXPRESS OR IMPLIED ARE HEREBY
+ DISCLAMED. This includes but is not limited to warrenties of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Created on: 2011. 3. 18.
+ */
+#ifndef INSTRUMENT_H_
+#define INSTRUMENT_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+  struct clk
+  {
+       /*
+        * FIXME: CALLSTACKBOUND should be less than maximum call stack size.
+        */
+#define CALLSTACKBOUND 0x10000
+       unsigned idx;
+       void* pc[CALLSTACKBOUND];
+       unsigned long long tsc[CALLSTACKBOUND];
+  };
+  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