public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
* [PATCH] workaround for sigproc_init
@ 2011-07-29 11:41 jojelino
  2011-07-30 20:57 ` Christopher Faylor
  2011-07-30 21:05 ` Christopher Faylor
  0 siblings, 2 replies; 9+ messages in thread
From: jojelino @ 2011-07-29 11:41 UTC (permalink / raw)
  To: cygwin-patches

[-- Attachment #1: Type: text/plain, Size: 546 bytes --]

As sigproc_init is called during dll initialization, wait_sig thread is 
not created as soon as possible.(this is known in msdn createthread 
reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
And then wait_sig starts to wake up as sig_dispatch_pending enters 
waitforsingleobject. then main thread stops for few ms. and it shows 
poor performance.
as a workaround, issue user apc call, let the os decide when to call them.
And the result was quite good. patch,changelog modified are attached.
Please review it.

Regards.

[-- Attachment #2: workaround_sigproc.diff --]
[-- Type: text/plain, Size: 1886 bytes --]

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	29 Jul 2011 10:45:11 -0000
@@ -447,6 +447,9 @@
 
 /* Signal thread initialization.  Called from dll_crt0_1.
    This routine starts the signal handling thread.  */
+static void __stdcall apc_spawnthread(unsigned long p){
+	new cygthread (wait_sig, cygself, "sig");
+}
 void __stdcall
 sigproc_init ()
 {
@@ -459,7 +462,16 @@
       api_fatal ("couldn't create signal pipe, %E");
   ProtectHandle (my_readsig);
   myself->sendsig = my_sendsig;
-  new cygthread (wait_sig, cygself, "sig");
+  /*
+   * Issue user APC call, and let the os decide when to call them.
+   * It is known as workaround. wait_sig thread wakes up faster.
+   */
+  if (!QueueUserAPC(apc_spawnthread,GetCurrentThread(),0)){
+	  /*
+	   * And failed. just call from here.
+	   */
+	  apc_spawnthread(0);
+  }
   /* sync_proc_subproc is used by proc_subproc.  It serializes
      access to the children and proc arrays.  */
   sync_proc_subproc.init ("sync_proc_subproc");

Index: winsup/cygwin/ChangeLog
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/ChangeLog,v
retrieving revision 1.5455
diff -u -r1.5455 ChangeLog
--- winsup/cygwin/ChangeLog	26 Jul 2011 13:30:40 -0000	1.5455
+++ winsup/cygwin/ChangeLog	29 Jul 2011 11:07:49 -0000
@@ -1,3 +1,8 @@
+2011-07-29  Jinwoo Ye  <jojelino@gmail.com>
+
+	* sigproc.cc (apc_spawnthread): New function for sigproc_init.
+	(sigproc_init): Use apc_spawnthread, use QueueUserAPC and explain why.
+
 2011-07-26  Corinna Vinschen  <corinna@vinschen.de>
 
 	* fhandler_disk_file.cc (__DIR_mounts::eval_ino): Create path_conv

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] workaround for sigproc_init
  2011-07-29 11:41 [PATCH] workaround for sigproc_init jojelino
@ 2011-07-30 20:57 ` Christopher Faylor
  2011-07-30 21:05 ` Christopher Faylor
  1 sibling, 0 replies; 9+ messages in thread
From: Christopher Faylor @ 2011-07-30 20:57 UTC (permalink / raw)
  To: cygwin-patches

On Fri, Jul 29, 2011 at 08:41:10PM +0900, jojelino wrote:
>As sigproc_init is called during dll initialization, wait_sig thread is 
>not created as soon as possible.(this is known in msdn createthread 
>reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
>And then wait_sig starts to wake up as sig_dispatch_pending enters 
>waitforsingleobject. then main thread stops for few ms. and it shows 
>poor performance.
>as a workaround, issue user apc call, let the os decide when to call them.
>And the result was quite good. patch,changelog modified are attached.
>Please review it.

The result is good but the patch isn't the way I chose to implement
this.  I appreciate the idea, though.  The performance improvement
is amazing.

Thanks for the patch/idea.

cgf

P.S.  I really do appreciate the effort that you put into this but, had
it been accepted, it would have required some reformatting since you
used a different indentation style from the rest of the code.  I hope
that you'll consider keeping your changes formatted like the surrounded
code.  It will make patch adoption easier.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] workaround for sigproc_init
  2011-07-29 11:41 [PATCH] workaround for sigproc_init jojelino
  2011-07-30 20:57 ` Christopher Faylor
@ 2011-07-30 21:05 ` Christopher Faylor
  2011-07-31  8:27   ` Corinna Vinschen
  1 sibling, 1 reply; 9+ messages in thread
From: Christopher Faylor @ 2011-07-30 21:05 UTC (permalink / raw)
  To: cygwin-patches

On Fri, Jul 29, 2011 at 08:41:10PM +0900, jojelino wrote:
>As sigproc_init is called during dll initialization, wait_sig thread is 
>not created as soon as possible.(this is known in msdn createthread 
>reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
>And then wait_sig starts to wake up as sig_dispatch_pending enters 
>waitforsingleobject. then main thread stops for few ms. and it shows 
>poor performance.

Incidentally, the intent of the now-defunct wincap
wincap.has_buggy_thread_startup was to avoid creating wait_sig during
thread startup, moving it to dll_crt0_1() which is the code that
eventually calls main().

(This was all rehashed back in August/September 2010)

Although I didn't fiddle with that myself, Corinna reported that having
the value set had no effect in her test cases so I don't think your
analysis here is 100% correct.

cgf

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] workaround for sigproc_init
  2011-07-30 21:05 ` Christopher Faylor
@ 2011-07-31  8:27   ` Corinna Vinschen
  2011-07-31  9:17     ` [PATCH] you can use this patch to profile cygwin jojelino
                       ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Corinna Vinschen @ 2011-07-31  8:27 UTC (permalink / raw)
  To: cygwin-patches

On Jul 30 17:04, Christopher Faylor wrote:
> On Fri, Jul 29, 2011 at 08:41:10PM +0900, jojelino wrote:
> >As sigproc_init is called during dll initialization, wait_sig thread is 
> >not created as soon as possible.(this is known in msdn createthread 
> >reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
> >And then wait_sig starts to wake up as sig_dispatch_pending enters 
> >waitforsingleobject. then main thread stops for few ms. and it shows 
> >poor performance.
> 
> Incidentally, the intent of the now-defunct wincap
> wincap.has_buggy_thread_startup was to avoid creating wait_sig during
> thread startup, moving it to dll_crt0_1() which is the code that
> eventually calls main().
> 
> (This was all rehashed back in August/September 2010)
> 
> Although I didn't fiddle with that myself, Corinna reported that having
> the value set had no effect in her test cases so I don't think your
> analysis here is 100% correct.

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

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] you can use this patch to profile cygwin
  2011-07-31  8:27   ` Corinna Vinschen
@ 2011-07-31  9:17     ` jojelino
  2011-07-31 17:31       ` Christopher Faylor
  2011-07-31  9:25     ` [PATCH] you can use this patch to profile cygwin-2 jojelino
  2011-07-31 18:51     ` [PATCH] workaround for sigproc_init Christopher Faylor
  2 siblings, 1 reply; 9+ messages in thread
From: jojelino @ 2011-07-31  9:17 UTC (permalink / raw)
  To: cygwin-patches

[-- Attachment #1: Type: text/plain, Size: 2169 bytes --]

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.

[-- Attachment #2: thread_profile_core.diff --]
[-- Type: text/plain, Size: 18852 bytes --]

? .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) \

[-- Attachment #3: thread_profile_stuff.diff --]
[-- Type: text/plain, Size: 11631 bytes --]

--- /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_ */

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] you can use this patch to profile cygwin-2
  2011-07-31  8:27   ` Corinna Vinschen
  2011-07-31  9:17     ` [PATCH] you can use this patch to profile cygwin jojelino
@ 2011-07-31  9:25     ` jojelino
  2011-07-31 18:51     ` [PATCH] workaround for sigproc_init Christopher Faylor
  2 siblings, 0 replies; 9+ messages in thread
From: jojelino @ 2011-07-31  9:25 UTC (permalink / raw)
  To: cygwin-patches

On 2011-07-31 PM 6:16, jojelino wrote:
 > # 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...)
I missed important one.
Please find rule in Makefile and apply following.

# Rule to build cygwin.dll
$(TEST_DLL_NAME): $(LDSCRIPT) dllfixdbg $(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) gcrt1.o $(DLL_OFILES) version.o winver.o \
  $(MALLOC_OBJ) $(LIBSERVER) $(LIBM) $(LIBC) boundbuffer.o instrument.o 
gmon.o mcount.o profil.o /lib/w32api/libkernel32.a \
  -lgcc $(DLL_IMPORTS) -Wl,-Map,cygwin.map
  @$(word 2,$^) $(OBJDUMP) $(OBJCOPY) $@ ${patsubst %0.dll,%1.dbg,$@}
  @ln -f $@ new-$(DLL_NAME)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] you can use this patch to profile cygwin
  2011-07-31  9:17     ` [PATCH] you can use this patch to profile cygwin jojelino
@ 2011-07-31 17:31       ` Christopher Faylor
  0 siblings, 0 replies; 9+ messages in thread
From: Christopher Faylor @ 2011-07-31 17:31 UTC (permalink / raw)
  To: cygwin-patches

On Sun, Jul 31, 2011 at 06:16:56PM +0900, jojelino wrote:
>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.

And, as usual, the formatting is completely off so it couldn't be
incorporated into the source code as is regardless.

Given that this isn't a submitted patch, it probably makes sense to
continue any discussion in cygwin-developers.

cgf

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] workaround for sigproc_init
  2011-07-31  8:27   ` Corinna Vinschen
  2011-07-31  9:17     ` [PATCH] you can use this patch to profile cygwin jojelino
  2011-07-31  9:25     ` [PATCH] you can use this patch to profile cygwin-2 jojelino
@ 2011-07-31 18:51     ` Christopher Faylor
  2011-08-01  8:57       ` Corinna Vinschen
  2 siblings, 1 reply; 9+ messages in thread
From: Christopher Faylor @ 2011-07-31 18:51 UTC (permalink / raw)
  To: cygwin-patches

On Sun, Jul 31, 2011 at 10:26:23AM +0200, Corinna Vinschen wrote:
>On Jul 30 17:04, Christopher Faylor wrote:
>> On Fri, Jul 29, 2011 at 08:41:10PM +0900, jojelino wrote:
>> >As sigproc_init is called during dll initialization, wait_sig thread is 
>> >not created as soon as possible.(this is known in msdn createthread 
>> >reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
>> >And then wait_sig starts to wake up as sig_dispatch_pending enters 
>> >waitforsingleobject. then main thread stops for few ms. and it shows 
>> >poor performance.
>> 
>> Incidentally, the intent of the now-defunct wincap
>> wincap.has_buggy_thread_startup was to avoid creating wait_sig during
>> thread startup, moving it to dll_crt0_1() which is the code that
>> eventually calls main().
>> 
>> (This was all rehashed back in August/September 2010)
>> 
>> Although I didn't fiddle with that myself, Corinna reported that having
>> the value set had no effect in her test cases so I don't think your
>> analysis here is 100% correct.
>
>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.

With my recent changes, I see about 10% difference between W7 64-bit
and XP 32-bit on the same machine.  W7 64-bit is slower.

cgf

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] workaround for sigproc_init
  2011-07-31 18:51     ` [PATCH] workaround for sigproc_init Christopher Faylor
@ 2011-08-01  8:57       ` Corinna Vinschen
  0 siblings, 0 replies; 9+ messages in thread
From: Corinna Vinschen @ 2011-08-01  8:57 UTC (permalink / raw)
  To: cygwin-patches

On Jul 31 14:51, Christopher Faylor wrote:
> On Sun, Jul 31, 2011 at 10:26:23AM +0200, Corinna Vinschen wrote:
> >On Jul 30 17:04, Christopher Faylor wrote:
> >> On Fri, Jul 29, 2011 at 08:41:10PM +0900, jojelino wrote:
> >> >As sigproc_init is called during dll initialization, wait_sig thread is 
> >> >not created as soon as possible.(this is known in msdn createthread 
> >> >reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx)
> >> >And then wait_sig starts to wake up as sig_dispatch_pending enters 
> >> >waitforsingleobject. then main thread stops for few ms. and it shows 
> >> >poor performance.
> >> 
> >> Incidentally, the intent of the now-defunct wincap
> >> wincap.has_buggy_thread_startup was to avoid creating wait_sig during
> >> thread startup, moving it to dll_crt0_1() which is the code that
> >> eventually calls main().
> >> 
> >> (This was all rehashed back in August/September 2010)
> >> 
> >> Although I didn't fiddle with that myself, Corinna reported that having
> >> the value set had no effect in her test cases so I don't think your
> >> analysis here is 100% correct.
> >
> >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.
> 
> With my recent changes, I see about 10% difference between W7 64-bit
> and XP 32-bit on the same machine.  W7 64-bit is slower.

Interesting.  I tested on identical virtual hardware.

  for i in `seq 1 300`; do date; done > list.log

This takes 6.8 secs on W7 32 bit, 10.7 secs on W7 64 bit, and 10.6 secs
on 2008 R2 64 bit with two virtual CPUs.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-08-01  8:57 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-29 11:41 [PATCH] workaround for sigproc_init jojelino
2011-07-30 20:57 ` Christopher Faylor
2011-07-30 21:05 ` Christopher Faylor
2011-07-31  8:27   ` Corinna Vinschen
2011-07-31  9:17     ` [PATCH] you can use this patch to profile cygwin jojelino
2011-07-31 17:31       ` Christopher Faylor
2011-07-31  9:25     ` [PATCH] you can use this patch to profile cygwin-2 jojelino
2011-07-31 18:51     ` [PATCH] workaround for sigproc_init Christopher Faylor
2011-08-01  8:57       ` Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).