[PATCH] cygwin-htdocs: Upgrade 32-bit note to Q and A

2024-06-09 Thread Mark Geisert
Upgrade the note about 32-bit Cygwin to a full question and answer(s).
Also close a couple of HTML tags that need it.

---
 install.html | 22 +++---
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/install.html b/install.html
index cdb9948b..c948e647 100755
--- a/install.html
+++ b/install.html
@@ -201,7 +201,7 @@ version for an old, unsupported Windows?
   
   
 Also use --no-verify with this URL.
-  
 
   
   
@@ -242,7 +242,7 @@ version for an old, unsupported Windows?
   64-bit: 
http://ctm.crouchingtigerhiddenfruitbat.org/pub/cygwin/circa/64bit/2016/08/30/104235
   
 Also use --no-verify with these URLs.
-  
 
   
   
@@ -273,15 +273,23 @@ version for an old, unsupported Windows?
   Time Machine for providing this archive.
 
 
-  A note about 32-bit Cygwin
+Q: Can I still run unsupported 32-bit 
Cygwin?
+
+  
+A1: You can, but why would you?  32-bit Cygwin was frozen at version
+3.3.6, around August 2022.  There have been and there will be no bug
+fixes or security updates, and no new functionality added.  No longer
+supported on the mailing lists; it has joined the choir invisible.
+  
 
   
-The limited address space of 32-bit Windows means that
+A2: If you're on 32-bit Windows as well,
+the limited address space there means that
 random
 failures in the fork(2) system call are more likely.  Therefore, we
-recommend using 32-bit Cygwin only in limited scenarios, with only a 
minimum
-of necessary packages installed, and only if there's no way to run 64-bit
-Cygwin instead.
+recommend using 32-bit Cygwin only in limited scenarios, with only a
+minimum of necessary packages installed, and only if there's no way
+to run 64-bit Cygwin instead.
   
 
   
-- 
2.43.0



[PATCH v2] Fix profiler error() definition and usage

2023-11-14 Thread Mark Geisert
Minor updates to profiler and gmondump, which share some code:
- fix operation of error() so it actually works as intended
- resize 4K-size auto buffer reservations to BUFSIZ (==1K)
- remove trailing '\n' from 2nd arg on error() calls everywhere
- provide consistent annotation of Windows error number displays

Fixes: 9887fb27f6126 ("Cygwin: New tool: profiler")
Fixes: 087a3d76d7335 ("Cygwin: New tool: gmondump")
Signed-off-by: Mark Geisert 

---
 winsup/cygwin/release/3.4.10 |  3 +++
 winsup/utils/gmondump.c  |  8 ---
 winsup/utils/profiler.cc | 46 +++-
 3 files changed, 32 insertions(+), 25 deletions(-)

diff --git a/winsup/cygwin/release/3.4.10 b/winsup/cygwin/release/3.4.10
index ec28cdf7e..641c82647 100644
--- a/winsup/cygwin/release/3.4.10
+++ b/winsup/cygwin/release/3.4.10
@@ -9,3 +9,6 @@ Bug Fixes
 
 - Let feraiseexcept actually raise an exception.
   Addresses: https://cygwin.com/pipermail/cygwin/2023-October/254667.html
+
+- Updates to profiler and gmondump: error display mechanics, buffer sizing,
+  and output formatting.
diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
index 16b99594a..3472a147e 100644
--- a/winsup/utils/gmondump.c
+++ b/winsup/utils/gmondump.c
@@ -58,7 +58,7 @@ void
 note (const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   vsprintf (buf, fmt, args);
@@ -72,7 +72,7 @@ void
 warn (int geterrno, const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   sprintf (buf, "%s: ", pgm);
@@ -92,10 +92,12 @@ void __attribute__ ((noreturn))
 error (int geterrno, const char *fmt, ...)
 {
   va_list args;
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
-  warn (geterrno, fmt, args);
+  vsprintf (buf, fmt, args);
   va_end (args);
+  warn (geterrno, "%s", buf);
 
   exit (1);
 }
diff --git a/winsup/utils/profiler.cc b/winsup/utils/profiler.cc
index 520e29d12..b5ce16cf2 100644
--- a/winsup/utils/profiler.cc
+++ b/winsup/utils/profiler.cc
@@ -130,7 +130,7 @@ void
 note (const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   vsprintf (buf, fmt, args);
@@ -144,7 +144,7 @@ void
 warn (int geterrno, const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   sprintf (buf, "%s: ", pgm);
@@ -164,10 +164,12 @@ void __attribute__ ((noreturn))
 error (int geterrno, const char *fmt, ...)
 {
   va_list args;
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
-  warn (geterrno, fmt, args);
+  vsprintf (buf, fmt, args);
   va_end (args);
+  warn (geterrno, "%s", buf);
 
   exit (1);
 }
@@ -263,15 +265,15 @@ start_profiler (child *c)
 note ("*** start profiler thread on pid %lu\n", (ulong) c->pid);
   c->context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
   if (!c->context)
-error (0, "unable to allocate CONTEXT buffer\n");
+error (0, "unable to allocate CONTEXT buffer");
   c->context->ContextFlags = CONTEXT_CONTROL;
   c->hquitevt = CreateEvent (NULL, TRUE, FALSE, NULL);
   if (!c->hquitevt)
-error (0, "unable to create quit event\n");
+error (0, "unable to create quit event");
   c->profiling = 1;
   c->hprofthr = CreateThread (NULL, 0, profiler, (void *) c, 0, );
   if (!c->hprofthr)
-error (0, "unable to create profiling thread\n");
+error (0, "unable to create profiling thread");
 
   /* There is a temptation to raise the execution priority of the profiling
* threads.  Don't do this, or at least don't do it this way.  Testing
@@ -321,7 +323,7 @@ dump_profile_data (child *c)
 
   fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);
   if (fd < 0)
-error (0, "dump_profile_data: unable to create %s\n", filename);
+error (0, "dump_profile_data: unable to create %s", filename);
 
   memset (, 0, sizeof (hdr));
   hdr.lpc = s->textlo;
@@ -427,7 +429,7 @@ add_thread (DWORD pid, DWORD tid, HANDLE h, WCHAR *name)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "add_thread: pid %lu not found\n", (ulong) pid);
+error (0, "add_thread: pid %lu not found", (ulong) pid);
 
   thread_list *t = (thread_list *) calloc (1, sizeof (thread_list));
   t->tid = tid;
@@ -444,7 +446,7 @@ remove_thread (DWORD pid, DWORD tid)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "remove_thread: pid %lu not found\n", (ulong) pid);
+error (0, "remove_thread: pid %lu not found", (ulong) pid);
 
   thread_list *t = c->threads;
   while (t)
@@ -463,7 +465,7 @@ remove_thread (DWORD pid, DWORD tid)
   t = t->next;
 }
 
-  error (0, "remove_thread: pid %lu tid %lu not found\n",
+  error 

Re: [PATCH] Cygwin: Fix profiler error() definition and usage

2023-11-14 Thread Mark Geisert

Hi Corinna,

On Mon, 13 Nov 2023, Corinna Vinschen wrote:

On Nov 13 01:46, Mark Geisert wrote:

Minor updates to profiler and gmondump, which share some code:
- fix operation of error() so it actually works as intended
- resize 4K-size auto buffer reservations to BUFSIZ (==1K)
- remove trailing '\n' from 2nd arg on error() calls everywhere
- provide consistent annotation of Windows error number displays

Fixes: 9887fb27f6126 ("Cygwin: New tool: profiler")
Fixes: 087a3d76d7335 ("Cygwin: New tool: gmondump")
Signed-off-by: Mark Geisert 


Looks good basically, but I noticed some minor problem already
in the former version of this code:


@@ -650,7 +652,7 @@ ctrl_c (DWORD)
   static int tic = 1;

   if ((tic ^= 1) && !GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0))
-error (0, "couldn't send CTRL-C to child, win32 error %d\n",
+error (0, "couldn't send CTRL-C to child, Windows error %d",
GetLastError ());
   return TRUE;


GetLastError returns a DWORD == unsigned int. %u would be the
right format specifier.  Care to fix that, too?


Thanks for catching this.  Patch v2 is incoming, and it includes a
relnote for 3.4.10.
Cheers & Regards,

..mark


[PATCH] Cygwin: Fix profiler error() definition and usage

2023-11-13 Thread Mark Geisert
Minor updates to profiler and gmondump, which share some code:
- fix operation of error() so it actually works as intended
- resize 4K-size auto buffer reservations to BUFSIZ (==1K)
- remove trailing '\n' from 2nd arg on error() calls everywhere
- provide consistent annotation of Windows error number displays

Fixes: 9887fb27f6126 ("Cygwin: New tool: profiler")
Fixes: 087a3d76d7335 ("Cygwin: New tool: gmondump")
Signed-off-by: Mark Geisert 

---
 winsup/utils/gmondump.c  |  8 ---
 winsup/utils/profiler.cc | 46 +---
 2 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
index 16b99594a..3472a147e 100644
--- a/winsup/utils/gmondump.c
+++ b/winsup/utils/gmondump.c
@@ -58,7 +58,7 @@ void
 note (const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   vsprintf (buf, fmt, args);
@@ -72,7 +72,7 @@ void
 warn (int geterrno, const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   sprintf (buf, "%s: ", pgm);
@@ -92,10 +92,12 @@ void __attribute__ ((noreturn))
 error (int geterrno, const char *fmt, ...)
 {
   va_list args;
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
-  warn (geterrno, fmt, args);
+  vsprintf (buf, fmt, args);
   va_end (args);
+  warn (geterrno, "%s", buf);
 
   exit (1);
 }
diff --git a/winsup/utils/profiler.cc b/winsup/utils/profiler.cc
index 520e29d12..b2e26d663 100644
--- a/winsup/utils/profiler.cc
+++ b/winsup/utils/profiler.cc
@@ -130,7 +130,7 @@ void
 note (const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   vsprintf (buf, fmt, args);
@@ -144,7 +144,7 @@ void
 warn (int geterrno, const char *fmt, ...)
 {
   va_list args;
-  charbuf[4096];
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
   sprintf (buf, "%s: ", pgm);
@@ -164,10 +164,12 @@ void __attribute__ ((noreturn))
 error (int geterrno, const char *fmt, ...)
 {
   va_list args;
+  charbuf[BUFSIZ];
 
   va_start (args, fmt);
-  warn (geterrno, fmt, args);
+  vsprintf (buf, fmt, args);
   va_end (args);
+  warn (geterrno, "%s", buf);
 
   exit (1);
 }
@@ -263,15 +265,15 @@ start_profiler (child *c)
 note ("*** start profiler thread on pid %lu\n", (ulong) c->pid);
   c->context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
   if (!c->context)
-error (0, "unable to allocate CONTEXT buffer\n");
+error (0, "unable to allocate CONTEXT buffer");
   c->context->ContextFlags = CONTEXT_CONTROL;
   c->hquitevt = CreateEvent (NULL, TRUE, FALSE, NULL);
   if (!c->hquitevt)
-error (0, "unable to create quit event\n");
+error (0, "unable to create quit event");
   c->profiling = 1;
   c->hprofthr = CreateThread (NULL, 0, profiler, (void *) c, 0, );
   if (!c->hprofthr)
-error (0, "unable to create profiling thread\n");
+error (0, "unable to create profiling thread");
 
   /* There is a temptation to raise the execution priority of the profiling
* threads.  Don't do this, or at least don't do it this way.  Testing
@@ -321,7 +323,7 @@ dump_profile_data (child *c)
 
   fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);
   if (fd < 0)
-error (0, "dump_profile_data: unable to create %s\n", filename);
+error (0, "dump_profile_data: unable to create %s", filename);
 
   memset (, 0, sizeof (hdr));
   hdr.lpc = s->textlo;
@@ -427,7 +429,7 @@ add_thread (DWORD pid, DWORD tid, HANDLE h, WCHAR *name)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "add_thread: pid %lu not found\n", (ulong) pid);
+error (0, "add_thread: pid %lu not found", (ulong) pid);
 
   thread_list *t = (thread_list *) calloc (1, sizeof (thread_list));
   t->tid = tid;
@@ -444,7 +446,7 @@ remove_thread (DWORD pid, DWORD tid)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "remove_thread: pid %lu not found\n", (ulong) pid);
+error (0, "remove_thread: pid %lu not found", (ulong) pid);
 
   thread_list *t = c->threads;
   while (t)
@@ -463,7 +465,7 @@ remove_thread (DWORD pid, DWORD tid)
   t = t->next;
 }
 
-  error (0, "remove_thread: pid %lu tid %lu not found\n",
+  error (0, "remove_thread: pid %lu tid %lu not found",
  (ulong) pid, (ulong) tid);
 }
 
@@ -475,9 +477,9 @@ read_child (void *buf, SIZE_T size, void *addr, HANDLE h)
   if (debugging)
 note ("read %d bytes at %p from handle %d\n", size, addr, h);
   if (0 == ReadProcessMemory (h, addr, buf, size, ))
-error (0, "read_child: failed\n");
+error (0, "read_child: failed");
   if (len != size)
-error (0, "read_

Re: Which git hash to supply on Fixes: line -- never mind

2023-11-13 Thread Mark Geisert

On Sun, 12 Nov 2023, Mark Geisert wrote:

Hi folks,
I want to submit a patch that fixes 'profiler'.  The Fixes: line of the patch 
commentary should reference the original addition of profiler to the Cygwin 
source tree.


Using the gitweb interface, the commit display of profiler.cc shows:
authorMark Geisert   2021-07-15 21:49:55 -0700
committer Jon Turney  2021-07-19 13:28:37 +0100
commit  9bd6c0b2b1081ae72d8273038309887fb27f6126 (patch)
tree360d7d3cc748683eb9e63729a7e52a62012730e4 /winsup/utils/profiler.cc
parent  Cygwin: cfsetspeed: allow speed to be a numerical baud rate (diff)

Do I use the last 13 nibbles of the "commit" hash or the "tree" hash?


Never mind; I've figured it out.  It's the "commit" hash, which I 
determined by 'git log profiler.cc'.  Obvious in hindsight.

Cheers,

..mark


Which git hash to supply on Fixes: line

2023-11-12 Thread Mark Geisert

Hi folks,
I want to submit a patch that fixes 'profiler'.  The Fixes: line of the 
patch commentary should reference the original addition of profiler to the 
Cygwin source tree.


Using the gitweb interface, the commit display of profiler.cc shows:
authorMark Geisert   2021-07-15 21:49:55 -0700
committer Jon Turney  2021-07-19 13:28:37 +0100
commit  9bd6c0b2b1081ae72d8273038309887fb27f6126 (patch)
tree360d7d3cc748683eb9e63729a7e52a62012730e4 /winsup/utils/profiler.cc
parent  Cygwin: cfsetspeed: allow speed to be a numerical baud rate (diff)

Do I use the last 13 nibbles of the "commit" hash or the "tree" hash?

First time I've seen both; on previous patches I've supplied a hash but 
I'm not sure which one of these they were because I was relying on some 
other method to find them.

Thanks,

..mark


Re: [PATCH] Cygwin: Fix __cpuset_zero_s prototype

2023-09-09 Thread Mark Geisert

Mark Geisert wrote, and then wrote again:

Corinna Vinschen wrote:

On Sep  7 22:36, Mark Geisert wrote:

Add a missing "void" to the prototype for __cpuset_zero_s().

Reported-by: Marco Mason 
Addresses: https://cygwin.com/pipermail/cygwin/2023-September/254423.html
Signed-off-by: Mark Geisert 
Fixes: c6cfc99648d6 (Cygwin: sys/cpuset.h: add cpuset-specific external 
functions)


Thanks, can you also add an entry to the 3.4.10 release file
(which doesn't exist yet), please?


Done. Here's a link:
https://cygwin.com/pipermail/cygwin/2023-September/254423.html


D'oh again!  Here's the correct link.  Sorry for the continuing noise.
https://cygwin.com/pipermail/cygwin-patches/2023q3/012481.html

..mark


Re: [PATCH] Cygwin: Fix __cpuset_zero_s prototype

2023-09-09 Thread Mark Geisert

Corinna Vinschen wrote:

On Sep  7 22:36, Mark Geisert wrote:

Add a missing "void" to the prototype for __cpuset_zero_s().

Reported-by: Marco Mason 
Addresses: https://cygwin.com/pipermail/cygwin/2023-September/254423.html
Signed-off-by: Mark Geisert 
Fixes: c6cfc99648d6 (Cygwin: sys/cpuset.h: add cpuset-specific external 
functions)


Thanks, can you also add an entry to the 3.4.10 release file
(which doesn't exist yet), please?


Done. Here's a link:
https://cygwin.com/pipermail/cygwin/2023-September/254423.html
Cheers,

..mark


[PATCH] Cygwin: Add relnote to 3.4.10 release file

2023-09-09 Thread Mark Geisert
Document the most recent update to include/sys/cpuset.h.

---
 winsup/cygwin/release/3.4.10 | 5 +
 1 file changed, 5 insertions(+)
 create mode 100644 winsup/cygwin/release/3.4.10

diff --git a/winsup/cygwin/release/3.4.10 b/winsup/cygwin/release/3.4.10
new file mode 100644
index 0..f34b131b3
--- /dev/null
+++ b/winsup/cygwin/release/3.4.10
@@ -0,0 +1,5 @@
+Bug Fixes
+-
+
+- Fix missing term in __cpuset_zero_s() prototoype in sys/cpuset.h.
+  Addresses: https://cygwin.com/pipermail/cygwin/2023-September/254423.html
-- 
2.39.0



[PATCH] Cygwin: Fix __cpuset_zero_s prototype

2023-09-07 Thread Mark Geisert
Add a missing "void" to the prototype for __cpuset_zero_s().

Reported-by: Marco Mason 
Addresses: https://cygwin.com/pipermail/cygwin/2023-September/254423.html
Signed-off-by: Mark Geisert 
Fixes: c6cfc99648d6 (Cygwin: sys/cpuset.h: add cpuset-specific external 
functions)

---
 winsup/cygwin/include/sys/cpuset.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index a5a8fa81e..3d0874880 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -48,7 +48,7 @@ void __cpuset_free (cpu_set_t *);
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
 #define CPU_ZERO_S(siz, set) __cpuset_zero_s (siz, set)
-static __inline
+static __inline void
 __cpuset_zero_s (__size_t siz, cpu_set_t *set)
 {
 #if __GNUC_PREREQ (2, 91)
-- 
2.39.0



[PATCH] Cygwin: Update release/3.4.8 for latest commit

2023-07-12 Thread Mark Geisert
---
 winsup/cygwin/release/3.4.8 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/winsup/cygwin/release/3.4.8 b/winsup/cygwin/release/3.4.8
index d1e34ce3c..3113be8cb 100644
--- a/winsup/cygwin/release/3.4.8
+++ b/winsup/cygwin/release/3.4.8
@@ -3,3 +3,6 @@ Bug Fixes
 
 - Make  safe for c89 compilations.
   Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
+
+- Make gcc-specific code in  compiler-agnostic.
+  Addresses: https://cygwin.com/pipermail/cygwin/2023-July/253927.html
-- 
2.39.0



Re: Where should relnote updates for Cygwin DLL patches be going?

2023-07-11 Thread Mark Geisert

Hi Corinna,

Corinna Vinschen wrote:

On Jul 11 01:05, Mark Geisert wrote:

AIUI for cygwin-3_4-branch they currently go to release/3.4.8.
For the main|master branch they currently go where?


release/3.5.0

An entry there is only necessary if it doesn't get picked for 3.4
anyway.


Ah, that helps me understand.


I hope to get it right the first time ;-).


Is the release model confusing?  If so, can you explain why?


I think I haven't been paying close enough attention and have been doing the 
relnote updates by rote.  But there being two active branches and I 
(understandably) don't determine which releases my commits go to means I should 
wait until they show up on the cvs-patches list, then I will know which relnote 
files to update.  That should work OK, right?


Is it preferred that relnote updates should be separate patches from the code 
updates?
Thanks,

..mark


Where should relnote updates for Cygwin DLL patches be going?

2023-07-11 Thread Mark Geisert

AIUI for cygwin-3_4-branch they currently go to release/3.4.8.
For the main|master branch they currently go where?
I hope to get it right the first time ;-).
Thank you,

..mark


[PATCH v2] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-09 Thread Mark Geisert
The current version of  cannot be compiled by Clang due to
the use of builtin versions of malloc, free, and memset.  Their presence
here was a dubious optimization anyway, so their usage has been
converted to standard library functions.

The use of __builtin_popcountl remains because Clang implements it just
like gcc does.  If/when some other compiler (Rust? Go?) runs into this
issue we can deal with specialized handling then.

The "#include " here to define __inline can be removed since
both of the new includes sub-include it.

Addresses: https://cygwin.com/pipermail/cygwin/2023-July/253927.html
Fixes: 9cc910dd33a5 (Cygwin: Make  safe for c89 compilations)
Signed-off-by: Mark Geisert 

---
 winsup/cygwin/include/sys/cpuset.h | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 0c95134ff..95c777cfb 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -9,7 +9,8 @@ details. */
 #ifndef _SYS_CPUSET_H_
 #define _SYS_CPUSET_H_
 
-#include 
+#include 
+#include 
 
 #ifdef __cplusplus
 extern "C" {
@@ -44,14 +45,14 @@ __cpuset_alloc_size (int num)
 static __inline cpu_set_t *
 __cpuset_alloc (int num)
 {
-  return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
+  return (cpu_set_t *) malloc (CPU_ALLOC_SIZE(num));
 }
 
 #define CPU_FREE(set) __cpuset_free (set)
 static __inline void
 __cpuset_free (cpu_set_t *set)
 {
-  __builtin_free (set);
+  free (set);
 }
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
@@ -59,7 +60,7 @@ __cpuset_free (cpu_set_t *set)
 static __inline void
 __cpuset_zero_s (size_t siz, cpu_set_t *set)
 {
-  (void) __builtin_memset (set, 0, siz);
+  (void) memset (set, 0, siz);
 }
 
 #define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
-- 
2.39.0



Re: [PATCH] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-09 Thread Mark Geisert

Hi all,

Brian Inglis wrote:

On 2023-07-08 15:53, Mark Geisert wrote:

Mark Geisert wrote:
I got tripped up by misspelling and not being able to link clang{,++} programs 
on my test system.  I checked the .o files with objdump: Clang and clang++ both 
support __builtin_popcountl, but they emit code for the Hackers Delight 
algorithm rather than using the single-instruction popcnt.  Sorry for the 
confustion [sic].


That's what I meant - clang 8 "identifies as" gcc 4, and builtin and intrinsic 
function support are almost the same (and fairly close to gcc 11) builtin and 
intrinsic function support.


And as you mentioned, any support for builtins is better than what we can whip up 
off the top of our heads (unless you use HD/2!)


For our purposes, the main differences between clang 8 and current are latest 
language, library, and processor support, but it also supports useful tools like 
the analyzer and formatter, which gcc does not provide.


And it is convenient to be able to run another compiler side by side for 
comparisons without copying files and remoting to another system.


I now understand what you were getting at.  We are in agreement.  Thanks to your 
persistence and everybody elses comments and to my belatedly getting a working 
clang/clang++ build environment, there is a much smaller v2 patch incoming.

Thanks and Regards All,

..mark



Re: [PATCH] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-08 Thread Mark Geisert

Mark Geisert wrote:
[... blah blah ...]

I got tripped up by misspelling and not being able to link clang{,++} programs on 
my test system.  I checked the .o files with objdump: Clang and clang++ both 
support __builtin_popcountl, but they emit code for the Hackers Delight algorithm 
rather than using the single-instruction popcnt.  Sorry for the confustion [sic].


..mark



Re: [PATCH] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-08 Thread Mark Geisert

Brian Inglis wrote:

On 2023-07-07 12:54, Brian Inglis wrote:

On 2023-07-07 03:44, Corinna Vinschen wrote:

Hi Mark,

On Jul  7 00:41, Mark Geisert wrote:

The current version of  cannot be compiled by Clang due to
the use of __builtin* functions.  Their presence here was a dubious
optimization anyway, so their usage has been converted to standard
library functions.  A popcnt (population count of 1 bits in a word)
function is provided here because there isn't one in the standard library
or elsewhere in the Cygwin DLL.


And clang really doesn't provide it?  That's unfortunate.

Do you really think it's not worth to use it if it's available?

You could workaround it like this:


+/* Modern CPUs have popcnt* instructions but the need here is not worth
+ * worrying about builtins or inline assembler for different compilers. */
+static inline int
+__maskpopcnt (__cpu_mask mask)
+{

#if (__GNUC__ >= 4)
  return __builtin_popcountl (mask);


Missed the difference in spelling, but clang supports the same builtin functions 
__builtin_popcount{,l,ll} et. al. or provides *optimized* inline functions if not 
directly available as an instruction on the architecture.


Clang in its current version 16.0.x has __builtin_popcount*, but not in the 
ancient version 8.0.1 that is currently packaged for Cygwin.  I think that's what 
was behind Jon's earlier comment that perhaps we should remove clang from Cygwin 
unless/until somebody can adopt and maintain an up-to-date version.  :-(.


..mark


Re: [PATCH] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-07 Thread Mark Geisert

Hi Corinna,

Corinna Vinschen wrote:

On Jul  7 00:41, Mark Geisert wrote:

The current version of  cannot be compiled by Clang due to
the use of __builtin* functions.  Their presence here was a dubious
optimization anyway, so their usage has been converted to standard
library functions.  A popcnt (population count of 1 bits in a word)
function is provided here because there isn't one in the standard library
or elsewhere in the Cygwin DLL.


And clang really doesn't provide it?  That's unfortunate.

Do you really think it's not worth to use it if it's available?


I don't know for sure.  I'd guess the popcnt op should be optimized if available; 
the others probably don't need it.



You could workaround it like this:


+/* Modern CPUs have popcnt* instructions but the need here is not worth
+ * worrying about builtins or inline assembler for different compilers. */
+static inline int
+__maskpopcnt (__cpu_mask mask)
+{

#if (__GNUC__ >= 4)
  return __builtin_popcountl (mask);
#else

+  int res = 0;
+  unsigned long ulmask = (unsigned long) mask;
+
+  while (ulmask != 0)
+{
+  if (ulmask & 1)
+++res;
+  ulmask >>= 1;
+}
+  return res;

#endif

+}
+


The first version of the patch (unsubmitted) worked something like that, though it 
was a chore figuring out how to tell the difference between gcc and clang.  clang 
#defines __GNUC__ (?!) for example.  I ended up using __GNUC_PREREQ__ with the 
hope clang version numbers stay lower than gcc version numbers.  Has to be a 
better way than that.


On the other hand, one compilation with clang or clang++, I forget which, and with 
some optimization flag, recognized the 'while' loop in that function and turned it 
into the Hackers Delight algorithm for popcnt in ~20 instructions and no loop.


TL;DR let me ponder this over the weekend.
Thanks for listening,

..mark



[PATCH] Cygwin: Make gcc-specific code in compiler-agnostic

2023-07-07 Thread Mark Geisert
The current version of  cannot be compiled by Clang due to
the use of __builtin* functions.  Their presence here was a dubious
optimization anyway, so their usage has been converted to standard
library functions.  A popcnt (population count of 1 bits in a word)
function is provided here because there isn't one in the standard library
or elsewhere in the Cygwin DLL.

The "#include " here to define __inline can be removed since
both of the new includes sub-include it.

Addresses: https://cygwin.com/pipermail/cygwin/2023-July/253927.html
Fixes: 9cc910dd33a5 (Cygwin: Make  safe for c89 compilations)
Signed-off-by: Mark Geisert 

---
 winsup/cygwin/include/sys/cpuset.h | 28 +++-
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 0c95134ff..f76e788d5 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -9,7 +9,8 @@ details. */
 #ifndef _SYS_CPUSET_H_
 #define _SYS_CPUSET_H_
 
-#include 
+#include 
+#include 
 
 #ifdef __cplusplus
 extern "C" {
@@ -31,6 +32,23 @@ typedef struct
 #if __GNU_VISIBLE
 int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 
+/* Modern CPUs have popcnt* instructions but the need here is not worth
+ * worrying about builtins or inline assembler for different compilers. */ 
+static inline int
+__maskpopcnt (__cpu_mask mask)
+{
+  int res = 0;
+  unsigned long ulmask = (unsigned long) mask;
+
+  while (ulmask != 0)
+{
+  if (ulmask & 1)
+++res;
+  ulmask >>= 1;
+}
+  return res;
+}
+
 /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
Allocations are padded such that full-word operations can be done easily. */
 #define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)
@@ -44,14 +62,14 @@ __cpuset_alloc_size (int num)
 static __inline cpu_set_t *
 __cpuset_alloc (int num)
 {
-  return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
+  return (cpu_set_t *) malloc (CPU_ALLOC_SIZE(num));
 }
 
 #define CPU_FREE(set) __cpuset_free (set)
 static __inline void
 __cpuset_free (cpu_set_t *set)
 {
-  __builtin_free (set);
+  free (set);
 }
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
@@ -59,7 +77,7 @@ __cpuset_free (cpu_set_t *set)
 static __inline void
 __cpuset_zero_s (size_t siz, cpu_set_t *set)
 {
-  (void) __builtin_memset (set, 0, siz);
+  (void) memset (set, 0, siz);
 }
 
 #define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
@@ -94,7 +112,7 @@ __cpuset_count_s (size_t siz, cpu_set_t *set)
 {
   int i, res = 0;
   for (i = 0; i < siz / sizeof (__cpu_mask); i++)
-res += __builtin_popcountl ((set)->__bits[i]);
+res += __maskpopcnt ((set)->__bits[i]);
   return res;
 }
 
-- 
2.39.0



Re: [PATCH v2] Cygwin: Make safe for c89 compilations

2023-07-04 Thread Mark Geisert

Corinna Vinschen wrote:

On Jul  4 16:33, Corinna Vinschen wrote:

On Jul  3 17:51, Mark Geisert wrote:

Four modifications to include/sys/cpuset.h:
* Change C++-style comments to C-style also supported by C++
* Change "inline" to "__inline" on code lines
* Add "#include " to make sure __inline is defined
* Don't declare loop variables on for-loop init clauses

Tested by first reproducing the reported issue with home-grown test
programs by compiling with gcc option "-std=c89", then compiling again
using the modified . Other "-std=" options tested too.

Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
Fixes: 315e5fbd99ec ("Cygwin: Fix type mismatch on sys/cpuset.h")
Signed-off-by: Mark Geisert 

---
  winsup/cygwin/include/sys/cpuset.h | 49 --
  winsup/cygwin/release/3.4.7|  3 ++
  2 files changed, 30 insertions(+), 22 deletions(-)


Pushed.


FYI, I missed to notice that you added the release message to the
already existing 3.4.7 release.  I moved it into a new file for 3.4.8.


Thank you for cleaning up after my goof on the version.
Cheers & Regards,

..mark


[PATCH v2] Cygwin: Make safe for c89 compilations

2023-07-03 Thread Mark Geisert
Four modifications to include/sys/cpuset.h:
* Change C++-style comments to C-style also supported by C++
* Change "inline" to "__inline" on code lines
* Add "#include " to make sure __inline is defined
* Don't declare loop variables on for-loop init clauses

Tested by first reproducing the reported issue with home-grown test
programs by compiling with gcc option "-std=c89", then compiling again
using the modified . Other "-std=" options tested too.

Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
Fixes: 315e5fbd99ec ("Cygwin: Fix type mismatch on sys/cpuset.h")
Signed-off-by: Mark Geisert 

---
 winsup/cygwin/include/sys/cpuset.h | 49 --
 winsup/cygwin/release/3.4.7|  3 ++
 2 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index d83359fdf..0c95134ff 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -9,14 +9,16 @@ details. */
 #ifndef _SYS_CPUSET_H_
 #define _SYS_CPUSET_H_
 
+#include 
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef __SIZE_TYPE__ __cpu_mask;
-#define __CPU_SETSIZE 1024  // maximum number of logical processors tracked
-#define __NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
-#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  // maximum group number
+#define __CPU_SETSIZE 1024  /* maximum number of logical processors tracked */
+#define __NCPUBITS (8 * sizeof (__cpu_mask))  /* max size of processor group */
+#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  /* maximum group number */
 
 #define __CPUELT(cpu)  ((cpu) / __NCPUBITS)
 #define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
@@ -32,21 +34,21 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
Allocations are padded such that full-word operations can be done easily. */
 #define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)
-static inline size_t
+static __inline size_t
 __cpuset_alloc_size (int num)
 {
   return (size_t) (((num + __NCPUBITS - 1) / __NCPUBITS) * sizeof 
(__cpu_mask));
 }
 
 #define CPU_ALLOC(num) __cpuset_alloc (num)
-static inline cpu_set_t *
+static __inline cpu_set_t *
 __cpuset_alloc (int num)
 {
   return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
 }
 
 #define CPU_FREE(set) __cpuset_free (set)
-static inline void
+static __inline void
 __cpuset_free (cpu_set_t *set)
 {
   __builtin_free (set);
@@ -54,14 +56,14 @@ __cpuset_free (cpu_set_t *set)
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
 #define CPU_ZERO_S(siz, set) __cpuset_zero_s (siz, set)
-static inline void
+static __inline void
 __cpuset_zero_s (size_t siz, cpu_set_t *set)
 {
   (void) __builtin_memset (set, 0, siz);
 }
 
 #define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
-static inline void
+static __inline void
 __cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
 {
   if (cpu >= 0 && cpu < 8 * siz)
@@ -69,7 +71,7 @@ __cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_CLR_S(cpu, siz, set) __cpuset_clr_s (cpu, siz, set)
-static inline void
+static __inline void
 __cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
 {
   if (cpu >= 0 && cpu < 8 * siz)
@@ -77,7 +79,7 @@ __cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_ISSET_S(cpu, siz, set) __cpuset_isset_s (cpu, siz, set)
-static inline int
+static __inline int
 __cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
 {
   int res = 0;
@@ -87,45 +89,48 @@ __cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_COUNT_S(siz, set) __cpuset_count_s (siz, set)
-static inline int
+static __inline int
 __cpuset_count_s (size_t siz, cpu_set_t *set)
 {
-  int res = 0;
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i, res = 0;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 res += __builtin_popcountl ((set)->__bits[i]);
   return res;
 }
 
 #define CPU_AND_S(siz, dst, src1, src2) __cpuset_and_s (siz, dst, src1, src2)
-static inline void
+static __inline void
 __cpuset_and_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
 {
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 (dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
 }
 
 #define CPU_OR_S(siz, dst, src1, src2) __cpuset_or_s (siz, dst, src1, src2)
-static inline void
+static __inline void
 __cpuset_or_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
 {
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 (dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
 }
 
 #define CPU

Re: [PATCH] Cygwin: Make safe for c89 compilations

2023-07-03 Thread Mark Geisert

Hi Corinna,

Corinna Vinschen wrote:

On Jul  3 02:27, Mark Geisert wrote:

Brian Inglis wrote:

On 2023-07-03 00:17, Mark Geisert wrote:

Three modifications to include/sys/cpuset.h:
* Change C++-style comments to C-style also supported by C++
* Change "inline" to "__inline" on code lines
* Don't declare loop variables on for-loop init clauses

Tested by first reproducing the reported issue with home-grown test
programs by compiling with gcc option "-std=c89", then compiling again
using the modified . Other "-std=" options tested too.

Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
Fixes: 315e5fbd99ec ("Cygwin: Fix type mismatch on sys/cpuset.h")


Signed-off-by?


Eh, I was unsure if submitter or reviewer provides this.  Submitter it is.


Does this patch need __inline defined e.g.

    +#include 

did you perhaps include this directly in your test cases?


-static inline size_t
+static __inline size_t

...


No, not directly.  The test case with the shortest list of #includes has:
#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 

So it's apparently defined by one of those or some sub-include.  But indeed
it's not safe to depend on that so I will try harder to figure out what
other occurrences of __inline in the Cygwin source tree are depending on for
the definition.


In this specific case  includes .  I figure one can't depend 
on what's included, or in what order.  So as Brian suggested, I've added an 
"#include ".  Not every site of __inline within the Cygwin source 
tree does this; I guess those will be fixed if/when reported as a problem.


v2 patch for 3.4.7 is on its way in.  If it's OK I'll then submit it for 3.3.6.
Thanks all for the review comments,

..mark





Re: [PATCH] Cygwin: Make safe for c89 compilations

2023-07-03 Thread Mark Geisert

Hi Brian,

Brian Inglis wrote:

On 2023-07-03 00:17, Mark Geisert wrote:

Three modifications to include/sys/cpuset.h:
* Change C++-style comments to C-style also supported by C++
* Change "inline" to "__inline" on code lines
* Don't declare loop variables on for-loop init clauses

Tested by first reproducing the reported issue with home-grown test
programs by compiling with gcc option "-std=c89", then compiling again
using the modified . Other "-std=" options tested too.

Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
Fixes: 315e5fbd99ec ("Cygwin: Fix type mismatch on sys/cpuset.h")

---
  winsup/cygwin/include/sys/cpuset.h | 47 --
  winsup/cygwin/release/3.4.7    |  3 ++
  2 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h

index d83359fdf..01576b041 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -14,9 +14,9 @@ extern "C" {
  #endif
  typedef __SIZE_TYPE__ __cpu_mask;
-#define __CPU_SETSIZE 1024  // maximum number of logical processors tracked
-#define __NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
-#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  // maximum group number
+#define __CPU_SETSIZE 1024  /* maximum number of logical processors tracked */
+#define __NCPUBITS (8 * sizeof (__cpu_mask))  /* max size of processor group */
+#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  /* maximum group number */
  #define __CPUELT(cpu)  ((cpu) / __NCPUBITS)
  #define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
@@ -32,21 +32,21 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
  /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
 Allocations are padded such that full-word operations can be done easily. 
*/
  #define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)


Does this patch need __inline defined e.g.

   +#include 

did you perhaps include this directly in your test cases?


-static inline size_t
+static __inline size_t

...


No, not directly.  The test case with the shortest list of #includes has:
#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 
#include 

So it's apparently defined by one of those or some sub-include.  But indeed it's 
not safe to depend on that so I will try harder to figure out what other 
occurrences of __inline in the Cygwin source tree are depending on for the definition.

Thanks,

..mark


[PATCH] Cygwin: Make safe for c89 compilations

2023-07-03 Thread Mark Geisert
Three modifications to include/sys/cpuset.h:
* Change C++-style comments to C-style also supported by C++
* Change "inline" to "__inline" on code lines
* Don't declare loop variables on for-loop init clauses

Tested by first reproducing the reported issue with home-grown test
programs by compiling with gcc option "-std=c89", then compiling again
using the modified . Other "-std=" options tested too.

Addresses: https://cygwin.com/pipermail/cygwin-patches/2023q3/012308.html
Fixes: 315e5fbd99ec ("Cygwin: Fix type mismatch on sys/cpuset.h")

---
 winsup/cygwin/include/sys/cpuset.h | 47 --
 winsup/cygwin/release/3.4.7|  3 ++
 2 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index d83359fdf..01576b041 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -14,9 +14,9 @@ extern "C" {
 #endif
 
 typedef __SIZE_TYPE__ __cpu_mask;
-#define __CPU_SETSIZE 1024  // maximum number of logical processors tracked
-#define __NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
-#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  // maximum group number
+#define __CPU_SETSIZE 1024  /* maximum number of logical processors tracked */
+#define __NCPUBITS (8 * sizeof (__cpu_mask))  /* max size of processor group */
+#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  /* maximum group number */
 
 #define __CPUELT(cpu)  ((cpu) / __NCPUBITS)
 #define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
@@ -32,21 +32,21 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
Allocations are padded such that full-word operations can be done easily. */
 #define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)
-static inline size_t
+static __inline size_t
 __cpuset_alloc_size (int num)
 {
   return (size_t) (((num + __NCPUBITS - 1) / __NCPUBITS) * sizeof 
(__cpu_mask));
 }
 
 #define CPU_ALLOC(num) __cpuset_alloc (num)
-static inline cpu_set_t *
+static __inline cpu_set_t *
 __cpuset_alloc (int num)
 {
   return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
 }
 
 #define CPU_FREE(set) __cpuset_free (set)
-static inline void
+static __inline void
 __cpuset_free (cpu_set_t *set)
 {
   __builtin_free (set);
@@ -54,14 +54,14 @@ __cpuset_free (cpu_set_t *set)
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
 #define CPU_ZERO_S(siz, set) __cpuset_zero_s (siz, set)
-static inline void
+static __inline void
 __cpuset_zero_s (size_t siz, cpu_set_t *set)
 {
   (void) __builtin_memset (set, 0, siz);
 }
 
 #define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
-static inline void
+static __inline void
 __cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
 {
   if (cpu >= 0 && cpu < 8 * siz)
@@ -69,7 +69,7 @@ __cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_CLR_S(cpu, siz, set) __cpuset_clr_s (cpu, siz, set)
-static inline void
+static __inline void
 __cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
 {
   if (cpu >= 0 && cpu < 8 * siz)
@@ -77,7 +77,7 @@ __cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_ISSET_S(cpu, siz, set) __cpuset_isset_s (cpu, siz, set)
-static inline int
+static __inline int
 __cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
 {
   int res = 0;
@@ -87,45 +87,48 @@ __cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
 }
 
 #define CPU_COUNT_S(siz, set) __cpuset_count_s (siz, set)
-static inline int
+static __inline int
 __cpuset_count_s (size_t siz, cpu_set_t *set)
 {
-  int res = 0;
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i, res = 0;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 res += __builtin_popcountl ((set)->__bits[i]);
   return res;
 }
 
 #define CPU_AND_S(siz, dst, src1, src2) __cpuset_and_s (siz, dst, src1, src2)
-static inline void
+static __inline void
 __cpuset_and_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
 {
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 (dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
 }
 
 #define CPU_OR_S(siz, dst, src1, src2) __cpuset_or_s (siz, dst, src1, src2)
-static inline void
+static __inline void
 __cpuset_or_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
 {
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 (dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
 }
 
 #define CPU_XOR_S(siz, dst, src1, src2) __cpuset_xor_s (siz, dst, src1, src2)
-static inline void
+static __inline void
 __cpuset_xor_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
 {
-  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+  int i;
+  for (i = 0; i < siz / sizeof (__cpu_mask); i++)
 

Re: [PATCH v2] Cygwin: Fix type mismatch on sys/cpuset.h

2023-07-03 Thread Mark Geisert

Mark Geisert wrote:
[...]

Thanks for the report and investigations.  I'll address this shortly.


A candidate patch for 3.4.7 is incoming.  If it passes muster I'll fire off a 
patch for 3.3.6.  I don't know why I'm using military terminology.  Independence 
Day soon in the US, I guess.

Cheers,

..mark


Re: [PATCH v2] Cygwin: Fix type mismatch on sys/cpuset.h

2023-07-02 Thread Mark Geisert

Hi all,

Brian Inglis wrote:

On 2023-07-01 08:20, Jon Turney wrote:

On 14/03/2023 08:56, Mark Geisert wrote:

Addresses https://cygwin.com/pipermail/cygwin/2023-March/253220.html

Take the opportunity to follow FreeBSD's and Linux's lead in recasting
macro inline code as calls to static inline functions.  This allows the
macros to be type-safe.  In addition, added a lower bound check to the
functions that use a cpu number to avoid a potential buffer underrun on
a bad argument.  h/t to Corinna for the advice on recasting.

Fixes: 362b98b49af5 ("Cygwin: Implement CPU_SET(3) macros")


There's been a couple of reports that this leads to compilation failures when 
this header is included in -std=c89 mode.

Solutions are probably something like:
* Use __inline__ rather than inline
* Don't use initial declaration inside the for loop's init-statement
e.g. https://github.com/tinyproxy/tinyproxy/issues/499


/usr/include/sys/cdefs.h appears to support using __inline instead of __inline__ 
or inline, and is included many places __inline is used: it appears to be 
necessary, but may not be sufficient.


Thanks for the report and investigations.  I'll address this shortly.

..mark


[PATCH v2] Cygwin: Fix type mismatch on sys/cpuset.h

2023-03-14 Thread Mark Geisert
Addresses https://cygwin.com/pipermail/cygwin/2023-March/253220.html

Take the opportunity to follow FreeBSD's and Linux's lead in recasting
macro inline code as calls to static inline functions.  This allows the
macros to be type-safe.  In addition, added a lower bound check to the
functions that use a cpu number to avoid a potential buffer underrun on
a bad argument.  h/t to Corinna for the advice on recasting.

Fixes: 362b98b49af5 ("Cygwin: Implement CPU_SET(3) macros")

---
 winsup/cygwin/include/sys/cpuset.h | 138 -
 winsup/cygwin/release/3.4.7|   5 ++
 2 files changed, 101 insertions(+), 42 deletions(-)
 create mode 100644 winsup/cygwin/release/3.4.7

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 572565165..d83359fdf 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -31,50 +31,104 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 
 /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
Allocations are padded such that full-word operations can be done easily. */
-#define CPU_ALLOC_SIZE(num) ((num+__NCPUBITS-1) / __NCPUBITS) * sizeof 
(__cpu_mask)
-#define CPU_ALLOC(num)  __builtin_malloc (CPU_ALLOC_SIZE(num))
-#define CPU_FREE(set)   __builtin_free (set)
+#define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)
+static inline size_t
+__cpuset_alloc_size (int num)
+{
+  return (size_t) (((num + __NCPUBITS - 1) / __NCPUBITS) * sizeof 
(__cpu_mask));
+}
+
+#define CPU_ALLOC(num) __cpuset_alloc (num)
+static inline cpu_set_t *
+__cpuset_alloc (int num)
+{
+  return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
+}
+
+#define CPU_FREE(set) __cpuset_free (set)
+static inline void
+__cpuset_free (cpu_set_t *set)
+{
+  __builtin_free (set);
+}
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
-#define CPU_ZERO_S(siz, set)__builtin_memset (set, 0, siz)
-
-#define CPU_SET_S(cpu,siz,set) \
-   if (cpu < 8 * siz) \
- (set)->__bits[__CPUELT(cpu)] |= __CPUMASK(cpu);
-
-#define CPU_CLR_S(cpu,siz,set) \
-   if (cpu < 8 * siz) \
- (set)->__bits[__CPUELT(cpu)] &= ~(__CPUMASK(cpu));
-
-#define CPU_ISSET_S(cpu,siz,set) \
-  ({int res = 0; \
-   if (cpu < 8 * siz) \
- res = !!((set)->__bits[__CPUELT(cpu)] & __CPUMASK(cpu)); \
-   res;})
-
-#define CPU_COUNT_S(siz, set) \
-  ({int tot = 0;\
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- tot += __builtin_popcountl ((set)->__bits[i]); \
-   tot;})
-
-#define CPU_AND_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
-
-#define CPU_OR_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
-
-#define CPU_XOR_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] ^ (src2)->__bits[i];
-
-#define CPU_EQUAL_S(siz, src1, src2) \
-  ({int res = 1; \
-   for (int i = 0; res && i < siz / sizeof (__cpu_mask); i++) \
- res &= (src1)->__bits[i] == (src2)->__bits[i]; \
-   res;})
+#define CPU_ZERO_S(siz, set) __cpuset_zero_s (siz, set)
+static inline void
+__cpuset_zero_s (size_t siz, cpu_set_t *set)
+{
+  (void) __builtin_memset (set, 0, siz);
+}
+
+#define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
+static inline void
+__cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  if (cpu >= 0 && cpu < 8 * siz)
+(set)->__bits[__CPUELT(cpu)] |= __CPUMASK(cpu);
+}
+
+#define CPU_CLR_S(cpu, siz, set) __cpuset_clr_s (cpu, siz, set)
+static inline void
+__cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  if (cpu >= 0 && cpu < 8 * siz)
+(set)->__bits[__CPUELT(cpu)] &= ~(__CPUMASK(cpu));
+}
+
+#define CPU_ISSET_S(cpu, siz, set) __cpuset_isset_s (cpu, siz, set)
+static inline int
+__cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  int res = 0;
+  if (cpu >= 0 && cpu < 8 * siz)
+res = !!((set)->__bits[__CPUELT(cpu)] & __CPUMASK(cpu));
+  return res;
+}
+
+#define CPU_COUNT_S(siz, set) __cpuset_count_s (siz, set)
+static inline int
+__cpuset_count_s (size_t siz, cpu_set_t *set)
+{
+  int res = 0;
+  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+res += __builtin_popcountl ((set)->__bits[i]);
+  return res;
+}
+
+#define CPU_AND_S(siz, dst, src1, src2) __cpuset_and_s (siz, dst, src1, src2)
+static inline void
+__cpuset_and_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
+{
+  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+(dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
+}
+
+#define CPU_OR_S(siz, dst, src1, src2) __cpuset_or_s (siz, dst, src1, src2)
+static inline void
+__cpuset_or_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, 

[PATCH] Cygwin: Fix type mismatch on sys/cpuset.h -- relnote 3.4.6

2023-03-11 Thread Mark Geisert
---
 winsup/cygwin/release/3.4.6 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/winsup/cygwin/release/3.4.6 b/winsup/cygwin/release/3.4.6
index ccc168a95..ed124ed37 100644
--- a/winsup/cygwin/release/3.4.6
+++ b/winsup/cygwin/release/3.4.6
@@ -12,3 +12,6 @@ Addresses: 
https://cygwin.com/pipermail/cygwin/2023-February/253037.html
 
 Don't accidentally drop the default ACEs when chmod'ing directories.
 Addresses: https://cygwin.com/pipermail/cygwin/2023-February/253037.html
+
+Fix CPU_SET(3) macro type mismatch by making the macros type-safe.
+Addresses https://cygwin.com/pipermail/cygwin/2023-March/253220.html
-- 
2.39.0



[PATCH] Cygwin: Fix type mismatch on sys/cpuset.h

2023-03-10 Thread Mark Geisert
Addresses https://cygwin.com/pipermail/cygwin/2023-March/253220.html

Take the opportunity to follow FreeBSD's and Linux's lead in recasting
macro inline code as calls to static inline functions.  This allows the
macros to be type-safe.  In addition, added a lower bound check to the
functions that use a cpu number to avoid a potential buffer underrun on
a bad argument.  h/t to Corinna for the advice on recasting.

---
 winsup/cygwin/include/sys/cpuset.h | 138 -
 1 file changed, 96 insertions(+), 42 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 572565165..d83359fdf 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -31,50 +31,104 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 
 /* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
Allocations are padded such that full-word operations can be done easily. */
-#define CPU_ALLOC_SIZE(num) ((num+__NCPUBITS-1) / __NCPUBITS) * sizeof 
(__cpu_mask)
-#define CPU_ALLOC(num)  __builtin_malloc (CPU_ALLOC_SIZE(num))
-#define CPU_FREE(set)   __builtin_free (set)
+#define CPU_ALLOC_SIZE(num) __cpuset_alloc_size (num)
+static inline size_t
+__cpuset_alloc_size (int num)
+{
+  return (size_t) (((num + __NCPUBITS - 1) / __NCPUBITS) * sizeof 
(__cpu_mask));
+}
+
+#define CPU_ALLOC(num) __cpuset_alloc (num)
+static inline cpu_set_t *
+__cpuset_alloc (int num)
+{
+  return (cpu_set_t *) __builtin_malloc (CPU_ALLOC_SIZE(num));
+}
+
+#define CPU_FREE(set) __cpuset_free (set)
+static inline void
+__cpuset_free (cpu_set_t *set)
+{
+  __builtin_free (set);
+}
 
 /* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
-#define CPU_ZERO_S(siz, set)__builtin_memset (set, 0, siz)
-
-#define CPU_SET_S(cpu,siz,set) \
-   if (cpu < 8 * siz) \
- (set)->__bits[__CPUELT(cpu)] |= __CPUMASK(cpu);
-
-#define CPU_CLR_S(cpu,siz,set) \
-   if (cpu < 8 * siz) \
- (set)->__bits[__CPUELT(cpu)] &= ~(__CPUMASK(cpu));
-
-#define CPU_ISSET_S(cpu,siz,set) \
-  ({int res = 0; \
-   if (cpu < 8 * siz) \
- res = !!((set)->__bits[__CPUELT(cpu)] & __CPUMASK(cpu)); \
-   res;})
-
-#define CPU_COUNT_S(siz, set) \
-  ({int tot = 0;\
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- tot += __builtin_popcountl ((set)->__bits[i]); \
-   tot;})
-
-#define CPU_AND_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
-
-#define CPU_OR_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
-
-#define CPU_XOR_S(siz, dst, src1, src2) \
-   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
- (dst)->__bits[i] = (src1)->__bits[i] ^ (src2)->__bits[i];
-
-#define CPU_EQUAL_S(siz, src1, src2) \
-  ({int res = 1; \
-   for (int i = 0; res && i < siz / sizeof (__cpu_mask); i++) \
- res &= (src1)->__bits[i] == (src2)->__bits[i]; \
-   res;})
+#define CPU_ZERO_S(siz, set) __cpuset_zero_s (siz, set)
+static inline void
+__cpuset_zero_s (size_t siz, cpu_set_t *set)
+{
+  (void) __builtin_memset (set, 0, siz);
+}
+
+#define CPU_SET_S(cpu, siz, set) __cpuset_set_s (cpu, siz, set)
+static inline void
+__cpuset_set_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  if (cpu >= 0 && cpu < 8 * siz)
+(set)->__bits[__CPUELT(cpu)] |= __CPUMASK(cpu);
+}
+
+#define CPU_CLR_S(cpu, siz, set) __cpuset_clr_s (cpu, siz, set)
+static inline void
+__cpuset_clr_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  if (cpu >= 0 && cpu < 8 * siz)
+(set)->__bits[__CPUELT(cpu)] &= ~(__CPUMASK(cpu));
+}
+
+#define CPU_ISSET_S(cpu, siz, set) __cpuset_isset_s (cpu, siz, set)
+static inline int
+__cpuset_isset_s (int cpu, size_t siz, cpu_set_t *set)
+{
+  int res = 0;
+  if (cpu >= 0 && cpu < 8 * siz)
+res = !!((set)->__bits[__CPUELT(cpu)] & __CPUMASK(cpu));
+  return res;
+}
+
+#define CPU_COUNT_S(siz, set) __cpuset_count_s (siz, set)
+static inline int
+__cpuset_count_s (size_t siz, cpu_set_t *set)
+{
+  int res = 0;
+  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+res += __builtin_popcountl ((set)->__bits[i]);
+  return res;
+}
+
+#define CPU_AND_S(siz, dst, src1, src2) __cpuset_and_s (siz, dst, src1, src2)
+static inline void
+__cpuset_and_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
+{
+  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+(dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
+}
+
+#define CPU_OR_S(siz, dst, src1, src2) __cpuset_or_s (siz, dst, src1, src2)
+static inline void
+__cpuset_or_s (size_t siz, cpu_set_t *dst, cpu_set_t *src1, cpu_set_t *src2)
+{
+  for (int i = 0; i < siz / sizeof (__cpu_mask); i++)
+(dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
+}
+
+#define 

Re: type mismatch on cpuset.h

2023-03-07 Thread Mark Geisert

[Redirected here from the main mailing list...]

Hi Corinna,

Corinna Vinschen via Cygwin wrote:

Hi Mark,

On Mar  6 07:57, Marco Atzeri via Cygwin wrote:

Hi,

building latest gdal I noticed a type mismatch, that forced me to build
with "-fpermissive"

on /usr/include/sys/cpuset.h

  #define CPU_ALLOC(num)  __builtin_malloc (CPU_ALLOC_SIZE(num))


but on
https://linux.die.net/man/3/cpu_alloc

  cpu_set_t *CPU_ALLOC(int num_cpus)


so void* versus cpu_set_t*


Marco is correct.  cpuset.h was your pet project a while back.  Would
you like to pick it up?  Maybe we should convert all the macros into
type-safe inline functions, or macros calling type-safe (inline)
functions, as on Linux as well as on BSD?


As far as I can tell from online docs, the CPU_SET(3) macros are still macros on 
Linux, though they are documented with prototypes as if they were functions.  I 
don't immediately see a need to change our cpuset.h for this.


I'm also uncertain what exactly you mean by "type-safe" in this context.  Could 
you please give me an example for one of the macros?


I desk-checked all the macros vs their prototypes and I believe CPU_ALLOC that 
Marco ran into is the only faulty one.  It could be fixed with a cast.  CPU_FREE's 
result is void so I should make sure __builtin_free() corresponds. 
CPU_ALLOC_SIZE's result is size_t and I believe the macro is correct as-is because 
it is an expression using untyped integers and sizeof()s, the latter are 
size_t-returning.


The other few macros that return results return int, and those are precisely the 
ones whose inline code uses an int variable to accumulate a result.


If there is some other consideration I'm not seeing, e.g. readability, please let 
me know.  Otherwise I don't really see a need for changes here (modulo casting 
return values properly where needed).


..mark


[PATCH] Cygwin: Have gmondump support ssp-generated gmon.out

2022-06-08 Thread Mark Geisert
Cygwin tool ssp generates gmon.out files with different address
resolution than other tools do. Two address bytes per bucket rather than
the usual four address bytes. Gprof can deal with the difference but
gmondump can't because the latter's gmon.out header validation fails.

- Remove the offending portion of the header validation code.
- Make sure all code can handle differing address resolutions.
- Display address resolution in verbose data dumps.
- Change "rawarc" to "struct rawarc" in certain sizeof expressions to
  avoid buffer overrun faults.
- When "-v" (verbose) is specified, note when there is missing bucket
  data or rawarc data.

---
 winsup/utils/gmondump.c | 35 ++-
 1 file changed, 22 insertions(+), 13 deletions(-)

diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
index 2d29e826d..16b99594a 100644
--- a/winsup/utils/gmondump.c
+++ b/winsup/utils/gmondump.c
@@ -103,6 +103,7 @@ error (int geterrno, const char *fmt, ...)
 void
 gmondump1 (char *filename)
 {
+  intaddrincr;
   ushort*bucket = NULL;
   intfd;
   struct gmonhdr hdr;
@@ -134,16 +135,15 @@ gmondump1 (char *filename)
   if (hdr.lpc >= hdr.hpc)
 goto notgmon;
   numbuckets = (hdr.ncnt - sizeof (hdr)) / sizeof (short);
-  if (numbuckets != (hdr.hpc - hdr.lpc) / 4)
-goto notgmon;
+  addrincr = (hdr.hpc - hdr.lpc) / numbuckets;
   numrawarcs = 0;
   if (stat.st_size != hdr.ncnt)
 {
   numrawarcs = stat.st_size - hdr.ncnt;
-  if (numrawarcs !=
-  (int) sizeof (rawarc) * (numrawarcs / (int) sizeof (rawarc)))
+  if (numrawarcs != (int) sizeof (struct rawarc) *
+(numrawarcs / (int) sizeof (struct rawarc)))
 goto notgmon;
-  numrawarcs /= (int) sizeof (rawarc);
+  numrawarcs /= (int) sizeof (struct rawarc);
 }
 
   /* Looks good, so read and display the profiling info. */
@@ -162,7 +162,8 @@ gmondump1 (char *filename)
 
   note ("file %s, gmon version 0x%x, sample rate %d\n",
 filename, hdr.version, hdr.profrate);
-  note ("  address range %p..%p\n", hdr.lpc, hdr.hpc);
+  note ("  address range %p..%p, address increment %d/bucket\n",
+hdr.lpc, hdr.hpc, addrincr);
   note ("  numbuckets %d, hitbuckets %d, hitcount %d, numrawarcs %d\n",
 numbuckets, hitbuckets, hitcount, numrawarcs);
 
@@ -171,27 +172,31 @@ gmondump1 (char *filename)
 {
   if (hitbuckets)
 note ("  bucket data follows...\n");
+  else
+note ("  no bucket data present\n");
   char *addr = (char *) hdr.lpc;
-  int   incr = (hdr.hpc - hdr.lpc) / numbuckets;
-  for (res = 0; res < numbuckets; ++bucket, ++res, addr += incr)
+  for (res = 0; res < numbuckets; ++bucket, ++res, addr += addrincr)
 if (*bucket)
   note ("address %p, hitcount %d\n", addr, *bucket);
   bucket -= numbuckets;
 
   if (numrawarcs)
 {
-  rawarc = (struct rawarc *) calloc (numrawarcs, sizeof (rawarc));
-  res = read (fd, rawarc, numrawarcs * (int) sizeof (rawarc));
-  if (res != numrawarcs * (int) sizeof (rawarc))
+  rawarc = (struct rawarc *) calloc (numrawarcs,
+ sizeof (struct rawarc));
+  res = read (fd, rawarc, numrawarcs * (int) sizeof (struct rawarc));
+  if (res != numrawarcs * (int) sizeof (struct rawarc))
 error (0, "unable to read rawarc data");
   note ("  rawarc data follows...\n");
   for (res = 0; res < numrawarcs; ++rawarc, ++res)
 note ("from %p, self %p, count %d\n",
   rawarc->raw_frompc, rawarc->raw_selfpc, rawarc->raw_count);
+  rawarc -= numrawarcs;
 }
+  else
+note ("  no rawarc data present\n");
 }
 
-  note ("\n");
   if (0)
 {
 notgmon:
@@ -261,7 +266,11 @@ main(int argc, char **argv)
 usage1 (ofile);
 
   for (int i = optind; i < argc; i++)
-gmondump1 (argv[i]);
+{
+  gmondump1 (argv[i]);
+  if ((i + 1) < argc)
+note ("\n");
+}
 
   return 0;
 }
-- 
2.36.1



[PATCH] Cygwin: Fix "0x0x" in gmondump and ssp man pages

2022-04-21 Thread Mark Geisert
A recent patch fixed gmondump to stop printing "0x0x" as an address
prefix.  It turns out the Cygwin User's Guide and the gmondump and
ssp man pages (all from utils.xml) have examples of the same error.

---
 winsup/cygwin/release/3.3.5 | 2 +-
 winsup/doc/utils.xml| 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/release/3.3.5 b/winsup/cygwin/release/3.3.5
index f0a834039..049d19b8c 100644
--- a/winsup/cygwin/release/3.3.5
+++ b/winsup/cygwin/release/3.3.5
@@ -42,7 +42,7 @@ Bug Fixes
   Addresses: https://cygwin.com/pipermail/cygwin/2022-March/251022.html
 
 - Fix a formatting problem in gmondump where all displayed addresses are
-  mistakenly prefixed with "0x0x".
+  mistakenly prefixed with "0x0x". Fix man pages for gmondump and ssp.
 
 - Fix crash on pty master close in Windows 7.
   Addresses: https://cygwin.com/pipermail/cygwin/2022-March/251162.html
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 0b9e38549..895988037 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -846,7 +846,7 @@ line separates the ACLs for each file.
 
 $ gmondump gmon.out.21900.zstd.exe
 file gmon.out.21900.zstd.exe, gmon version 0x51879, sample rate 100
-  address range 0x0x100401000..0x0x1004cc668
+  address range 0x100401000..0x1004cc668
   numbuckets 208282, hitbuckets 1199, hitcount 12124, numrawarcs 0
 
 
@@ -2951,7 +2951,7 @@ Idx Name  Size  VMA   LMA   File off  
Algn
   section and the VMA of the section after it (sections are usually
   contiguous; you can also add the Size to the VMA to get the end address).
   In this case, the VMA is 0x61001000 and the ending address is either
-  0x6108 (start of .data method) or 0x0x6107fa00 (VMA+Size method). 

+  0x6108 (start of .data method) or 0x6107fa00 (VMA+Size method). 

 
  There are two basic ways to use SSP - either profiling a whole
   program, or selectively profiling parts of the program. 
-- 
2.36.0



Re: [PATCH] Cygwin: Fix gmondump formatting goofs

2022-03-16 Thread Mark Geisert

Corinna Vinschen wrote:

On Mar 14 17:47, Mark Geisert wrote:

The rewrite of %X to %p was malhandled.  Fix that/them.


This should probably go into 3.3 as well.  Care to write a
matching entry for the release/3.3.5 file?

Done, under separate patch
https://cygwin.com/pipermail/cygwin-patches/2022q1/011851.html
Cheers,

..mark


[PATCH] Cygwin: document recent gmondump formatting fix

2022-03-16 Thread Mark Geisert
---
 winsup/cygwin/release/3.3.5 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/winsup/cygwin/release/3.3.5 b/winsup/cygwin/release/3.3.5
index 752d65703..d2a7f772a 100644
--- a/winsup/cygwin/release/3.3.5
+++ b/winsup/cygwin/release/3.3.5
@@ -40,3 +40,6 @@ Bug Fixes
 - Fix a problem that fsync() flushes the console input buffer unlike
   linux. fsync() should return EINVAL for special files such as tty.
   Addresses: https://cygwin.com/pipermail/cygwin/2022-March/251022.html
+
+- Fix a formatting problem in gmondump where all displayed addresses are
+  mistakenly prefixed with "0x0x".
-- 
2.35.1



[PATCH] Cygwin: Fix gmondump formatting goofs

2022-03-14 Thread Mark Geisert
The rewrite of %X to %p was malhandled.  Fix that/them.

---
 winsup/utils/gmondump.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
index ec9db0598..2d29e826d 100644
--- a/winsup/utils/gmondump.c
+++ b/winsup/utils/gmondump.c
@@ -162,7 +162,7 @@ gmondump1 (char *filename)
 
   note ("file %s, gmon version 0x%x, sample rate %d\n",
 filename, hdr.version, hdr.profrate);
-  note ("  address range 0x%p..0x%p\n", hdr.lpc, hdr.hpc);
+  note ("  address range %p..%p\n", hdr.lpc, hdr.hpc);
   note ("  numbuckets %d, hitbuckets %d, hitcount %d, numrawarcs %d\n",
 numbuckets, hitbuckets, hitcount, numrawarcs);
 
@@ -175,7 +175,7 @@ gmondump1 (char *filename)
   int   incr = (hdr.hpc - hdr.lpc) / numbuckets;
   for (res = 0; res < numbuckets; ++bucket, ++res, addr += incr)
 if (*bucket)
-  note ("address 0x%p, hitcount %d\n", addr, *bucket);
+  note ("address %p, hitcount %d\n", addr, *bucket);
   bucket -= numbuckets;
 
   if (numrawarcs)
@@ -186,7 +186,7 @@ gmondump1 (char *filename)
 error (0, "unable to read rawarc data");
   note ("  rawarc data follows...\n");
   for (res = 0; res < numrawarcs; ++rawarc, ++res)
-note ("from 0x%p, self 0x%p, count %d\n",
+note ("from %p, self %p, count %d\n",
   rawarc->raw_frompc, rawarc->raw_selfpc, rawarc->raw_count);
 }
 }
-- 
2.35.1



Re: [PATCH v2] Cygwin: clipboard: Fix a bug in read().

2021-12-08 Thread Mark Geisert

Takashi Yano wrote:
[...]

I think the following patch makes the intent clearer.
What do you think?


 From d0aee9af225384a24ac6301f987ce2e94f262500 Mon Sep 17 00:00:00 2001
From: Takashi Yano 
Date: Wed, 8 Dec 2021 17:06:03 +0900
Subject: [PATCH] Cygwin: clipboard: Make intent of the code clearer.

---
  winsup/cygwin/fhandler_clipboard.cc   | 4 ++--
  winsup/cygwin/include/sys/clipboard.h | 1 +
  2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/fhandler_clipboard.cc 
b/winsup/cygwin/fhandler_clipboard.cc
index 05f54ffb3..65a3cad97 100644
--- a/winsup/cygwin/fhandler_clipboard.cc
+++ b/winsup/cygwin/fhandler_clipboard.cc
@@ -76,7 +76,7 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, 
size_t len)
clipbuf->cb_sec  = clipbuf->ts.tv_sec;
  #endif
clipbuf->cb_size = len;
-  memcpy ([1], buf, len); // append user-supplied data
+  memcpy (clipbuf->data, buf, len); // append user-supplied data
  
GlobalUnlock (hmem);

EmptyClipboard ();
@@ -229,7 +229,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
if (pos < (off_t) clipbuf->cb_size)
{
  ret = (len > (clipbuf->cb_size - pos)) ? clipbuf->cb_size - pos : len;
- memcpy (ptr, (char *) (clipbuf + 1) + pos, ret);
+ memcpy (ptr, clipbuf->data + pos, ret);
  pos += ret;
}
  }
diff --git a/winsup/cygwin/include/sys/clipboard.h 
b/winsup/cygwin/include/sys/clipboard.h
index 4c00c8ea1..b2544be85 100644
--- a/winsup/cygwin/include/sys/clipboard.h
+++ b/winsup/cygwin/include/sys/clipboard.h
@@ -44,6 +44,7 @@ typedef struct
  };
};
uint64_t  cb_size; // 8 bytes everywhere
+  char  data[];
  } cygcb_t;
  
  #endif


Sigh.  I guess it's not possible to keep rid of a data item like I'd hoped.  At 
least "data[]" is cleaner than the historical "data[1]" here.  If you call the 
item cb_data I can live with it.

Thanks all for the discussion.

..mark


Re: [PATCH v2] Cygwin: clipboard: Fix a bug in read().

2021-12-07 Thread Mark Geisert

Brian Inglis wrote:

On 2021-12-07 13:18, Thomas Wolff wrote:


Am 07.12.2021 um 15:23 schrieb Corinna Vinschen:

On Dec  7 23:00, Takashi Yano wrote:

- Fix a bug in fhandler_dev_clipboard::read() that the second read
   fails with 'Bad address'.

Addresses:
   https://cygwin.com/pipermail/cygwin/2021-December/250141.html
---
  winsup/cygwin/fhandler_clipboard.cc | 2 +-
  winsup/cygwin/release/3.3.4 | 6 ++
  2 files changed, 7 insertions(+), 1 deletion(-)
  create mode 100644 winsup/cygwin/release/3.3.4

diff --git a/winsup/cygwin/fhandler_clipboard.cc 
b/winsup/cygwin/fhandler_clipboard.cc

index 0b87dd352..ae10228a7 100644
--- a/winsup/cygwin/fhandler_clipboard.cc
+++ b/winsup/cygwin/fhandler_clipboard.cc
@@ -229,7 +229,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
    if (pos < (off_t) clipbuf->cb_size)
  {
    ret = (len > (clipbuf->cb_size - pos)) ? clipbuf->cb_size - pos : len;
-  memcpy (ptr, [1] + pos , ret);
+  memcpy (ptr, (char *) [1] + pos, ret);



I'm always cringing a bit when I see this kind of expression. Personally
I think (ptr + offset) is easier to read than [offset], but of course
that's just me.  If you agree, would it be ok to change the above to

   (char *) (clipbuf + 1)

while you're at it?  If you like the ampersand expression more, it's ok,
too, of course.  Please push.


In this specific case I think it's actually more confusing because of the type 
mangling that's intended in the clipbuf.

At quick glance, it looks a bit as if the following were meant:

   (char *) clipbuf + 1

I'd even make it clearer like

+  memcpy (ptr, ((char *) [1]) + pos, ret);
or even
+  memcpy (ptr, ((char *) ([1])) + pos, ret);


If the intent is to address:

 clipbuf + pos + 1

use either that or:

 [pos + 1]

to avoid obscuring the intent,
and add comments to make it clearer!


Boy am I kicking myself for screwing up the original here and opening this can of 
worms.  Brian, you'd be correct if clipbuf was (char *) like anything-buf often 
is.  But here it's a struct defining the initial part of a dynamic char buffer.


So my original
[1]
to mean "just after the defining struct" was OK.  But the code needed a ptr to 
some char offset after that and

[1] + pos
was wrong.  Casting the left term to (char *) would fix it.  But I like Corinna's 
choice of

(char *) (clipbuf + 1)
to be most elegant and clear of all.  Now enclose that in parens and append the 
char offset so the new expression is

((char *) (clipbuf + 1)) + pos
and all should be golden.  I don't think extra commentary is needed in code.

(I think.)

..mark


[PATCH v2] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-25 Thread Mark Geisert
This patch unifies the layout of the clipboard descriptor cygcb_t for
32- and 64-bit Cygwin.  It allows correct copy/paste between the two
environments without corruption of user's copied data and without access
violations due to interpreting that data as a size field.

The definitions of CYGWIN_NATIVE and cygcb_t are moved to a new include
file, sys/clipboard.h.  The include file is used by fhandler_clipboard.cc
as well as getclip.c and putclip.c in the Cygwin cygutils package.

When copy/pasting between 32- and 64-bit Cygwin environments, both must
be running version 3.3.0 or later for successful operation.

---
 winsup/cygwin/fhandler_clipboard.cc   | 42 +--
 winsup/cygwin/include/sys/clipboard.h | 49 +++
 winsup/cygwin/release/3.3.0   |  4 +++
 3 files changed, 78 insertions(+), 17 deletions(-)
 create mode 100644 winsup/cygwin/include/sys/clipboard.h

diff --git a/winsup/cygwin/fhandler_clipboard.cc 
b/winsup/cygwin/fhandler_clipboard.cc
index ccdb295f3..7adb50991 100644
--- a/winsup/cygwin/fhandler_clipboard.cc
+++ b/winsup/cygwin/fhandler_clipboard.cc
@@ -17,6 +17,7 @@ details. */
 #include "dtable.h"
 #include "cygheap.h"
 #include "child_info.h"
+#include "sys/clipboard.h"
 
 /*
  * Robert Collins:
@@ -24,15 +25,6 @@ details. */
  * changed? How does /dev/clipboard operate under (say) linux?
  */
 
-static const WCHAR *CYGWIN_NATIVE = L"CYGWIN_NATIVE_CLIPBOARD";
-
-typedef struct
-{
-  timestruc_t  timestamp;
-  size_t   len;
-  char data[1];
-} cygcb_t;
-
 fhandler_dev_clipboard::fhandler_dev_clipboard ()
   : fhandler_base (), pos (0), membuffer (NULL), msize (0)
 {
@@ -74,9 +66,17 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, 
size_t len)
}
   clipbuf = (cygcb_t *) GlobalLock (hmem);
 
-  clock_gettime (CLOCK_REALTIME, >timestamp);
-  clipbuf->len = len;
-  memcpy (clipbuf->data, buf, len);
+  clock_gettime (CLOCK_REALTIME, >ts);
+#ifdef __x86_64__
+  /* ts overlays cb_sec and cb_nsec such that no conversion is needed */
+#elif __i386__
+  /* Expand 32-bit timespec layout to 64-bit layout.
+ NOTE: Steps must be done in this order to avoid data loss. */
+  clipbuf->cb_nsec = clipbuf->ts.tv_nsec;
+  clipbuf->cb_sec  = clipbuf->ts.tv_sec;
+#endif
+  clipbuf->cb_size = len;
+  memcpy ([1], buf, len); // append user-supplied data
 
   GlobalUnlock (hmem);
   EmptyClipboard ();
@@ -179,8 +179,16 @@ fhandler_dev_clipboard::fstat (struct stat *buf)
  && (hglb = GetClipboardData (format))
  && (clipbuf = (cygcb_t *) GlobalLock (hglb)))
{
- buf->st_atim = buf->st_mtim = clipbuf->timestamp;
- buf->st_size = clipbuf->len;
+#ifdef __x86_64__
+ /* ts overlays cb_sec and cb_nsec such that no conversion is needed */
+#elif __i386__
+ /* Compress 64-bit timespec layout to 32-bit layout.
+NOTE: Steps must be done in this order to avoid data loss. */
+ clipbuf->ts.tv_sec  = clipbuf->cb_sec;
+ clipbuf->ts.tv_nsec = clipbuf->cb_nsec;
+#endif
+ buf->st_atim = buf->st_mtim = clipbuf->ts;
+ buf->st_size = clipbuf->cb_size;
  GlobalUnlock (hglb);
}
   CloseClipboard ();
@@ -218,10 +226,10 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
 {
   cygcb_t *clipbuf = (cygcb_t *) cb_data;
 
-  if (pos < (off_t) clipbuf->len)
+  if (pos < (off_t) clipbuf->cb_size)
{
- ret = ((len > (clipbuf->len - pos)) ? (clipbuf->len - pos) : len);
- memcpy (ptr, clipbuf->data + pos , ret);
+ ret = (len > (clipbuf->cb_size - pos)) ? clipbuf->cb_size - pos : len;
+ memcpy (ptr, [1] + pos , ret);
  pos += ret;
}
 }
diff --git a/winsup/cygwin/include/sys/clipboard.h 
b/winsup/cygwin/include/sys/clipboard.h
new file mode 100644
index 0..4c00c8ea1
--- /dev/null
+++ b/winsup/cygwin/include/sys/clipboard.h
@@ -0,0 +1,49 @@
+/* sys/clipboard.h
+
+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 _SYS_CLIPBOARD_H_
+#define _SYS_CLIPBOARD_H_
+
+/*
+ * These definitions are used in fhandler_clipboard.cc
+ * as well as in the Cygwin cygutils package, specifically
+ * getclip.c and putclip.c.
+ */
+
+static const WCHAR *CYGWIN_NATIVE = L"CYGWIN_NATIVE_CLIPBOARD";
+
+/*
+ * The following layout of cygcb_t is new with Cygwin 3.3.0.  It aids in the
+ * transfer of clipboard contents between 32- and 64-bit Cygwin environments.
+ */
+typedef struct
+{
+  union
+  {
+/*
+ * Note that ts below overlays the struct following it.  On 32-bit Cygwin
+ * timespec values have to be converted to|from cygcb_t layout.  On 64-bit
+ * Cygwin timespec values perfectly conform to the struct following, so
+ * no conversion is needed.
+ *
+ * We avoid directly 

Re: [PATCH] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-23 Thread Mark Geisert

Ken Brown wrote:

On 10/23/2021 1:35 AM, Mark Geisert wrote:

Corinna Vinschen wrote:

Just to close this up prior to the 3.3.0 release...

Given we never actually strived for 32<->64 bit interoperability, it's
hard to argue why this should be different for the clipboard stuff.

Running 32 and 64 bit Cygwin versions in parallel doesn't actually make
much sense for most people anyway, unless they explicitely develop for
32 and 64 bit systems under Cygwin.  From a productivity point of view
there's no good reason to run more than one arch.

So I agree with Ken here.  It's probably not worth the trouble.


Sorry, I've been sidetracked for a bit.  I can agree with Ken too.  The only 
circumstance I could think of where multiple internal format support might be 
useful (to non-developers) was some user hanging on to an older Cygwin because 
it was needed to support something else (s/w or h/w) old and non-upgradeable. 
Doesn't seem very likely at this point.


I'll try to get the v2 patch out over this weekend.  Same end-result for same 
environments as the v1 patch, but incorporating all the comments I received.


I think Corinna was saying that the whole idea of making the 32-bit and 64-bit 
clipboards interoperable is not worth the trouble.


Oh, I didn't read it that way.  But that works for me too.  Color it dropped 
:-).
Thanks,

..mark


Re: [PATCH] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-22 Thread Mark Geisert

Hi all,

Corinna Vinschen wrote:

On Oct 11 08:11, Ken Brown wrote:

On 10/11/2021 2:13 AM, Mark Geisert wrote:

It's just that after submitting the patch I realized that, if we really
are going to support both Cygwin archs (x86_64 and i686), there is still
the issue of different cygcb_t layouts between Cygwin versions being
ignored.

Specifically, the fhandler_clipboard::fstat routine can't tell which
Cygwin environment has set the clipboard contents.  My original patch
takes care of 32-bit and 64-bit, providing both are running Cygwin >=
3.3.0 (presumably).  What if it was a different version (pre 3.3.0) that
set the contents?


I wonder if this is worth the trouble.  Right now we have a problem in which
data written to /dev/clipboard in one arch can't be read in the other arch.
The fix will appear in Cygwin 3.3.0.  Do we really have to try to make the
fix apply retroactively in case the user updates one arch but not the other?


Just to close this up prior to the 3.3.0 release...

Given we never actually strived for 32<->64 bit interoperability, it's
hard to argue why this should be different for the clipboard stuff.

Running 32 and 64 bit Cygwin versions in parallel doesn't actually make
much sense for most people anyway, unless they explicitely develop for
32 and 64 bit systems under Cygwin.  From a productivity point of view
there's no good reason to run more than one arch.

So I agree with Ken here.  It's probably not worth the trouble.


Sorry, I've been sidetracked for a bit.  I can agree with Ken too.  The only 
circumstance I could think of where multiple internal format support might be 
useful (to non-developers) was some user hanging on to an older Cygwin because it 
was needed to support something else (s/w or h/w) old and non-upgradeable. 
Doesn't seem very likely at this point.


I'll try to get the v2 patch out over this weekend.  Same end-result for same 
environments as the v1 patch, but incorporating all the comments I received.


To that end, does Jon's suggestion of /usr/include/sys/cygwin.h seem like the best 
location to define struct cygcb_t for use by both Cygwin and cygutils package?

Thanks much,

..mark


Re: [PATCH] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-11 Thread Mark Geisert

Ken Brown wrote:

On 10/9/2021 10:29 AM, Jon Turney wrote:

[...]

On 10/8/2021 5:52 AM, Takashi Yano wrote:

[...]

Thanks all for the comments; much appreciated.  They'll be factored into v2 in one 
form or another.  I pronounced my original patch "bad" not because of any problem 
with code operation or struct cygcb_t definition.  I used anonymous union and 
anonymous struct internally to mostly realize what Takashi suggested for layout, 
just naming the items cb_* rather than tv_* or other.  The code works as intended, 
32- and 64-bit.


It's just that after submitting the patch I realized that, if we really are going 
to support both Cygwin archs (x86_64 and i686), there is still the issue of 
different cygcb_t layouts between Cygwin versions being ignored.


Specifically, the fhandler_clipboard::fstat routine can't tell which Cygwin 
environment has set the clipboard contents.  My original patch takes care of 
32-bit and 64-bit, providing both are running Cygwin >= 3.3.0 (presumably).  What 
if it was a different version (pre 3.3.0) that set the contents?


So I'm working on a heuristic to identify which cygcb_t layout is present in the 
clipboard data.  This will hopefully distinguish between the 3 historical cygcb_t 
layouts as well as x86_64 differing from i686 for each one.

Stay tuned,

..mark


Re: [PATCH] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-06 Thread Mark Geisert

Mark Geisert wrote:

This allows correct copy and pasting between the two Cygwin flavors.

[...]

Eh, that's a bad patch. Don't apply. It's OK for concept review.
v2 forthcoming.
Thanks,

..mark


[PATCH] Cygwin: Make native clipboard layout same for 32- and 64-bit

2021-10-06 Thread Mark Geisert
This allows correct copy and pasting between the two Cygwin flavors.

What's done is to overlay the differing timespec formats via a union
within the control structure cygcb_t.  Then conversion between the two
formats is done on the 32-bit side only.

The cygutils package has two programs, putclip and getclip, that also
depend on the layout of the cygcb_t.  At present they have duplicate
defs of struct cygcb_t defined here as no Cygwin header provides it.

---
 winsup/cygwin/fhandler_clipboard.cc | 39 +
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/winsup/cygwin/fhandler_clipboard.cc 
b/winsup/cygwin/fhandler_clipboard.cc
index ccdb295f3..649e57072 100644
--- a/winsup/cygwin/fhandler_clipboard.cc
+++ b/winsup/cygwin/fhandler_clipboard.cc
@@ -28,9 +28,16 @@ static const WCHAR *CYGWIN_NATIVE = 
L"CYGWIN_NATIVE_CLIPBOARD";
 
 typedef struct
 {
-  timestruc_t  timestamp;
-  size_t   len;
-  char data[1];
+  union
+  {
+struct timespec ts; // 8 bytes on 32-bit Cygwin, 16 bytes on 64-bit Cygwin
+struct
+{
+  uint64_t cb_sec;
+  uint64_t cb_nsec;
+};
+  };
+  uint64_t cb_size;
 } cygcb_t;
 
 fhandler_dev_clipboard::fhandler_dev_clipboard ()
@@ -74,9 +81,14 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, 
size_t len)
}
   clipbuf = (cygcb_t *) GlobalLock (hmem);
 
-  clock_gettime (CLOCK_REALTIME, >timestamp);
-  clipbuf->len = len;
-  memcpy (clipbuf->data, buf, len);
+  clock_gettime (CLOCK_REALTIME, >ts);
+#ifndef __x86_64__
+  // expand 32-bit timespec layout to 64-bit layout
+  clipbuf->cb_nsec = clipbuf->ts.tv_nsec;
+  clipbuf->cb_sec = clipbuf->ts.tv_sec;
+#endif
+  clipbuf->cb_size = len;
+  memcpy ([1], buf, len); // append data
 
   GlobalUnlock (hmem);
   EmptyClipboard ();
@@ -179,8 +191,13 @@ fhandler_dev_clipboard::fstat (struct stat *buf)
  && (hglb = GetClipboardData (format))
  && (clipbuf = (cygcb_t *) GlobalLock (hglb)))
{
- buf->st_atim = buf->st_mtim = clipbuf->timestamp;
- buf->st_size = clipbuf->len;
+#ifndef __x86_64__
+ // compress 64-bit timespec layout to 32-bit layout
+ clipbuf->ts.tv_sec = clipbuf->cb_sec;
+ clipbuf->ts.tv_nsec = clipbuf->cb_nsec;
+#endif
+ buf->st_atim = buf->st_mtim = clipbuf->ts;
+ buf->st_size = clipbuf->cb_size;
  GlobalUnlock (hglb);
}
   CloseClipboard ();
@@ -218,10 +235,10 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
 {
   cygcb_t *clipbuf = (cygcb_t *) cb_data;
 
-  if (pos < (off_t) clipbuf->len)
+  if (pos < (off_t) clipbuf->cb_size)
{
- ret = ((len > (clipbuf->len - pos)) ? (clipbuf->len - pos) : len);
- memcpy (ptr, clipbuf->data + pos , ret);
+ ret = (len > (clipbuf->cb_size - pos)) ? clipbuf->cb_size - pos : len;
+ memcpy (ptr, [1] + pos , ret);
  pos += ret;
}
 }
-- 
2.33.0



[PATCH] Cygwin: Make gmondump conform to its doc + adjust doc

2021-08-02 Thread Mark Geisert
The doc for gmondump says 1 or more FILENAME are expected, but 0 is
handled. That's an oversight. Make invocation with 0 FILENAMEs print a
one-line help message.

Reword the beginning of profiler's description doc to clarify target's
child processes are run but only optionally profiled.

---
 winsup/doc/utils.xml|  7 ---
 winsup/utils/gmondump.c | 12 
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 659541f00..0b9e38549 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -2240,9 +2240,10 @@ specifying an empty password.
 
 
   Description
-The profiler utility executes a given program, and
-  optionally the children of that program, collecting the location of the
-  CPU instruction pointer (IP) many times per second. This gives a profile
+The profiler utility executes a given program and
+  any children of that program, collecting the location of the CPU
+  instruction pointer (IP) many times per second. (It is optional to
+  collect this info from child processes.) This info gives a profile
   of the program's execution, showing where the most time is being spent.
   This profiling technique is called "IP sampling".
 
diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
index e469f01f1..ec9db0598 100644
--- a/winsup/utils/gmondump.c
+++ b/winsup/utils/gmondump.c
@@ -46,6 +46,14 @@ OPTIONS are:\n\
   exit (where == stderr ? 1 : 0 );
 }
 
+void __attribute__ ((__noreturn__))
+usage1 (FILE *where)
+{
+  fprintf (where, "Usage: %s [OPTIONS] FILENAME...\n", pgm);
+
+  exit (where == stderr ? 1 : 0 );
+}
+
 void
 note (const char *fmt, ...)
 {
@@ -248,6 +256,10 @@ main(int argc, char **argv)
 ;
   }
 
+  if (optind >= argc)
+/* Print one-line help and exit. */
+usage1 (ofile);
+
   for (int i = optind; i < argc; i++)
 gmondump1 (argv[i]);
 
-- 
2.32.0



[PATCH] Cygwin: More profiler format + small issue fixes

2021-08-02 Thread Mark Geisert
Make sure to cast to ulong all DWORD values displayed with format "%lu".
More instances are fixed here than in either my earlier unused patch or
Corinna's patch. I decided to use typedef..ulong for more compact code.

Address jturney's reported small issues:
- Remove explicit external ref for cygwin_internal() as it is already
  provided by .
- Leave intact ref for cygwin_dll_path[] as it is required by function(s)
  in path.cc that profiler uses. Added comment to that effect.
- Delete existing main() wrapper. Rename main2() to main(). This because
  profiler is now a Cygwin program and doesn't need to dynamically load
  cygwin1.dll.
- Documentation issues will be addressed in a separate xml patch.

(I would have linked message-ids of Corinna's and Jon's messages for
proper theading but I no longer have their original emails and the mail
archives don't show msgids any more.)

---
 winsup/utils/profiler.cc | 60 ++--
 1 file changed, 20 insertions(+), 40 deletions(-)

diff --git a/winsup/utils/profiler.cc b/winsup/utils/profiler.cc
index 354aefca8..2be7baf74 100644
--- a/winsup/utils/profiler.cc
+++ b/winsup/utils/profiler.cc
@@ -14,7 +14,6 @@
 #define WIN32_LEAN_AND_MEAN
 #include 
 
-#define cygwin_internal cygwin_internal_dontuse
 #include 
 #include 
 #include 
@@ -27,14 +26,13 @@
 #include 
 #include 
 #include "cygwin/version.h"
-#include "cygtls_padsize.h"
 #include "gcc_seh.h"
+typedef unsigned long ulong;
 typedef unsigned short ushort;
 typedef uint16_t u_int16_t; // Non-standard sized type needed by ancient gmon.h
 #define NO_GLOBALS_H
 #include "gmon.h"
 #include "path.h"
-#undef cygwin_internal
 
 /* Undo this #define from winsup.h. */
 #ifdef ExitThread
@@ -201,7 +199,7 @@ bump_bucket (child *c, size_t pc)
 {
   span_list *s = c->spans;
 
-//note ("%lu %p\n", c->pid, pc);
+//note ("%lu %p\n", (ulong) c->pid, pc);
   if (pc == 0ULL)
 return;
   while (s)
@@ -225,7 +223,7 @@ bump_bucket (child *c, size_t pc)
* profiling info on them will be confusing if their addresses overlap.
*/
   if (verbose)
-note ("*** pc %p out of range for pid %lu\n", pc, c->pid);
+note ("*** pc %p out of range for pid %lu\n", pc, (ulong) c->pid);
 }
 
 /* profiler runs on its own thread; each child has a separate profiler. */
@@ -258,7 +256,7 @@ start_profiler (child *c)
   DWORD  tid;
 
   if (verbose)
-note ("*** start profiler thread on pid %lu\n", c->pid);
+note ("*** start profiler thread on pid %lu\n", (ulong) c->pid);
   c->context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
   if (!c->context)
 error (0, "unable to allocate CONTEXT buffer\n");
@@ -284,7 +282,7 @@ void
 stop_profiler (child *c)
 {
   if (verbose)
-note ("*** stop profiler thread on pid %lu\n", c->pid);
+note ("*** stop profiler thread on pid %lu\n", (ulong) c->pid);
   c->profiling = 0;
   SignalObjectAndWait (c->hquitevt, c->hprofthr, INFINITE, FALSE);
   CloseHandle (c->hquitevt);
@@ -312,11 +310,10 @@ dump_profile_data (child *c)
   if (s->name)
 {
   WCHAR *name = 1 + wcsrchr (s->name, L'\\');
-  sprintf (filename, "%s.%lu.%ls", prefix, (unsigned long) c->pid,
-  name);
+  sprintf (filename, "%s.%lu.%ls", prefix, (ulong) c->pid, name);
 }
   else
-sprintf (filename, "%s.%lu", prefix, (unsigned long) c->pid);
+sprintf (filename, "%s.%lu", prefix, (ulong) c->pid);
 
   fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);
   if (fd < 0)
@@ -390,7 +387,7 @@ add_child (DWORD pid, WCHAR *name, LPVOID base, HANDLE 
hproc)
   start_profiler (children.next);
   numprocesses++;
   if (verbose)
-note ("*** Windows process %lu attached\n", pid);
+note ("*** Windows process %lu attached\n", (ulong) pid);
 }
 }
 
@@ -412,7 +409,7 @@ remove_child (DWORD pid)
 c1->hproc = 0;
 free (c1);
 if (verbose)
-  note ("*** Windows process %lu detached\n", pid);
+  note ("*** Windows process %lu detached\n", (ulong) pid);
 numprocesses--;
 return;
   }
@@ -426,7 +423,7 @@ add_thread (DWORD pid, DWORD tid, HANDLE h, WCHAR *name)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "add_thread: pid %lu not found\n", pid);
+error (0, "add_thread: pid %lu not found\n", (ulong) pid);
 
   thread_list *t = (thread_list *) calloc (1, sizeof (thread_list));
   t->tid = tid;
@@ -443,7 +440,7 @@ remove_thread (DWORD pid, DWORD tid)
   child *c = get_child (pid);
 
   if (!c)
-error (0, "remove_thread: pid %lu not found\n", pid);
+error (0, "remove_thread: pid %lu not found\n", (ulong) pid);
 
   thread_list *t = c->threads;
   while (t)
@@ -462,7 +459,8 @@ remove_thread (DWORD pid, DWORD tid)
   t = t->next;
 }
 
-  error (0, "remove_thread: pid %lu tid %lu not found\n", pid, tid);
+  error (0, "remove_thread: pid %lu tid %lu not found\n",
+ (ulong) 

[PATCH] Cygwin: fix format warnings in profiler.cc

2021-07-21 Thread Mark Geisert
Use new typedef to normalize pids for printing on both 32- and 64-bit Cygwin.

---
 winsup/utils/profiler.cc | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/winsup/utils/profiler.cc b/winsup/utils/profiler.cc
index d1a01c3a2..152bf1cca 100644
--- a/winsup/utils/profiler.cc
+++ b/winsup/utils/profiler.cc
@@ -29,6 +29,7 @@
 #include "cygwin/version.h"
 #include "cygtls_padsize.h"
 #include "gcc_seh.h"
+typedef unsigned long ulong;
 typedef unsigned short ushort;
 typedef uint16_t u_int16_t; // Non-standard sized type needed by ancient gmon.h
 #define NO_GLOBALS_H
@@ -312,10 +313,10 @@ dump_profile_data (child *c)
   if (s->name)
 {
   WCHAR *name = 1 + wcsrchr (s->name, L'\\');
-  sprintf (filename, "%s.%u.%ls", prefix, c->pid, name);
+  sprintf (filename, "%s.%lu.%ls", prefix, (ulong) c->pid, name);
 }
   else
-sprintf (filename, "%s.%u", prefix, c->pid);
+sprintf (filename, "%s.%lu", prefix, (ulong) c->pid);
 
   fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);
   if (fd < 0)
@@ -804,9 +805,9 @@ cygwin_pid (DWORD winpid)
   cygpid = (DWORD) cygwin_internal (CW_WINPID_TO_CYGWIN_PID, winpid);
 
   if (cygpid >= max_cygpid)
-snprintf (buf, sizeof buf, "%u", winpid);
+snprintf (buf, sizeof buf, "%lu", (ulong) winpid);
   else
-snprintf (buf, sizeof buf, "%u (pid: %u)", winpid, cygpid);
+snprintf (buf, sizeof buf, "%lu (pid: %lu)", (ulong) winpid, (ulong) 
cygpid);
   return buf;
 }
 
-- 
2.32.0



[PATCH 3/3] Cygwin: updates to wire in profiler, gmondump

2021-07-15 Thread Mark Geisert
These are updates to wire into the build tree the new tools profiler and
gmondump, and to supply documentation for the tools.

The documentation for profiler and ssp now mention each other but do not
discuss their similarities or differences.  That will be handled in a
future update to the "Profiling Cygwin Programs" section of the Cygwin
User's Guide, to be supplied.

---
 winsup/cygwin/release/3.2.1 |   7 ++
 winsup/doc/utils.xml| 123 
 winsup/utils/Makefile.am|   5 ++
 3 files changed, 135 insertions(+)

diff --git a/winsup/cygwin/release/3.2.1 b/winsup/cygwin/release/3.2.1
index 99c65ce30..4f4db622a 100644
--- a/winsup/cygwin/release/3.2.1
+++ b/winsup/cygwin/release/3.2.1
@@ -1,6 +1,13 @@
 What's new:
 ---
 
+- An IP-sampling profiler named 'profiler' has been added.  It can be used
+  to profile any Cygwin program along with any DLLs loaded.
+
+- A new tool 'gmondump' has been added.  It can dump the raw information
+  of any "gmon.out" file created by profiler, ssp, or use of the gcc/g++
+  option '-pg'.  (Continue using gprof to get symbolic profile displays.)
+
 
 What changed:
 -
diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 1d9b8488c..0b7b5d0ea 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml
@@ -793,6 +793,56 @@ line separates the ACLs for each file.
 
   
 
+  
+
+  gmondump
+  1
+  Cygwin Utilities
+
+
+
+  gmondump
+  Display formatted contents of profile data files
+
+
+
+
+gmondump [OPTION]... FILENAME...
+
+
+
+
+  Options
+  
+  -h, --help Display usage information and exit
+  -v, --verbose  Display more file details (toggle: default false)
+  -V, --version  Display version information and exit
+
+
+
+
+  Description
+The gmondump utility displays the contents of
+  one or more profile data files. Such files usually have names starting
+  with "gmon.out" and are created by a profiling program such as
+  profiler or ssp. Compiling your
+  gcc/g++ programs with option -pg also works.
+ By default, summary information is shown. You can use the
+  option -v to get more detailed displays.
+Note that gmondump just displays the raw data;
+  one would usually use gprof to display the data in
+  a useful form incorporating symbolic info such as function names and
+  source line numbers.
+Here is an example of gmondump operation:
+
+$ gmondump gmon.out.21900.zstd.exe
+file gmon.out.21900.zstd.exe, gmon version 0x51879, sample rate 100
+  address range 0x0x100401000..0x0x1004cc668
+  numbuckets 208282, hitbuckets 1199, hitcount 12124, numrawarcs 0
+
+
+  
+
   
 
   kill
@@ -2127,6 +2177,75 @@ specifying an empty password.
 
   
 
+  
+
+  profiler
+  1
+  Cygwin Utilities
+
+
+
+  profiler
+  Sampling profiler of Cygwin programs with their 
DLLs
+
+
+
+
+profiler [OPTION]... PROGRAM [ARG]...
+profiler [OPTION]... -p PID
+
+
+
+
+  Options
+  
+  -d, --debugDisplay debugging messages (toggle: default false)
+  -e, --events   Display Windows DEBUG_EVENTS (toggle: default false)
+  -f, --fork-profile Profiles child processes (toggle: default false)
+  -h, --help Display usage information and exit
+  -o, --output=FILENAME  Write output to file FILENAME rather than stdout
+  -p, --pid=NAttach to running program with Cygwin pid N
+ ...or with Windows pid -N
+  -s, --sample-rate=NSet IP sampling rate to N Hz (default 100)
+  -v, --verbose  Display more status messages (toggle: default false)
+  -V, --version  Display version information and exit
+  -w, --new-window   Launch given command in a new window
+
+
+
+
+  Description
+The profiler utility executes a given program, and
+  optionally the children of that program, collecting the location of the
+  CPU instruction pointer (IP) many times per second. This gives a profile
+  of the program's execution, showing where the most time is being spent.
+  This profiling technique is called "IP sampling".
+
+A novel feature of profiler is that time spent in
+  DLLs loaded with or by your program is profiled too. You use
+  gprof to process and display the resulting profile
+  information. In this fashion you can determine whether your own code,
+  the Cygwin DLL, or another DLL has "hot spots" that might benefit from
+  tuning.
+
+(See also ssp, another profiler that
+  operates in a different fashion: stepping by instruction. This can
+  provide a different view on your program's operation.)
+
+Here is an example of profiler operation:
+
+$ profiler du -khs .
+22G .
+97 samples across 83 buckets written to gmon.out.5908.cygwin1.dll
+4 samples 

[PATCH 2/3] Cygwin: New tool: gmondump

2021-07-15 Thread Mark Geisert
This new tool was formerly part of 'profiler' but was spun out thanks to
Jon T's reasonable review comment.  Gmondump is more of a debugging tool
than something users might have need for.  Users would more likely use
gprof to make use of symbolic info like function names and source line
numbers.

---
 winsup/utils/gmondump.c | 255 
 1 file changed, 255 insertions(+)
 create mode 100644 winsup/utils/gmondump.c

diff --git a/winsup/utils/gmondump.c b/winsup/utils/gmondump.c
new file mode 100644
index 0..e469f01f1
--- /dev/null
+++ b/winsup/utils/gmondump.c
@@ -0,0 +1,255 @@
+/*
+gmondump.c
+Displays summary info about given profile data file(s).
+
+Written by Mark Geisert .
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license.  Please consult the file "CYGWIN_LICENSE" for details.
+*/
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cygwin/version.h"
+
+typedef unsigned short ushort;
+typedef uint16_t u_int16_t; // Non-standard sized type needed by ancient gmon.h
+#include "gmon.h"
+
+FILE   *ofile;
+const char *pgm = "gmondump";
+int verbose = 0;
+
+void __attribute__ ((__noreturn__))
+usage (FILE *where)
+{
+  fprintf (where, "\
+Usage: %s [OPTIONS] FILENAME...\n\
+\n\
+Display formatted contents of profile data file(s).\n\
+Such files usually have names starting with \"gmon.out\".\n\
+OPTIONS are:\n\
+\n\
+  -h, --help Display usage information and exit\n\
+  -v, --verbose  Display more file details (toggle: default false)\n\
+  -V, --version  Display version information and exit\n\
+\n", pgm);
+
+  exit (where == stderr ? 1 : 0 );
+}
+
+void
+note (const char *fmt, ...)
+{
+  va_list args;
+  charbuf[4096];
+
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  va_end (args);
+
+  fputs (buf, ofile);
+  fflush (ofile);
+}
+
+void
+warn (int geterrno, const char *fmt, ...)
+{
+  va_list args;
+  charbuf[4096];
+
+  va_start (args, fmt);
+  sprintf (buf, "%s: ", pgm);
+  vsprintf (strchr (buf, '\0'), fmt, args);
+  va_end (args);
+  if (geterrno)
+perror (buf);
+  else
+{
+  fputs (buf, ofile);
+  fputs ("\n", ofile);
+  fflush (ofile);
+}
+}
+
+void __attribute__ ((noreturn))
+error (int geterrno, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start (args, fmt);
+  warn (geterrno, fmt, args);
+  va_end (args);
+
+  exit (1);
+}
+
+void
+gmondump1 (char *filename)
+{
+  ushort*bucket = NULL;
+  intfd;
+  struct gmonhdr hdr;
+  inthitbuckets;
+  inthitcount;
+  intnumbuckets;
+  intnumrawarcs;
+  struct rawarc *rawarc = NULL;
+  intres;
+  struct stat stat;
+
+  fd = open (filename, O_RDONLY | O_BINARY);
+  if (fd < 0)
+{
+  note ("file%s %s couldn't be opened; continuing\n",
+strchr (filename, '*') ? "s" : "", filename);
+  return;
+}
+
+  /* Read and sanity-check what should be a gmon header. */
+  res = fstat (fd, );
+  if (res < 0)
+goto notgmon;
+  if (S_IFREG != (stat.st_mode & S_IFMT))
+goto notgmon;
+  res = read (fd, , sizeof (hdr));
+  if (res != sizeof (hdr))
+goto notgmon;
+  if (hdr.lpc >= hdr.hpc)
+goto notgmon;
+  numbuckets = (hdr.ncnt - sizeof (hdr)) / sizeof (short);
+  if (numbuckets != (hdr.hpc - hdr.lpc) / 4)
+goto notgmon;
+  numrawarcs = 0;
+  if (stat.st_size != hdr.ncnt)
+{
+  numrawarcs = stat.st_size - hdr.ncnt;
+  if (numrawarcs !=
+  (int) sizeof (rawarc) * (numrawarcs / (int) sizeof (rawarc)))
+goto notgmon;
+  numrawarcs /= (int) sizeof (rawarc);
+}
+
+  /* Looks good, so read and display the profiling info. */
+  bucket = (ushort *) calloc (numbuckets, sizeof (ushort));
+  res = read (fd, bucket, hdr.ncnt - sizeof (hdr));
+  if (res != hdr.ncnt - (int) sizeof (hdr))
+goto notgmon;
+  hitcount = hitbuckets = 0;
+  for (res = 0; res < numbuckets; ++bucket, ++res)
+if (*bucket)
+  {
+++hitbuckets;
+hitcount += *bucket;
+  }
+  bucket -= numbuckets;
+
+  note ("file %s, gmon version 0x%x, sample rate %d\n",
+filename, hdr.version, hdr.profrate);
+  note ("  address range 0x%p..0x%p\n", hdr.lpc, hdr.hpc);
+  note ("  numbuckets %d, hitbuckets %d, hitcount %d, numrawarcs %d\n",
+numbuckets, hitbuckets, hitcount, numrawarcs);
+
+  /* If verbose is set, display contents of buckets and rawarcs arrays. */
+  if (verbose)
+{
+  if (hitbuckets)
+note ("  bucket data follows...\n");
+  char *addr = (char *) hdr.lpc;
+  int   incr = (hdr.hpc - hdr.lpc) / numbuckets;
+  for (res = 0; res < numbuckets; ++bucket, ++res, addr += incr)
+if (

[PATCH 1/3] Cygwin: New tool: profiler

2021-07-15 Thread Mark Geisert
The new tool formerly known as cygmon is renamed to 'profiler'.  For the
name I considered 'ipsampler' and could not think of any others.  I'm open
to a different name if any is suggested.

I decided that a discussion of the pros and cons of this profiler vs the
existing ssp should probably be in the "Profiling Cygwin Programs" section
of the Cygwin User's Guide rather than in the help for either.  That
material will be supplied at some point.

CONTEXT buffers are made child-specific and thus thread-specific since
there is one profiler thread for each child program being profiled.

The SetThreadPriority() warning comment has been expanded.

chmod() works on Cygwin so the "//XXX ineffective" comment is gone.

I decided to make the "sample all executable sections" and "sample
dynamically generated code" suggestions simply expanded comments for now.

The profiler program is now a Cygwin exe rather than a native exe.

---
 winsup/utils/profiler.cc | 1109 ++
 1 file changed, 1109 insertions(+)
 create mode 100644 winsup/utils/profiler.cc

diff --git a/winsup/utils/profiler.cc b/winsup/utils/profiler.cc
new file mode 100644
index 0..d1a01c3a2
--- /dev/null
+++ b/winsup/utils/profiler.cc
@@ -0,0 +1,1109 @@
+/*
+profiler.cc
+Periodically samples IP of a process and its DLLs; writes gprof data files.
+
+Written by Mark Geisert , who admits to
+copying pretty liberally from strace.cc.  h/t to cgf for strace!
+
+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.
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include 
+
+#define cygwin_internal cygwin_internal_dontuse
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "cygwin/version.h"
+#include "cygtls_padsize.h"
+#include "gcc_seh.h"
+typedef unsigned short ushort;
+typedef uint16_t u_int16_t; // Non-standard sized type needed by ancient gmon.h
+#define NO_GLOBALS_H
+#include "gmon.h"
+#include "path.h"
+#undef cygwin_internal
+
+/* Undo this #define from winsup.h. */
+#ifdef ExitThread
+#undef ExitThread
+#endif
+
+#define SCALE_SHIFT 2 // == 4 bytes of address space per bucket
+#define MS_VC_EXCEPTION 0x406D1388 // thread name notification from child
+
+DWORD   child_pid;
+int debugging = 0;
+void   *drive_map;
+int events = 0;
+int forkprofile = 0;
+int new_window;
+int numprocesses;
+FILE   *ofile = stdout;
+const char *pgm;
+char   *prefix = (char *) "gmon.out";
+int samplerate = 100; // in Hz; up to 1000 might work
+int verbose = 0;
+
+void __attribute__ ((__noreturn__))
+usage (FILE *where = stderr)
+{
+  fprintf (where, "\
+Usage: %s [OPTIONS] \n\
+   or: %s [OPTIONS] -p \n\
+\n\
+Profiles a command or process by sampling its IP (instruction pointer).\n\
+OPTIONS are:\n\
+\n\
+  -d, --debugDisplay debugging messages (toggle: default false)\n\
+  -e, --events   Display Windows DEBUG_EVENTS (toggle: default 
false)\n\
+  -f, --fork-profile Profile child processes (toggle: default false)\n\
+  -h, --help Display usage information and exit\n\
+  -o, --output=FILENAME  Write output to file FILENAME rather than stdout\n\
+  -p, --pid=NAttach to running program with Cygwin pid N\n\
+ ...or with Windows pid -N\n\
+  -s, --sample-rate=NSet IP sampling rate to N Hz (default 100)\n\
+  -v, --verbose  Display more status messages (toggle: default 
false)\n\
+  -V, --version  Display version information and exit\n\
+  -w, --new-window   Launch given command in a new window\n\
+\n", pgm, pgm);
+
+  exit (where == stderr ? 1 : 0 );
+}
+
+/* A span is a memory address range covering an EXE's or DLL's .text segment. 
*/
+struct span_list
+{
+  WCHAR  *name;
+  LPVOID  base;
+  size_t  textlo;
+  size_t  texthi;
+  int hitcount;
+  int hitbuckets;
+  int numbuckets;
+  int*buckets;
+  struct span_list *next;
+};
+
+/* A thread. */
+struct thread_list
+{
+  DWORD   tid;
+  HANDLE  hthread;
+  WCHAR  *name;
+  struct thread_list *next;
+};
+
+/* A child is any process being sampled in this profiler run. */
+struct child_list
+{
+  DWORD  pid;
+  volatile int profiling;
+  HANDLE hproc;
+  HANDLE hquitevt;
+  HANDLE hprofthr;
+  CONTEXT*context;
+  struct thread_list *threads;
+  struct span_list   *spans;
+  struct child_list  *next;
+};
+
+child_list children;
+typedef struct child_list child;
+
+void
+note (const char *fmt, ...)
+{
+  va_list args;
+  charbuf[4096];
+
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  va_end (args);
+
+  fputs (buf, ofile);
+  fflush (ofi

[PATCH] Cygwin: Zero out gmon header before use

2021-06-23 Thread Mark Geisert
Tools that process gmon.out files can be confused by gmon header fields
with garbage in them due to lack of initialization.  Repair that.

---
 winsup/cygwin/gmon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/winsup/cygwin/gmon.c b/winsup/cygwin/gmon.c
index b31842cd9..8b1c449c4 100644
--- a/winsup/cygwin/gmon.c
+++ b/winsup/cygwin/gmon.c
@@ -224,6 +224,7 @@ _mcleanup(void)
write(log, dbuf, len);
 #endif
hdr = (struct gmonhdr *)
+   bzero(hdr, sizeof *hdr);
hdr->lpc = p->lowpc;
hdr->hpc = p->highpc;
hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
-- 
2.31.1



Re: [PATCH] Cygwin: New tool: cygmon

2021-06-17 Thread Mark Geisert

Hi Jon,

I appreciate your review.  I will fold the suggestions from your short email plus 
this longer email into a v2 patch fairly soon.


Jon Turney wrote:

On 12/06/2021 07:46, Mark Geisert wrote:


diff --git a/winsup/utils/cygmon.cc b/winsup/utils/cygmon.cc
new file mode 100644
index 0..9156b27d7
--- /dev/null
+++ b/winsup/utils/cygmon.cc

[...]

+#include "../cygwin/include/sys/cygwin.h"
+#include "../cygwin/include/cygwin/version.h"
+#include "../cygwin/cygtls_padsize.h"
+#include "../cygwin/gcc_seh.h"


The latest Makefile.am sets things up so these relative paths aren't needed.


Oh yes, I saw those go by but have not made use of the changes.  Will do.


+typedef unsigned short ushort;
+typedef uint16_t u_int16_t; // to work around ancient gmon.h usage


'Non-standard sized type needed by ancient gmon.h' might be clearer


Indeed, thanks.  Will update.


+#include "../cygwin/gmon.h"

[...]

+size_t
+sample (HANDLE h)
+{
+  static CONTEXT *context = NULL;
+  size_t status;
+
+  if (!context)
+    {
+  context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
+  context->ContextFlags = CONTEXT_CONTROL;
+    }


Why isn't this just 'static CONTEXT'?

But it also shouldn't be static, because this function needs to be thread-safe as 
it is called by the profiler thread for every inferior process?


Oof, I must've gotten sidetracked off of coding the change from static to auto by 
a squirrel or a shiny disc or something.  Yes, the local context buffer needs to 
be thread-safe in case of multiple children being profiled.  I knew that...


[...]

+  else
+//TODO this approach might not support 32-bit executables on 64-bit


It definitely doesn't. But that's fine.


Will make the comment more definitive.

[...]

+void
+start_profiler (child *c)
+{
+  DWORD  tid;
+
+  if (verbose)
+    note ("*** start profiler thread on pid %lu\n", c->pid);
+  c->hquitevt = CreateEvent (NULL, TRUE, FALSE, NULL);
+  if (!c->hquitevt)
+    error (0, "unable to create quit event\n");
+  c->profiling = 1;
+  c->hprofthr = CreateThread (NULL, 0, profiler, (void *) c, 0, );
+  if (!c->hprofthr)
+    error (0, "unable to create profiling thread\n");
+
+//SetThreadPriority (c->hprofthr, THREAD_PRIORITY_TIME_CRITICAL); Don't do 
this!


But now I want to see what happens when I do!


You'll be sorry, but yeah the warning here is important because there's a real 
temptation here to do something, anything.. I'll make it more descriptive.


[...]

+  fd = open (filename, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY);

[...]

+  close (fd);
+  chmod (filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);//XXX ineffective


???


For the life of me I could not figure out how to make the output file mode 0644 
with either open() flags or chmod() afterwards.  I keep getting unwanted 'x' bits 
set.  Perhaps a side-effect of this being a native program rather than a Cygwin 
program.  I just flagged it until I can resolve it.


[...]

+void
+info_profile_file (char *filename)


I think this should be a separate tool, since it's not really part of the function 
of this tool.


Yeah, I guess so.  I didn't think of that option.  I just saw this as too big to 
be a Cygwin-specific patch to gprof, where it could plausibly go.  I will split 
this out to a separate tool called 'gmoninfo' or some such.  Suggestions welcome.


[...]

+IMAGE_SECTION_HEADER *
+find_text_section (LPVOID base, HANDLE h)
+{
+  static IMAGE_SECTION_HEADER asect;
+  DWORD  lfanew;
+  WORD   machine;
+  WORD   nsects;
+  DWORD  ntsig;
+  char  *ptr = (char *) base;
+
+  IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *) ptr;
+  read_child ((void *) , sizeof (lfanew), >e_lfanew, h);
+  ptr += lfanew;
+
+  /* Code handles 32- or 64-bit headers depending on compilation environment. 
*/
+  /*TODO It doesn't yet handle 32-bit headers on 64-bit Cygwin or v/v.    
*/
+  IMAGE_NT_HEADERS *inth = (IMAGE_NT_HEADERS *) ptr;
+  read_child ((void *) , sizeof (ntsig), >Signature, h);
+  if (ntsig != IMAGE_NT_SIGNATURE)
+    error (0, "find_text_section: NT signature not found\n");
+
+  read_child ((void *) , sizeof (machine),
+  >FileHeader.Machine, h);
+#ifdef __x86_64__
+  if (machine != IMAGE_FILE_MACHINE_AMD64)
+#else
+  if (machine != IMAGE_FILE_MACHINE_I386)
+#endif
+    error (0, "target program was built for different machine architecture\n");
+
+  read_child ((void *) , sizeof (nsects),
+  >FileHeader.NumberOfSections, h);
+  ptr += sizeof (*inth);
+
+  IMAGE_SECTION_HEADER *ish = (IMAGE_SECTION_HEADER *) ptr;
+  for (int i = 0; i < nsects; i++)
+    {
+  read_child ((void *) , sizeof (asect), ish, h);
+  if (0 == memcmp (".text\0\0\0", , 8))
+    return 
+  ish++;
+    }


While this is adequate and correct in 99% of cases, I think what you're perhaps 
looking for here is sec

Re: [PATCH] Cygwin: New tool: cygmon

2021-06-15 Thread Mark Geisert

Hi Jon,

Jon Turney wrote:

On 12/06/2021 07:46, Mark Geisert wrote:

This tool is a sampling profiler of Cygwin programs with their DLLs.
Presently its development is managed at https://github.com/mgeisert/cygmon.
Documentation of cygmon has been added to the usual doc/utils.xml file.


Nice!

How attached are you to the name?

There's nothing cygwin specific about this (you could profile any Windows 
executable), so does it really need 'cyg' in the name?


It's a profiler, so what is 'mon' short for?


I (thought I) was sort of riding on the ancient separation in Unix between 
generating the data and displaying it.  Back to Unix v6 the generating was done by 
something with "mon" in the name.. monitor() in the C library syscalling profil() 
to generate the data and write it to the file mon.out.  The separate program 
'prof' read a mon.out file and the corresponding executable to display the data.


Over time mon.out -> gmon.out, and prof -> gprof.  I presume those happened with 
GNU involvement.


So for Cygwin, I riffed on "gmon" by making the data generator, a program in this 
case, 'cygmon'.  gprof still applies as the way to display the data.



A more detailed review to follow.


I'm going over that review now.  Thanks!


There are a couple of one-line fixes to unrelated files for minor issues
noticed while implementing cygmon.  The files involved are gmon.c and
doc/utils.xml (one line not part of the cygmon updates to that file).


Please submit the gmon fix as a separate patch, ideally with some commentary about 
what it fixes.


Sure, will do.


diff --git a/winsup/doc/utils.xml b/winsup/doc/utils.xml
index 22bd86904..2f256d602 100644
--- a/winsup/doc/utils.xml
+++ b/winsup/doc/utils.xml

[...]

+
+    
+  Description
+    The cygmon utility executes a given program, and
+  optionally the children of that program, collecting the location of the
+  CPU instruction pointer (IP) many times per second. This gives a profile
+  of the program's execution, showing where the most time is being spent.
+  This profiling technique is called "IP sampling".


Contrasting this with how 'ssp' profiles (and vice versa there) would be nice.


Good idea.  Will do.


+
+    A novel feature of cygmon is that time spent in
+  DLLs loaded with or by your program is profiled too. You use
+  gprof to process and display the resulting profile
+  information. In this fashion you can determine whether your own code,
+  the Cygwin DLL, or another DLL has "hot spots" that might benefit from
+  tuning.
+
+     Note that cygmon is a native Windows program
+  and so does not rely on the Cygwin DLL itself (you can verify this with
+  cygcheck). As a result it does not understand
+  symlinks in its command line.
+    


Thanks,

..mark



[PATCH] Cygwin: New tool: cygmon

2021-06-12 Thread Mark Geisert
oes not understand
   symlinks. This program is mainly useful for debugging the Cygwin DLL
diff --git a/winsup/utils/cygmon.cc b/winsup/utils/cygmon.cc
new file mode 100644
index 0..9156b27d7
--- /dev/null
+++ b/winsup/utils/cygmon.cc
@@ -0,0 +1,1240 @@
+/*
+cygmon.cc
+Periodically samples IP of a process and its DLLs; writes gprof data files.
+
+Written by Mark Geisert , who admits to
+copying pretty liberally from strace.cc.  h/t to cgf for strace!
+
+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.
+*/
+
+#define WIN32_LEAN_AND_MEAN
+#include 
+#include 
+
+#define cygwin_internal cygwin_internal_dontuse
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../cygwin/include/sys/cygwin.h"
+#include "../cygwin/include/cygwin/version.h"
+#include "../cygwin/cygtls_padsize.h"
+#include "../cygwin/gcc_seh.h"
+typedef unsigned short ushort;
+typedef uint16_t u_int16_t; // to work around ancient gmon.h usage
+#include "../cygwin/gmon.h"
+#include "path.h"
+#undef cygwin_internal
+
+#define SCALE_SHIFT 2 // == 4 bytes of address space per bucket
+#define MS_VC_EXCEPTION 0x406D1388 // thread name notification from child
+
+DWORD   child_pid;
+int debugging = 0;
+void   *drive_map;
+int events = 0;
+int forkprofile = 0;
+int new_window;
+int numprocesses;
+FILE   *ofile = stdout;
+const char *pgm;
+char   *prefix = (char *) "gmon.out";
+int samplerate = 100; // in Hz; up to 1000 might work
+int verbose = 0;
+
+void __attribute__ ((__noreturn__))
+usage (FILE *where = stderr)
+{
+  fprintf (where, "\
+Usage: %s [OPTIONS] \n\
+   or: %s [OPTIONS] -p \n\
+   or: %s -i ...\n\
+\n\
+Profiles a command or process by sampling its IP (instruction pointer).\n\
+OPTIONS are:\n\
+\n\
+  -d, --debugDisplay debugging messages (toggle: default false)\n\
+  -e, --events   Display Windows DEBUG_EVENTS (toggle: default 
false)\n\
+  -f, --fork-profile Profile child processes (toggle: default false)\n\
+  -h, --help Display usage information and exit\n\
+  -i, --info=FILENAME(S) Display summary info about given profile data 
file(s)\n\
+  -o, --output=FILENAME  Write output to file FILENAME rather than stdout\n\
+  -p, --pid=NAttach to running program with Cygwin pid N\n\
+ ...or with Windows pid -N\n\
+  -s, --sample-rate=NSet IP sampling rate to N Hz (default 100)\n\
+  -v, --verbose  Display more status messages (toggle: default 
false)\n\
+  -V, --version  Display version information and exit\n\
+  -w, --new-window   Launch given command in a new window\n\
+\n", pgm, pgm, pgm);
+
+  exit (where == stderr ? 1 : 0 );
+}
+
+/* A span is a memory address range covering an EXE's or DLL's .text segment. 
*/
+struct span_list
+{
+  WCHAR  *name;
+  LPVOID  base;
+  size_t  textlo;
+  size_t  texthi;
+  int hitcount;
+  int hitbuckets;
+  int numbuckets;
+  int*buckets;
+  struct span_list *next;
+};
+
+/* A thread. */
+struct thread_list
+{
+  DWORD   tid;
+  HANDLE  hthread;
+  WCHAR  *name;
+  struct thread_list *next;
+};
+
+/* A child is any process being sampled in this cygmon run. */
+struct child_list
+{
+  DWORD  pid;
+  HANDLE hproc;
+  HANDLE hquitevt;
+  HANDLE hprofthr;
+  volatile int profiling;
+  struct thread_list *threads;
+  struct span_list   *spans;
+  struct child_list  *next;
+};
+
+child_list children;
+typedef struct child_list child;
+
+void
+note (const char *fmt, ...)
+{
+  va_list args;
+  charbuf[4096];
+
+  va_start (args, fmt);
+  vsprintf (buf, fmt, args);
+  va_end (args);
+
+  fputs (buf, ofile);
+  fflush (ofile);
+}
+
+void
+warn (int geterrno, const char *fmt, ...)
+{
+  va_list args;
+  charbuf[4096];
+
+  va_start (args, fmt);
+  sprintf (buf, "%s: ", pgm);
+  vsprintf (strchr (buf, '\0'), fmt, args);
+  va_end (args);
+  if (geterrno)
+perror (buf);
+  else
+{
+  fputs (buf, ofile);
+  fputs ("\n", ofile);
+  fflush (ofile);
+}
+}
+
+void __attribute__ ((noreturn))
+error (int geterrno, const char *fmt, ...)
+{
+  va_list args;
+
+  va_start (args, fmt);
+  warn (geterrno, fmt, args);
+  va_end (args);
+
+  exit (1);
+}
+
+size_t
+sample (HANDLE h)
+{
+  static CONTEXT *context = NULL;
+  size_t status;
+
+  if (!context)
+{
+  context = (CONTEXT *) calloc (1, sizeof (CONTEXT));
+  context->ContextFlags = CONTEXT_CONTROL;
+}
+
+  if (-1U == SuspendThread (h))
+return 0ULL;
+  status = GetThreadContext (h, context);
+  if (-1U == ResumeThread (h))
+if (verbose)
+  note ("*** unable to resume th

Re: [PATCH v2] Cygwin: Have tmpfile(3) use O_TMPFILE

2021-02-12 Thread Mark Geisert

Corinna Vinschen via Cygwin-patches wrote:
[...]

The patch was missing the EXPORT_ALIAS for tmpfile64, as outlined in
https://cygwin.com/pipermail/cygwin-developers/2021-February/012039.html
I added this to the patch and pushed it.


Oof, I missed that on the v2 patch.  Thanks for catching it!

..mark


[PATCH v2] Cygwin: Have tmpfile(3) use O_TMPFILE

2021-02-10 Thread Mark Geisert
Per discussion on cygwin-developers, a Cygwin tmpfile(3) implementation
has been added to syscalls.cc.  This overrides the one supplied by
newlib.  Then the open(2) flag O_TMPFILE was added to the open call that
tmpfile internally makes.

This v2 patch removes O_CREAT from open() call as O_TMPFILE obviates it.
Note that open() takes a directory's path but returns an fd to a file.
---
 winsup/cygwin/release/3.2.0 |  4 
 winsup/cygwin/syscalls.cc   | 17 +
 2 files changed, 21 insertions(+)

diff --git a/winsup/cygwin/release/3.2.0 b/winsup/cygwin/release/3.2.0
index f748a9bc8..d02d16863 100644
--- a/winsup/cygwin/release/3.2.0
+++ b/winsup/cygwin/release/3.2.0
@@ -19,6 +19,10 @@ What changed:
 
 - A few FAQ updates.
 
+- Have tmpfile(3) make use of Win32 FILE_ATTRIBUTE_TEMPORARY via open(2)
+  flag O_TMPFILE.
+  Addresses: https://cygwin.com/pipermail/cygwin/2021-January/247304.html
+
 
 Bug Fixes
 -
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 52a020f07..4cda69033 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -5225,3 +5225,20 @@ pipe2 (int filedes[2], int mode)
   syscall_printf ("%R = pipe2([%d, %d], %y)", res, read, write, mode);
   return res;
 }
+
+extern "C" FILE *
+tmpfile (void)
+{
+  char *dir = getenv ("TMPDIR");
+  if (!dir)
+dir = P_tmpdir;
+  int fd = open (dir, O_RDWR | O_BINARY | O_TMPFILE, S_IRUSR | S_IWUSR);
+  if (fd < 0)
+return NULL;
+  FILE *fp = fdopen (fd, "wb+");
+  int e = errno;
+  if (!fp)
+close (fd); // ..will remove tmp file
+  set_errno (e);
+  return fp;
+}
-- 
2.30.0



Re: [PATCH] Cygwin: Have tmpfile(3) use O_TMPFILE

2021-02-10 Thread Mark Geisert

Hi Corinna,

Corinna Vinschen via Cygwin-patches wrote:

Hi Mark,

On Feb  9 02:50, Mark Geisert wrote:

Per discussion on cygwin-developers, a Cygwin tmpfile(3) implementation
has been added to syscalls.cc.  This overrides the one supplied by
newlib.  Then the open(2) flag O_TMPFILE was added to the open call that
tmpfile internally makes.
---
  winsup/cygwin/release/3.2.0 |  4 
  winsup/cygwin/syscalls.cc   | 20 
  2 files changed, 24 insertions(+)

diff --git a/winsup/cygwin/release/3.2.0 b/winsup/cygwin/release/3.2.0
index f748a9bc8..d02d16863 100644
--- a/winsup/cygwin/release/3.2.0
+++ b/winsup/cygwin/release/3.2.0
@@ -19,6 +19,10 @@ What changed:
  
  - A few FAQ updates.
  
+- Have tmpfile(3) make use of Win32 FILE_ATTRIBUTE_TEMPORARY via open(2)

+  flag O_TMPFILE.
+  Addresses: https://cygwin.com/pipermail/cygwin/2021-January/247304.html
+
  
  Bug Fixes

  -
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 52a020f07..b79c1c7cd 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -5225,3 +5225,23 @@ pipe2 (int filedes[2], int mode)
syscall_printf ("%R = pipe2([%d, %d], %y)", res, read, write, mode);
return res;
  }
+
+extern "C" FILE *
+tmpfile (void)
+{
+  char *dir = getenv ("TMPDIR");


This isn't what Linux tmpfile does.  Per the man page, it tries to
create the file in P_tmpdir first, and if that fails, it tries
"/tmp".


Oops, I was following newlib's code here.  I'll adjust this.


+  if (!dir)
+dir = P_tmpdir;
+  int fd = open (dir, O_RDWR | O_CREAT | O_BINARY | O_TMPFILE,


You have to specify O_EXCL here.  The idea is that this file cannot be
made permanent, and missing the O_EXCL flag allows exactly that.  See
https://man7.org/linux/man-pages/man2/open.2.html, the lengthy
description in terms of O_TMPFILE.


I started out with O_EXCL as you suggested, but found syscalls.cc:1504 reporting 
EEXIST.  Is there some clash there between fh->exists() and O_TMPFILE?  Hmm.


..mark


[PATCH] Cygwin: Have tmpfile(3) use O_TMPFILE

2021-02-09 Thread Mark Geisert
Per discussion on cygwin-developers, a Cygwin tmpfile(3) implementation
has been added to syscalls.cc.  This overrides the one supplied by
newlib.  Then the open(2) flag O_TMPFILE was added to the open call that
tmpfile internally makes.
---
 winsup/cygwin/release/3.2.0 |  4 
 winsup/cygwin/syscalls.cc   | 20 
 2 files changed, 24 insertions(+)

diff --git a/winsup/cygwin/release/3.2.0 b/winsup/cygwin/release/3.2.0
index f748a9bc8..d02d16863 100644
--- a/winsup/cygwin/release/3.2.0
+++ b/winsup/cygwin/release/3.2.0
@@ -19,6 +19,10 @@ What changed:
 
 - A few FAQ updates.
 
+- Have tmpfile(3) make use of Win32 FILE_ATTRIBUTE_TEMPORARY via open(2)
+  flag O_TMPFILE.
+  Addresses: https://cygwin.com/pipermail/cygwin/2021-January/247304.html
+
 
 Bug Fixes
 -
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 52a020f07..b79c1c7cd 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -5225,3 +5225,23 @@ pipe2 (int filedes[2], int mode)
   syscall_printf ("%R = pipe2([%d, %d], %y)", res, read, write, mode);
   return res;
 }
+
+extern "C" FILE *
+tmpfile (void)
+{
+  char *dir = getenv ("TMPDIR");
+  if (!dir)
+dir = P_tmpdir;
+  int fd = open (dir, O_RDWR | O_CREAT | O_BINARY | O_TMPFILE,
+ S_IRUSR | S_IWUSR);
+  if (fd < 0)
+return NULL;
+  FILE *fp = fdopen (fd, "wb+");
+  int e = errno;
+  if (!fp)
+close (fd); // ..will remove file
+  set_errno (e);
+  return fp;
+}
+
+EXPORT_ALIAS (tmpfile, tmpfile64);
-- 
2.30.0



Re: [PATCH] Cygwin: Interim malloc speedup

2021-01-17 Thread Mark Geisert

Hi Corinna,
Happy New Year back at you!  I'm very glad to see you posting again!

Corinna Vinschen via Cygwin-patches wrote:

Hi Mark,

Happy New Year!

On Dec 21 20:53, Mark Geisert wrote:

Replaces function-level lock with data-level lock provided by existing
dlmalloc.  Sets up to enable dlmalloc's MSPACES, but does not yet enable
them due to visible but uninvestigated issues.

Single-thread applications may or may not see a performance gain,
depending on how heavily it uses the malloc functions.  Multi-thread
apps will likely see a performance gain.

[...]

diff --git a/winsup/cygwin/cygmalloc.h b/winsup/cygwin/cygmalloc.h
index 84bad824c..67a9f3b3f 100644
--- a/winsup/cygwin/cygmalloc.h
+++ b/winsup/cygwin/cygmalloc.h

[...]

+/* These defines tune the dlmalloc implementation in malloc.cc */
  # define MALLOC_FAILURE_ACTION__set_ENOMEM ()
  # define USE_DL_PREFIX 1
+# define USE_LOCKS 1


Just enabling USE_LOCKS looks wrong to me.  Before enabling USE_LOCKS,
you should check how the actual locking is performed.  For non WIN32,
that will be pthread_mutex_lock/unlock, which may not be feasible,
because it may break expectations during fork.


I did investigate this before setting it, and I've been running with '#define 
USE_LOCKS 1' for many weeks and haven't seen any memory issues of any kind. 
Malloc multi-thread stress testing, fork() stress testing, Cygwin DLL builds, 
Python and binutils builds, routine X usage; all OK.  (Once I straightened out 
sped-up mkimport to actually do what Jon T suggested, blush.)



What you may want to do is setting USE_LOCKS to 2, and defining your own
MLOCK_T/ACQUIRE_LOCK/... macros (in the `#if USE_LOCKS > 1' branch of
the malloc source, see lines 1798ff), using a type which is non-critical
during forking, as well as during process initialization.  Win32 fast
R/W Locks come to mind and adding them should be pretty straight-forward.
This may also allow MSPACES to work OOTB.


With '#define USE_LOCKS 1' the tangled mess of #if-logic in malloc.cc resolves on 
Cygwin to using pthread_mutex_locks, so that seems to be OK as-is unless what 
you're suggesting is preferable for speed (or MSPACES when I get to that).

+# define LOCK_AT_FORK 0


This looks dangerous.  You're removing the locking from fork entirely
*and* the lock isn't re-initialized in the child.  This reinitializing
was no problem before because mallock was NO_COPY, but it's a problem
now because the global malloc_state _gm_ isn't (and mustn't).  The
current implementation calling

   #if LOCK_AT_FORK
   pthread_atfork(_fork, _fork_parent, _fork_child);
   #endif

should do the trick, assuming the USE_LOCKS stuff is working as desired.


I don't remember what led me to #define LOCK_AT_FORK 0, but in the new light of 
this year it's obviously wrong.  I've #define'd it 1.



[...]
+#if MSPACES
+/* If mspaces (thread-specific memory pools) are enabled, use a thread-
+   local variable to store a pointer to the calling thread's mspace.
+
+   On any use of a malloc-family function, if the appropriate mspace cannot
+   be determined, the general (non-mspace) form of the corresponding malloc
+   function is substituted.  This is not expected to happen often.
+*/
+static NO_COPY DWORD tls_mspace; // index into thread's TLS array
+
+static void *
+get_current_mspace ()
+{
+  if (unlikely (tls_mspace == 0))
+return 0;
+
+  void *m = TlsGetValue (tls_mspace);
+  if (unlikely (m == 0))
+{
+  m = create_mspace (MSPACE_SIZE, 0);
+  if (!m)
+return 0;
+  TlsSetValue (tls_mspace, m);
+}
+  return m;
+}
+#endif


Please define a new slot in _cygtls keeping the memory address returned
by create_mspace.  You don't have to call TlsGetValue/TlsSetValue.


Thank you for repeating this suggestion.  I now understand why it's better.

I'm going to delay submitting the v2 patch until I see where the investigation of 
Achim's malloc testcase (running zstd on 1600 files, for instance) leads.  I'm 
about to respond to his thread in cygwin-apps.

Thanks & Regards,

..mark


Re: [PATCH] Cygwin: Interim malloc speedup -- addendum

2020-12-24 Thread Mark Geisert
I could easily provide an updated patch without the MSPACES stuff, given that that 
aspect is not really functional at this point.  Just let me know.


..mark


[PATCH] Cygwin: Interim malloc speedup

2020-12-21 Thread Mark Geisert
Replaces function-level lock with data-level lock provided by existing
dlmalloc.  Sets up to enable dlmalloc's MSPACES, but does not yet enable
them due to visible but uninvestigated issues.

Single-thread applications may or may not see a performance gain,
depending on how heavily it uses the malloc functions.  Multi-thread
apps will likely see a performance gain.

---
 winsup/cygwin/cygmalloc.h   |  28 +++-
 winsup/cygwin/fork.cc   |   8 -
 winsup/cygwin/malloc_wrapper.cc | 274 +---
 3 files changed, 202 insertions(+), 108 deletions(-)

diff --git a/winsup/cygwin/cygmalloc.h b/winsup/cygwin/cygmalloc.h
index 84bad824c..67a9f3b3f 100644
--- a/winsup/cygwin/cygmalloc.h
+++ b/winsup/cygwin/cygmalloc.h
@@ -26,20 +26,36 @@ void dlmalloc_stats ();
 #define MALLOC_ALIGNMENT ((size_t)16U)
 #endif
 
+/* As of Cygwin 3.2.0 we could enable dlmalloc's MSPACES */
+#define MSPACES 0 // DO NOT ENABLE: cygserver, XWin, etc will malfunction
+
 #if defined (DLMALLOC_VERSION) /* Building malloc.cc */
 
 extern "C" void __set_ENOMEM ();
 void *mmap64 (void *, size_t, int, int, int, off_t);
 # define mmap mmap64
+
+/* These defines tune the dlmalloc implementation in malloc.cc */
 # define MALLOC_FAILURE_ACTION __set_ENOMEM ()
 # define USE_DL_PREFIX 1
+# define USE_LOCKS 1
+# define LOCK_AT_FORK 0
+# define FOOTERS MSPACES
+#endif
 
-#elif defined (__INSIDE_CYGWIN__)
-
-# define __malloc_lock() mallock.acquire ()
-# define __malloc_unlock() mallock.release ()
-extern muto mallock;
-
+#if MSPACES
+# define MSPACE_SIZE (512 * 1024)
+void __reg2 *create_mspace (size_t, int);
+void __reg2 mspace_free (void *m, void *p);
+void __reg2 *mspace_malloc (void *m, size_t size);
+void __reg3 *mspace_realloc (void *m, void *p, size_t size);
+void __reg3 *mspace_calloc (void *m, size_t nmemb, size_t size);
+void __reg3 *mspace_memalign (void *m, size_t alignment, size_t bytes);
+size_t __reg1 mspace_usable_size (const void *p);
+int __reg2 mspace_trim (void *m, size_t);
+int __reg2 mspace_mallopt (int p, int v);
+void __reg1 mspace_malloc_stats (void *m);
+struct mallinfo mspace_mallinfo (void *m);
 #endif
 
 #ifdef __cplusplus
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 719217856..8f9ca45d1 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -22,7 +22,6 @@ details. */
 #include "tls_pbuf.h"
 #include "shared_info.h"
 #include "dll_init.h"
-#include "cygmalloc.h"
 #include "ntdll.h"
 
 #define NPIDS_HELD 4
@@ -296,8 +295,6 @@ frok::parent (volatile char * volatile stack_here)
   si.lpReserved2 = (LPBYTE) 
   si.cbReserved2 = sizeof (ch);
 
-  bool locked = __malloc_lock ();
-
   /* Remove impersonation */
   cygheap->user.deimpersonate ();
   fix_impersonation = true;
@@ -448,9 +445,6 @@ frok::parent (volatile char * volatile stack_here)
   "stack", stack_here, ch.stackbase,
   impure, impure_beg, impure_end,
   NULL);
-
-  __malloc_unlock ();
-  locked = false;
   if (!rc)
 {
   this_errno = get_errno ();
@@ -533,8 +527,6 @@ cleanup:
 
   if (fix_impersonation)
 cygheap->user.reimpersonate ();
-  if (locked)
-__malloc_unlock ();
 
   /* Remember to de-allocate the fd table. */
   if (hchild)
diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc
index 3b245800a..51dbf8a59 100644
--- a/winsup/cygwin/malloc_wrapper.cc
+++ b/winsup/cygwin/malloc_wrapper.cc
@@ -27,6 +27,34 @@ extern "C" struct mallinfo dlmallinfo ();
 static bool use_internal = true;
 static bool internal_malloc_determined;
 
+#if MSPACES
+/* If mspaces (thread-specific memory pools) are enabled, use a thread-
+   local variable to store a pointer to the calling thread's mspace.
+
+   On any use of a malloc-family function, if the appropriate mspace cannot
+   be determined, the general (non-mspace) form of the corresponding malloc
+   function is substituted.  This is not expected to happen often.
+*/
+static NO_COPY DWORD tls_mspace; // index into thread's TLS array
+
+static void *
+get_current_mspace ()
+{
+  if (unlikely (tls_mspace == 0))
+return 0;
+
+  void *m = TlsGetValue (tls_mspace);
+  if (unlikely (m == 0))
+{
+  m = create_mspace (MSPACE_SIZE, 0);
+  if (!m)
+return 0;
+  TlsSetValue (tls_mspace, m);
+}
+  return m;
+}
+#endif
+
 /* These routines are used by the application if it
doesn't provide its own malloc. */
 
@@ -34,28 +62,40 @@ extern "C" void
 free (void *p)
 {
   malloc_printf ("(%p), called by %p", p, caller_return_address ());
-  if (!use_internal)
-user_data->free (p);
-  else
+  if (likely (use_internal))
 {
-  __malloc_lock ();
+#if MSPACES
+  void *m = get_current_mspace ();
+  if (likely (m))
+   mspace_free (m, p);
+  else
+   dlfree (p);
+#else
   dlfree (p);
-  __malloc_unlock ();
+#endif
 }
+  else
+user_data->free (p);
 }
 
 extern "C" void *
 malloc (size_t size)
 {
   void *res;
-  if 

[PATCH] Cygwin: Allow to set SO_PEERCRED zero (v2)

2020-12-07 Thread Mark Geisert
The existing code errors as EINVAL any attempt to set a value for
SO_PEERCRED via setsockopt() on an AF_UNIX/AF_LOCAL socket.  But to
enable the workaround set_no_getpeereid behavior for Python one has
to be able to set SO_PEERCRED to zero.  Ergo, this patch.  Python has
no way to specify a NULL pointer for 'optval'.

This v2 of patch allows the original working (i.e., allow NULL,0 for
optval,optlen to mean turn off SO_PEERCRED) in addition to the new
working described above.  The sense of the 'if' stmt is reversed for
readability.

---
 winsup/cygwin/fhandler_socket_local.cc | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/fhandler_socket_local.cc 
b/winsup/cygwin/fhandler_socket_local.cc
index c94bf828f..964f3e819 100644
--- a/winsup/cygwin/fhandler_socket_local.cc
+++ b/winsup/cygwin/fhandler_socket_local.cc
@@ -1430,10 +1430,14 @@ fhandler_socket_local::setsockopt (int level, int 
optname, const void *optval,
 FIXME: In the long run we should find a more generic solution
 which doesn't require a blocking handshake in accept/connect
 to exchange SO_PEERCRED credentials. */
- if (optval || optlen)
-   set_errno (EINVAL);
- else
+ /* Temporary: Allow SO_PEERCRED to only be zeroed. Two ways to
+accomplish this: pass NULL,0 for optval,optlen; or pass the
+address,length of an '(int) 0' set up by the caller. */
+ if ((!optval && !optlen) ||
+   (optlen == (socklen_t) sizeof (int) && !*(int *) optval))
ret = af_local_set_no_getpeereid ();
+ else
+   set_errno (EINVAL);
  return ret;
 
case SO_REUSEADDR:
-- 
2.29.2



[PATCH] Cygwin: Allow to set SO_PEERCRED zero

2020-12-06 Thread Mark Geisert
The existing code errors as EINVAL any attempt to set a value for
SO_PEERCRED via setsockopt() on an AF_UNIX/AF_LOCAL socket.  But to
enable the workaround set_no_getpeereid behavior for Python one has
to be able to set SO_PEERCRED to zero.  Ergo, this patch.  Python has
no way to specify a NULL pointer for 'optval'.

---
 winsup/cygwin/fhandler_socket_local.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/fhandler_socket_local.cc 
b/winsup/cygwin/fhandler_socket_local.cc
index c94bf828f..421b8bbdb 100644
--- a/winsup/cygwin/fhandler_socket_local.cc
+++ b/winsup/cygwin/fhandler_socket_local.cc
@@ -1430,7 +1430,8 @@ fhandler_socket_local::setsockopt (int level, int 
optname, const void *optval,
 FIXME: In the long run we should find a more generic solution
 which doesn't require a blocking handshake in accept/connect
 to exchange SO_PEERCRED credentials. */
- if (optval || optlen)
+ /* Temporary: Allow only '(int) 0' to be specified. */
+ if (optlen < (socklen_t) sizeof (int) || 0 != *(int *) optval)
set_errno (EINVAL);
  else
ret = af_local_set_no_getpeereid ();
-- 
2.29.2



[PATCH] Cygwin: Launch cygmagic with bash, not sh

2020-12-06 Thread Mark Geisert
On some systems /bin/sh is not /bin/bash and cygmagic has bash-isms in
it.  So even though cygmagic has a /bin/bash shebang, it also needs to be
launched with bash from within Makefile.in.

---
 winsup/cygwin/Makefile.in | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index b15c746cf..a840f2b83 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -683,10 +683,10 @@ globals.h: mkglobals_h globals.cc
 ${DLL_OFILES} ${LIBCOS}: globals.h $(srcdir)/$(TLSOFFSETS_H)
 
 shared_info_magic.h: cygmagic shared_info.h
-   /bin/sh $(word 1,$^) $@ "${COMPILE.cc} -E -x c++" $(word 2,$^) 
SHARED_MAGIC 'class shared_info' USER_MAGIC 'class user_info'
+   /bin/bash $(word 1,$^) $@ "${COMPILE.cc} -E -x c++" $(word 2,$^) 
SHARED_MAGIC 'class shared_info' USER_MAGIC 'class user_info'
 
 child_info_magic.h: cygmagic child_info.h
-   /bin/sh $(word 1,$^) $@ "${COMPILE.cc} -E -x c++" $(word 2,$^) 
CHILD_INFO_MAGIC 'class child_info'
+   /bin/bash $(word 1,$^) $@ "${COMPILE.cc} -E -x c++" $(word 2,$^) 
CHILD_INFO_MAGIC 'class child_info'
 
 dcrt0.o sigproc.o: child_info_magic.h
 
-- 
2.29.2



Re: [PATCH] Cygwin: Speed up mkimport

2020-11-27 Thread Mark Geisert

Jon Turney wrote:

On 26/11/2020 09:56, Mark Geisert wrote:

@@ -86,8 +94,18 @@ for my $f (keys %text) {
  if (!$text{$f}) {
  unlink $f;
  } else {
-    system $objcopy, '-R', '.text', $f and exit 1;
-    system $objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1;
+    if ($forking && fork) {
+    # Testing shows parent does need to sleep a short time here,
+    # otherwise system is inundated with hundreds of objcopy processes
+    # and the forked perl processes that launched them.
+    my $delay = 0.01; # NOTE: Slower systems may need to raise this
+    select(undef, undef, undef, $delay); # Supports fractional seconds
+    } else {
+    # Do two objcopy calls at once to avoid one system() call overhead
+    system '(', $objcopy, '-R', '.text', $f, ')', '||',
+    $objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1;
+    exit 0 if $forking;
+    }
  }
  }


Hmm... not so sure about this.  This seems racy, as nothing ensures that these 
objcopies have finished before we combine all the produced .o files into a library.


Good point.  I've added a hash to track the forked pids, and after each of these 
two time-consuming loops finishes I loop over the pids list doing waitpid() on 
each pid.


I'm pretty sure with more understanding, this whole thing could be done better:  
For example, from a brief look, it seems that the t-*.o files are produced by gas, 
and then we remove .bss and .data sections.  Could we not arrange to assemble 
these objects without those sections in the first place?


I looked over as's options in its man page but could not see anything obvious.  I 
wonder if defining the sections explicitly as zero-length somehow in mkimport's 
assembler snippets would accomplish the same thing.  I'll try this next.


Note that mkimport operates both on those tiny object files it creates with as, 
but also on the object files created by the whole Cygwin build.  So adjusting the 
latter object files would need to be done somewhere else.

Thanks,

..mark



Re: [PATCH] Cygwin: Speed up mkimport

2020-11-27 Thread Mark Geisert

Achim Gratz wrote:

Mark Geisert writes:

+   # Do two objcopy calls at once to avoid one system() call overhead
+   system '(', $objcopy, '-R', '.text', $f, ')', '||',
+   $objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1;


That doesn't do what you think it does.  It in fact increases the
overhead since it'll start a shell that runs those two commands sand
will even needlessly start the first objcopy in a subshell.


Still faster than two system commands :-).  But thanks for the comment; I thought 
I was merely grouping args, to get around Perl's greedy arg list building for the 
system command.  After more experimenting I ended up with:

system '/bin/true', '||', $objcopy, '-R', '.text', $f, '||',
$objcopy, '-R', '.bss', '-R', '.data', "t-$f" and exit 1;
Kind of ugly, but better?  It obviates the need for parent to pace itself so the 
enclosing loop runs a bit faster.


..mark


Re: [PATCH] Cygwin: Speed up mkimport

2020-11-26 Thread Mark Geisert

Previously, Mark Geisert wrote:

Cut mkimport elapsed time in half by forking each iteration of the two
time-consuming loops within.  Only do this if more than one CPU is
present.  In the second loop, combine the two 'objdump' calls into one

 ^^^
That should say objcopy.  The code is correct though.

..mark


[PATCH] Cygwin: Speed up mkimport

2020-11-26 Thread Mark Geisert
Cut mkimport elapsed time in half by forking each iteration of the two
time-consuming loops within.  Only do this if more than one CPU is
present.  In the second loop, combine the two 'objdump' calls into one
system() invocation to avoid a system() invocation per iteration.

---
 winsup/cygwin/mkimport | 34 ++
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/winsup/cygwin/mkimport b/winsup/cygwin/mkimport
index 2b08dfe3d..919dc305b 100755
--- a/winsup/cygwin/mkimport
+++ b/winsup/cygwin/mkimport
@@ -47,6 +47,9 @@ for my $sym (keys %replace) {
 $import{$fn} = $imp_sym;
 }
 
+my $ncpus = `grep -c ^processor /proc/cpuinfo`;
+my $forking = $ncpus > 1; # Decides if loops below should fork() each iteration
+
 for my $f (keys %text) {
 my $imp_sym = delete $import{$f};
 my $glob_sym = $text{$f};
@@ -56,25 +59,30 @@ for my $f (keys %text) {
$text{$f} = 0;
 } else {
$text{$f} = 1;
-   open my $as_fd, '|-', $as, '-o', "$dir/t-$f", "-";
-   if ($is64bit) {
-   print $as_fd <

Re: [PATCH v2 0/6] Some AF_UNIX fixes

2020-10-14 Thread Mark Geisert

Ken Brown via Cygwin-patches wrote:
Are you aware of any test suite that I could run?  I've been using examples from 
Kerrisk's book, because that's what I read to learn the basics of sockets.  But 
those are just examples and are not meant to be comprehensive.


In ye olden days I used to use Stevens+Rago "Advanced Programming In The Unix 
Environment, 2nd ed.".  Chapter 17 covers UNIX domain sockets as advanced IPC. 
It's more examples but maybe they hit different corners of the playing field.  I 
don't know of a test suite or even a standalone program that exercises AF_UNIX.


..mark


Re: [PATCH] Cygwin: malloc tune-up

2020-08-25 Thread Mark Geisert

Hi Corinna,
Well, this patch turned out to be half-baked.  Locking is working correctly 
because USE_LOCKS was set to 1 for malloc.cc's compilation.  The torture test I 
run validated that.  OTOH as you said, MSPACES was set 1 for malloc.cc but 0 for 
malloc_wrapper.cc.  So this patch yields a malloc facility like pre-3.2 but 
using internal locking on data structures instead of function-level locking.  An 
improvement, but not the whole package that I'm attempting to deliver because 
there's still thread contention on the internal locks.  Properly operating 
mspaces should get rid of that or at least lower it significantly.


I appreciate your comments on TLS variables and fork safety.  I will investigate 
this area further.  The mspaces should/will survive a fork but obviously the 
threads that created them won't.  Memory blocks can be freed by any thread; 
there's no need to create threads in the child process just to manage mspaces.


I have more work to do then I'll submit a v2 of the patch.
Thanks & Regards,

..mark


[PATCH] Cygwin: malloc tune-up

2020-08-23 Thread Mark Geisert
1. Replace global malloc lock with finer-grained internal locks.
2. Enable MSPACES, i.e. thread-specific memory pools.

Porting and testing of several dlmalloc-related malloc implementations
(ptmalloc, ptmalloc2, ptmalloc3, nedalloc) shows that they are no faster
than the current dlmalloc used by Cygwin, when the latter is tuned.  This
could be because the others are forks of earlier dlmalloc versions.  For
the record, I could not get jemalloc or tcmalloc running at all due to
chicken-egg issues, nor could I get a Win32 Heap-based malloc to work
across fork(), which was expected.

I think I can see a way to get Win32 Heap-based malloc to work across
fork()s, but it would depend on undocumented info and would likely be
subject to breakage in future Windows versions.  Too bad, because that
form of malloc package would be 2 to 8 times faster in practice.

---
 winsup/cygwin/cygmalloc.h   |  21 +++-
 winsup/cygwin/fork.cc   |   7 --
 winsup/cygwin/malloc_wrapper.cc | 163 +++-
 3 files changed, 113 insertions(+), 78 deletions(-)

diff --git a/winsup/cygwin/cygmalloc.h b/winsup/cygwin/cygmalloc.h
index 84bad824c..302ce59c8 100644
--- a/winsup/cygwin/cygmalloc.h
+++ b/winsup/cygwin/cygmalloc.h
@@ -33,15 +33,30 @@ void *mmap64 (void *, size_t, int, int, int, off_t);
 # define mmap mmap64
 # define MALLOC_FAILURE_ACTION __set_ENOMEM ()
 # define USE_DL_PREFIX 1
+# define USE_LOCKS 1
+# define MSPACES 1
+# define FOOTERS 1
 
 #elif defined (__INSIDE_CYGWIN__)
 
-# define __malloc_lock() mallock.acquire ()
-# define __malloc_unlock() mallock.release ()
-extern muto mallock;
+# define MSPACES 0
 
 #endif
 
+#if MSPACES
+void __reg2 *create_mspace (size_t, int);
+void __reg2 mspace_free (void *m, void *p);
+void __reg2 *mspace_malloc (void *m, size_t size);
+void __reg3 *mspace_realloc (void *m, void *p, size_t size);
+void __reg3 *mspace_calloc (void *m, size_t nmemb, size_t size);
+void __reg3 *mspace_memalign (void *m, size_t alignment, size_t bytes);
+void __reg2 *mspace_valloc (void *m, size_t bytes);
+size_t __reg1 mspace_usable_size (const void *p);
+int __reg2 mspace_malloc_trim (void *m, size_t);
+int __reg2 mspace_mallopt (int p, int v);
+void __reg1 mspace_malloc_stats (void *m);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 38172ca1e..82f95dafe 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -296,8 +296,6 @@ frok::parent (volatile char * volatile stack_here)
   si.lpReserved2 = (LPBYTE) 
   si.cbReserved2 = sizeof (ch);
 
-  bool locked = __malloc_lock ();
-
   /* Remove impersonation */
   cygheap->user.deimpersonate ();
   fix_impersonation = true;
@@ -448,9 +446,6 @@ frok::parent (volatile char * volatile stack_here)
   "stack", stack_here, ch.stackbase,
   impure, impure_beg, impure_end,
   NULL);
-
-  __malloc_unlock ();
-  locked = false;
   if (!rc)
 {
   this_errno = get_errno ();
@@ -533,8 +528,6 @@ cleanup:
 
   if (fix_impersonation)
 cygheap->user.reimpersonate ();
-  if (locked)
-__malloc_unlock ();
 
   /* Remember to de-allocate the fd table. */
   if (hchild)
diff --git a/winsup/cygwin/malloc_wrapper.cc b/winsup/cygwin/malloc_wrapper.cc
index 3b245800a..f1c23b4a8 100644
--- a/winsup/cygwin/malloc_wrapper.cc
+++ b/winsup/cygwin/malloc_wrapper.cc
@@ -27,6 +27,33 @@ extern "C" struct mallinfo dlmallinfo ();
 static bool use_internal = true;
 static bool internal_malloc_determined;
 
+/* If MSPACES (thread-specific memory pools) are enabled, use a
+   thread-local variable to store a pointer to that thread's mspace.
+ */
+#if MSPACES
+static DWORD tls_mspace; // index into thread's TLS array
+#define MSPACE_SIZE (8 * 1024 * 1024)
+
+static void *
+get_current_mspace ()
+{
+  if (unlikely(tls_mspace == 0))
+api_fatal ("a malloc-related function was called before malloc_init");
+
+  void *m = TlsGetValue (tls_mspace);
+  if (unlikely(m == 0))
+{
+  m = create_mspace (MSPACE_SIZE, 0);
+  if (!m)
+api_fatal ("unable to create mspace");
+  TlsSetValue (tls_mspace, m);
+}
+  return m;
+}
+
+#define MSPACE get_current_mspace()
+#endif
+
 /* These routines are used by the application if it
doesn't provide its own malloc. */
 
@@ -37,11 +64,11 @@ free (void *p)
   if (!use_internal)
 user_data->free (p);
   else
-{
-  __malloc_lock ();
-  dlfree (p);
-  __malloc_unlock ();
-}
+#if MSPACES
+mspace_free (MSPACE, p);
+#else
+dlfree (p);
+#endif
 }
 
 extern "C" void *
@@ -51,11 +78,11 @@ malloc (size_t size)
   if (!use_internal)
 res = user_data->malloc (size);
   else
-{
-  __malloc_lock ();
-  res = dlmalloc (size);
-  __malloc_unlock ();
-}
+#if MSPACES
+res = mspace_malloc (MSPACE, size);
+#else
+res = dlmalloc (size);
+#endif
   malloc_printf ("(%ld) = %p, called by %p", size, res,
   

Re: Cygwin 3.1.6

2020-07-06 Thread Mark Geisert

Corinna Vinschen wrote:

Hi guys,

Do you have anything in the loop which should go into 3.1.6?


Nothing from me, thanks.

..mark


Re: [PATCH 1/3 v3] Cygwin: tzcode resync: basics

2020-06-09 Thread Mark Geisert

Hi Brian,

On Tue, 9 Jun 2020, Brian Inglis wrote:

On 2020-05-26 02:27, Corinna Vinschen wrote:

On May 26 00:09, Mark Geisert wrote:

Corinna Vinschen wrote:

On May 22 02:32, Mark Geisert wrote:

On May 25 14:06, Corinna Vinschen wrote:


Hi folks,

The tzcode package needs updated to get fixes into zic and zdump.
Also tzdata was maintained by Yaakov.

Corinna, would you like to keep tzcode co-maintained with Yaakov?

Or Mark, would you like to ITA tzcode and/or tzdata to keep it in sync with the
base code?

Or would you like me to ITA tzcode and/or tzdata?
I currently check tzdb weekly in cron to download updates for my own interests.
I could add cygport builds to that job.


This "tzcode" patch I did was a one-shot task just getting some time zone 
handling code within the Cygwin DLL up to date.  I don't know if there's 
any overlap between what I worked on and the tzcode+tzdata packages.  Eh, 
just the internal binary copy of a particular tzdata file which should be 
kept up to date: /usr/share/zoneinfo/posixrules.  Dunno how often that 
changes though.


It's fine with me for you to take over both tzcode+tzdata if nobody else 
objects.  Sounds like you have a regular schedule for looking over updates 
which is more than I have :-).

Cheers,

..mark


Re: [PATCH 1/3 v3] Cygwin: tzcode resync: basics

2020-05-26 Thread Mark Geisert

Hi Corinna,

Corinna Vinschen wrote:

Hi Mark,


On May 22 02:32, Mark Geisert wrote:

On May 25 14:06, Corinna Vinschen wrote:

Modifies winsup/cygwin/Makefile.in to build localtime.o from items in
new winsup/cygwin/tzcode subdirectory.  Compiler option "-fpermissive"
is used to accept warnings about missing casts on the return values of
malloc() calls.  This patch also removes existing localtime.cc and
tz_posixrules.h from winsup/cygwin as they are superseded by the
subsequent patches in this set.
[...]
@@ -246,6 +246,15 @@ MATH_OFILES:= \
tgammal.o \
truncl.o
  
+TZCODE_OFILES:=localtime.o

+
+localtime.o: $(srcdir)/tzcode/localtime.cc $(srcdir)/tzcode/localtime.c.patch
+   (cd $(srcdir)/tzcode && \
+   patch -u -o localtime.c.patched localtime.c localtime.c.patch)
+   $(CXX) ${CXXFLAGS} ${localtime_CFLAGS} \
+   -I$(target_builddir)/winsup/cygwin \
+   -I$(srcdir) -I$(srcdir)/tzcode -c -o $@ $<
+


This doesn't work well for me.  That rule is the top rule in Makefile.in
now, so just calling `make' doesn't build the DLL anymore, only
localtime.o.  The rule should get moved way down Makefile.in.


Oops.  My workflow didn't make this apparent to me.  Thanks for the fix.


What still bugs me is that we get these -fpermissive warnings (albeit
non-fatal) and the fact that we don't get a dependencies file.  On
second thought, there's no good reason to keep localtime.cc a C++ file.
Converting this file to a plain C wrapper drops the C++-specific warning
and thus allows to revert the localtime.o build rule to use ${COMMON_CFLAGS}.

So I took the liberty to tweak your patch a bit.  I created a followup
patchset, which I'd like you to take a look at.

I attached the followup patches to this mail.  Please scrutinize it and
don't hesitate to discuss the changes.  For a start:

- I do not exactly like the name "localtime_wrapper.c" but I don't
   have a better idea.


localtime_cygwin.c?  cyglocaltime.c?  Not much nicer IMO.


- muto's are C++-only, so I changed rwlock_wrlock/rwlock_unlock to use
   Windows SRWLocks.  I think this is a good thing and I'm inclined
   to drop the muto datatype entirely in favor of using SRWLocks since
   they are cleaner and langauge-agnostic.


Two changes in my patchset:

- I didn't initialize the SRWLOCK following the books.  Fixed that.

- Rather than creating the patched file in the source dir, I changed
   the Makefile.in rule so that the patched file is created in the build
   dir.  This drops the requirement to tweak .gitignore.  It's also
   cleaner.

- Splitting the build rule for localtime.c.patched from the build rule
   for localtime.o makes sure that the patched file is not regenerated
   every time we build localtime.o.

I attached my patchset again, but only patch 3 and 4 actually changed.


All the above are great improvements.  But I would now remove the "// Get ready 
to wrap NetBSD's localtime.c" line and blank line following it.  Good to go!

Thank you,

..mark


[PATCH 1/3 v3] Cygwin: tzcode resync: basics

2020-05-22 Thread Mark Geisert
Modifies winsup/cygwin/Makefile.in to build localtime.o from items in
new winsup/cygwin/tzcode subdirectory.  Compiler option "-fpermissive"
is used to accept warnings about missing casts on the return values of
malloc() calls.  This patch also removes existing localtime.cc and
tz_posixrules.h from winsup/cygwin as they are superseded by the
subsequent patches in this set.

---
 winsup/cygwin/Makefile.in |   15 +-
 winsup/cygwin/localtime.cc| 2597 -
 winsup/cygwin/tz_posixrules.h |   48 -
 3 files changed, 12 insertions(+), 2648 deletions(-)
 delete mode 100644 winsup/cygwin/localtime.cc
 delete mode 100644 winsup/cygwin/tz_posixrules.h

diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index f273ba793..2ac8bcbd8 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -27,7 +27,7 @@ export CCWRAP_HEADERS:=. ${srcdir}
 export CCWRAP_SYSTEM_HEADERS:=@cygwin_headers@ @newlib_headers@
 export CCWRAP_DIRAFTER_HEADERS:=@windows_headers@
 
-VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math
+VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math 
$(srcdir)/tzcode
 
 target_cpu:=@target_cpu@
 target_alias:=@target_alias@
@@ -246,6 +246,15 @@ MATH_OFILES:= \
tgammal.o \
truncl.o
 
+TZCODE_OFILES:=localtime.o
+
+localtime.o: $(srcdir)/tzcode/localtime.cc $(srcdir)/tzcode/localtime.c.patch
+   (cd $(srcdir)/tzcode && \
+   patch -u -o localtime.c.patched localtime.c localtime.c.patch)
+   $(CXX) ${CXXFLAGS} ${localtime_CFLAGS} \
+   -I$(target_builddir)/winsup/cygwin \
+   -I$(srcdir) -I$(srcdir)/tzcode -c -o $@ $<
+
 DLL_OFILES:= \
advapi32.o \
aio.o \
@@ -333,7 +342,6 @@ DLL_OFILES:= \
ldap.o \
libstdcxx_wrapper.o \
loadavg.o \
-   localtime.o \
lsearch.o \
malloc_wrapper.o \
minires-os-if.o \
@@ -412,6 +420,7 @@ DLL_OFILES:= \
$(EXTRA_OFILES) \
$(MALLOC_OFILES) \
$(MATH_OFILES) \
+   $(TZCODE_OFILES) \
$(MT_SAFE_OBJECTS)
 
 EXCLUDE_STATIC_OFILES:=$(addprefix --exclude=,\
@@ -559,7 +568,7 @@ TARGET_LIBS:=$(LIB_NAME) $(CYGWIN_START) $(GMON_START) 
$(LIBGMON_A) $(SUBLIBS) $
 
 ifneq "${filter -O%,$(CFLAGS)}" ""
 dtable_CFLAGS:=-fcheck-new
-localtime_CFLAGS:=-fwrapv
+localtime_CFLAGS:=-fwrapv -fpermissive
 malloc_CFLAGS:=-O3
 sync_CFLAGS:=-O3
 ifeq ($(target_cpu),i686)
diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
deleted file mode 100644
index 010376637..0
--- a/winsup/cygwin/localtime.cc
+++ /dev/null
@@ -1,2597 +0,0 @@
-/* $NetBSD: localtime.c,v 1.72 2012/10/28 19:02:29 christos Exp $  */
-
-/* Don't reformat the code arbitrarily.
-
-   It uses in wide parts the exact formatting as the upstream NetBSD
-   versions.  The purpose is to simplify subsequent diffs to the NetBSD
-   version, should the need arise again at one point. */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-/* Temporarily merged private.h and tzfile.h for ease of management - DJ */
-
-#include "winsup.h"
-#include "cygerrno.h"
-#include "sync.h"
-#include 
-#define STD_INSPIRED
-#define lint
-
-#define USG_COMPAT
-
-#ifndef lint
-#ifndef NOID
-static charelsieid[] = "@(#)localtime.c8.17";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
-*/
-
-#define NO_ERROR_IN_DST_GAP
-
-/*LINTLIBRARY*/
-
-#ifndef PRIVATE_H
-
-#define PRIVATE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static charprivatehid[] = "@(#)private.h   7.48";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Nested includes
-*/
-
-#include "stdio.h"
-#include "limits.h"/* for CHAR_BIT */
-#include "stdlib.h"
-#include "unistd.h"/* for F_OK and R_OK */
-
-/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
-#ifndef __pure
-#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
-# define __pure __attribute__ ((__pure__))
-#else
-# define __pure /* empty */
-#endif
-#endif
-
-/*
-** Finally, some convenience items.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (/*CONSTCOND*/((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
-#ifndef 

[PATCH 3/3 v3] Cygwin: tzcode resync: details

2020-05-22 Thread Mark Geisert
Add tz_posixrules.h with data generated from most recent Cygwin tzdata
package.  Establish localtime.cc as primarily a wrapper around a patched
copy of localtime.c.  See README for more information.

---
 winsup/cygwin/tzcode/README|  37 
 winsup/cygwin/tzcode/localtime.c.patch |  59 +++
 winsup/cygwin/tzcode/localtime.cc  | 159 +
 winsup/cygwin/tzcode/tz_posixrules.h   | 231 +
 4 files changed, 486 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/README
 create mode 100644 winsup/cygwin/tzcode/localtime.c.patch
 create mode 100644 winsup/cygwin/tzcode/localtime.cc
 create mode 100644 winsup/cygwin/tzcode/tz_posixrules.h

diff --git a/winsup/cygwin/tzcode/README b/winsup/cygwin/tzcode/README
new file mode 100644
index 0..b1a811e22
--- /dev/null
+++ b/winsup/cygwin/tzcode/README
@@ -0,0 +1,37 @@
+/*
+   How the code in this directory is supposed to work...
+   2020/05/22 Mark Geisert 
+
+   localtime.cc is the Cygwin-specific module that is compiled into
+   the Cygwin DLL when the latter is built.  It's just a wrapper that
+   #defines a bunch of stuff then #includes localtime.c.
+
+   localtime.c, at any point in time, is a reasonably recent version
+   of /src/lib/libc/time/localtime.c from NetBSD.  The same goes for
+   private.h and tzfile.h.  An empty namespace.h suffices for Cygwin.
+
+   The idea is that in the future, one just needs to bring over newer
+   versions of localtime.c, private.h, and/or tzfile.h from NetBSD as
+   they become available.
+
+   With luck, you can drop those files into this directory and they
+   can be immediately used to build a newer Cygwin DLL that has the
+   newer NetBSD functionality.  Without luck, you'll have to tweak the
+   wrapper localtime.cc.  In the worst case, some other strategy will
+   need to be figured out, such as manually pulling out the parts of
+   the NetBSD code Cygwin needs to build a stand-alone localtime.cc.
+
+   Re tz_posixrules.h: The data elements can be generated from
+   /usr/share/zoneinfo/posixrules in any version of Cygwin's tzdata
+   package.  Instructions are in the comment leading tz_posixrules.h.
+
+   Addendum:
+   Implementation of the strategy above has uncovered a small number
+   of NetBSD-isms in localtime.c that cannot be worked around with
+   preprocessor tricks.  So there is another file localtime.c.patched
+   that holds just these adjustments for Cygwin, and it's this file
+   that localtime.cc #includes.  localtime.c.patched is generated by
+   winsup/cygwin/Makefile[.in] operating with localtime.c.patch.
+
+   ..mark
+*/
diff --git a/winsup/cygwin/tzcode/localtime.c.patch 
b/winsup/cygwin/tzcode/localtime.c.patch
new file mode 100644
index 0..e19a2cd02
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c.patch
@@ -0,0 +1,59 @@
+--- localtime.c2020-05-16 21:54:00.533111800 -0700
 localtime.c.patched2020-05-22 00:03:30.826646000 -0700
+@@ -413,7 +413,7 @@
+ };
+ 
+ /* TZDIR with a trailing '/' rather than a trailing '\0'.  */
+-static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
++static char const tzdirslash[sizeof TZDIR + 1] = TZDIR "/";
+ 
+ /* Local storage needed for 'tzloadbody'.  */
+ union local_storage {
+@@ -473,7 +473,7 @@
+  would pull in stdio (and would fail if the
+  resulting string length exceeded INT_MAX!).  */
+   memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
+-  strcpy(lsp->fullname + sizeof tzdirslash, name);
++  strcpy(lsp->fullname + sizeof tzdirslash - 1, name);
+ 
+   /* Set doaccess if NAME contains a ".." file name
+  component, as such a name could read a file outside
+@@ -488,11 +488,11 @@
+   name = lsp->fullname;
+   }
+   if (doaccess && access(name, R_OK) != 0)
+-  return errno;
++  goto trydefrules;
+ 
+   fid = open(name, OPEN_MODE);
+   if (fid < 0)
+-  return errno;
++  goto trydefrules;
+   nread = read(fid, up->buf, sizeof up->buf);
+   if (nread < (ssize_t)tzheadsize) {
+   int err = nread < 0 ? errno : EINVAL;
+@@ -501,6 +501,15 @@
+   }
+   if (close(fid) < 0)
+   return errno;
++  if (0) {
++trydefrules:
++  const char *base = strrchr(name, '/');
++  base = base ? base + 1 : name;
++  if (strcmp(base, TZDEFRULES))
++  return errno;
++  nread = sizeof _posixrules_data;
++  memcpy(up->buf, _posixrules_data, nread);
++  }
+   for (stored = 4; stored <= 8; stored *= 2) {
+   int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+   int_fast32_t ttis

[PATCH 2/3 v3] Cygwin: tzcode resync: imports

2020-05-22 Thread Mark Geisert
Import most recent NetBSD localtime.c, private.h, and tzfile.h.  An
empty namespace.h suffices for Cygwin.

---
 winsup/cygwin/tzcode/localtime.c | 2493 ++
 winsup/cygwin/tzcode/namespace.h |0
 winsup/cygwin/tzcode/private.h   |  795 ++
 winsup/cygwin/tzcode/tzfile.h|  174 +++
 4 files changed, 3462 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/localtime.c
 create mode 100644 winsup/cygwin/tzcode/namespace.h
 create mode 100644 winsup/cygwin/tzcode/private.h
 create mode 100644 winsup/cygwin/tzcode/tzfile.h

diff --git a/winsup/cygwin/tzcode/localtime.c b/winsup/cygwin/tzcode/localtime.c
new file mode 100644
index 0..a4d02a4c7
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c
@@ -0,0 +1,2493 @@
+/* $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
+
+/* Convert timestamp from time_t to struct tm.  */
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+#include 
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static charelsieid[] = "@(#)localtime.c8.17";
+#else
+__RCSID("$NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
+*/
+
+/*LINTLIBRARY*/
+
+#include "namespace.h"
+#include 
+#define LOCALTIME_IMPLEMENTATION
+#include "private.h"
+
+#include "tzfile.h"
+#include 
+
+#if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+#else
+# define NETBSD_INSPIRED_EXTERN static
+#endif
+
+#if defined(__weak_alias)
+__weak_alias(daylight,_daylight)
+__weak_alias(tzname,_tzname)
+#endif
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR   '_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_BINARY | O_CLOEXEC)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_CLOEXEC)
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+** 1.  They might reference tzname[0] before calling tzset (explicitly
+** or implicitly).
+** 2.  They might reference tzname[1] before calling tzset (explicitly
+** or implicitly).
+** 3.  They might reference tzname[1] after setting to a time zone
+** in which Daylight Saving Time is never observed.
+** 4.  They might reference tzname[0] after setting to a time zone
+** in which Standard Time is never observed.
+** 5.  They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR   "   "
+#endif /* !defined WILDABBR */
+
+static const char  wildabbr[] = WILDABBR;
+
+static const char  gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
+
+struct ttinfo {/* time type information */
+   int_fast32_ttt_utoff;   /* UT offset in seconds */
+   booltt_isdst;   /* used to set tm_isdst */
+   int tt_desigidx;/* abbreviation list index */
+   booltt_ttisstd; /* transition is std time */
+   booltt_ttisut;  /* transition is UT */
+};
+
+struct lsinfo {/* leap second information */
+   time_t  ls_trans;   /* transition time */
+   int_fast64_tls_corr;/* correction to apply */
+};
+
+#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
+#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX  TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX  255
+#endif /* !defined TZNAME_MAX */
+
+#define state __state
+struct state {
+   int leapcnt;
+   int timecnt;
+   

[PATCH 0/3 v3] Cygwin: tzcode resync

2020-05-22 Thread Mark Geisert
This is v3 of this patch set incorporating review comments on v2.  I've
minimized the size of the localtime.c.patch file by beefing up #defines
in the wrapper localtime.cc.  I believe I've addressed all comments.

This patch set has been tested on both 64- and 32-bit Cygwin.  The
initial shell opens with timezone correctly set.  xclock, date, uptime
all show the correct local time.  Overriding TZ in the environment on a
call to date, as in 'TZ=Asia/Tokyo date' shows correctly adjusted time.

..mark

[PATCH 1/3 v3] Cygwin: tzcode resync: basics
[PATCH 2/3 v3] Cygwin: tzcode resync: imports
[PATCH 3/3 v3] Cygwin: tzcode resync: details



[PATCH 2/3] Cygwin: tzcode resync v2: imports

2020-05-18 Thread Mark Geisert
Import most recent NetBSD localtime.c, private.h, and tzfile.h.

---
 winsup/cygwin/tzcode/localtime.c | 2493 ++
 winsup/cygwin/tzcode/private.h   |  795 ++
 winsup/cygwin/tzcode/tzfile.h|  174 +++
 3 files changed, 3462 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/localtime.c
 create mode 100644 winsup/cygwin/tzcode/private.h
 create mode 100644 winsup/cygwin/tzcode/tzfile.h

diff --git a/winsup/cygwin/tzcode/localtime.c b/winsup/cygwin/tzcode/localtime.c
new file mode 100644
index 0..a4d02a4c7
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c
@@ -0,0 +1,2493 @@
+/* $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
+
+/* Convert timestamp from time_t to struct tm.  */
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+#include 
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static charelsieid[] = "@(#)localtime.c8.17";
+#else
+__RCSID("$NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
+*/
+
+/*LINTLIBRARY*/
+
+#include "namespace.h"
+#include 
+#define LOCALTIME_IMPLEMENTATION
+#include "private.h"
+
+#include "tzfile.h"
+#include 
+
+#if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+#else
+# define NETBSD_INSPIRED_EXTERN static
+#endif
+
+#if defined(__weak_alias)
+__weak_alias(daylight,_daylight)
+__weak_alias(tzname,_tzname)
+#endif
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR   '_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_BINARY | O_CLOEXEC)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_CLOEXEC)
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+** 1.  They might reference tzname[0] before calling tzset (explicitly
+** or implicitly).
+** 2.  They might reference tzname[1] before calling tzset (explicitly
+** or implicitly).
+** 3.  They might reference tzname[1] after setting to a time zone
+** in which Daylight Saving Time is never observed.
+** 4.  They might reference tzname[0] after setting to a time zone
+** in which Standard Time is never observed.
+** 5.  They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR   "   "
+#endif /* !defined WILDABBR */
+
+static const char  wildabbr[] = WILDABBR;
+
+static const char  gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
+
+struct ttinfo {/* time type information */
+   int_fast32_ttt_utoff;   /* UT offset in seconds */
+   booltt_isdst;   /* used to set tm_isdst */
+   int tt_desigidx;/* abbreviation list index */
+   booltt_ttisstd; /* transition is std time */
+   booltt_ttisut;  /* transition is UT */
+};
+
+struct lsinfo {/* leap second information */
+   time_t  ls_trans;   /* transition time */
+   int_fast64_tls_corr;/* correction to apply */
+};
+
+#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
+#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX  TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX  255
+#endif /* !defined TZNAME_MAX */
+
+#define state __state
+struct state {
+   int leapcnt;
+   int timecnt;
+   int typecnt;
+   int charcnt;
+   boolgoback;
+   boolgoahead;
+   time_t   

[PATCH 0/3] Cygwin: tzcode resync v2

2020-05-18 Thread Mark Geisert
This is a reorganization of the previous patch contents to cut down on
extraneous material.  It seems to be complete and could thus be applied
to a copy of the newlib-cygwin tree successfully for testing or review.

Methods of testing can be discussed by reply to this post, or on
cygwin-developers, whichever is most appropriate.  I'm also open to other
strategies of implementation if this one seems risky or unattractive for
some reason.

..mark

[PATCH 1/3] Cygwin: tzcode resync v2: basics
[PATCH 2/3] Cygwin: tzcode resync v2: imports
[PATCH 3/3] Cygwin: tzcode resync v2: details



[PATCH 3/3] Cygwin: tzcode resync v2: details

2020-05-18 Thread Mark Geisert
Add tz_posixrules.h with data generated from most recent Cygwin tzdata
package.  Establish localtime.cc as primarily a wrapper around a patched
copy of localtime.c.  See README for more information.

---
 winsup/cygwin/tzcode/README|  37 +++
 winsup/cygwin/tzcode/localtime.c.patch | 399 +
 winsup/cygwin/tzcode/localtime.cc  | 159 ++
 winsup/cygwin/tzcode/tz_posixrules.h   | 231 ++
 4 files changed, 826 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/README
 create mode 100644 winsup/cygwin/tzcode/localtime.c.patch
 create mode 100644 winsup/cygwin/tzcode/localtime.cc
 create mode 100644 winsup/cygwin/tzcode/tz_posixrules.h

diff --git a/winsup/cygwin/tzcode/README b/winsup/cygwin/tzcode/README
new file mode 100644
index 0..dd01ac565
--- /dev/null
+++ b/winsup/cygwin/tzcode/README
@@ -0,0 +1,37 @@
+/*
+   How the code in this directory is supposed to work...
+   2020/05/13 Mark Geisert 
+
+   localtime.cc is the Cygwin-specific module that is compiled into
+   the Cygwin DLL when the latter is built.  It's just a wrapper that
+   #defines a bunch of stuff then #includes localtime.c.
+
+   localtime.c, at any point in time, is a reasonably recent version
+   of /src/lib/libc/time/localtime.c from NetBSD.  The same goes for
+   private.h and tzfile.h.
+
+   The idea is that in the future, one just needs to bring over newer
+   versions of localtime.c, private.h, and/or tzfile.h from NetBSD as
+   they become available.
+
+   With luck, you can drop those files into this directory and they
+   can be immediately used to build a newer Cygwin DLL that has the
+   newer NetBSD functionality.  Without luck, you'll have to tweak the
+   wrapper localtime.cc.  In the worst case, some other strategy will
+   need to be figured out, such as manually pulling out the parts of
+   the NetBSD code Cygwin needs to build a stand-alone localtime.cc.
+
+   Re tz_posixrules.h: The data elements can be generated from
+   /usr/share/zoneinfo/posixrules in any version of Cygwin's tzdata
+   package.  Instructions are in the comment leading tz_posixrules.h.
+
+   Addendum:
+   Implementation of the strategy above has uncovered a small number
+   of NetBSD-isms in localtime.c that cannot be worked around with
+   preprocessor tricks.  So there is another file localtime.c.patched
+   that holds just these adjustments for Cygwin, and it's this file
+   that localtime.cc #includes.  localtime.c.patched is generated by
+   winsup/cygwin/Makefile[.in] operating with localtime.c.patch.
+
+   ..mark
+*/
diff --git a/winsup/cygwin/tzcode/localtime.c.patch 
b/winsup/cygwin/tzcode/localtime.c.patch
new file mode 100644
index 0..a17d9ee90
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c.patch
@@ -0,0 +1,399 @@
+*** localtime.c2020-05-16 21:54:00.533111800 -0700
+--- localtime.c.patched2020-05-16 22:42:40.486924300 -0700
+***
+*** 1,3 
+--- 1,4 
++ // localtime.c.patched: based on NetBSD's localtime.c version 1.122
+  /*   $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
+  
+  /* Convert timestamp from time_t to struct tm.  */
+***
+*** 23,29 
+  
+  /*LINTLIBRARY*/
+  
+- #include "namespace.h"
+  #include 
+  #define LOCALTIME_IMPLEMENTATION
+  #include "private.h"
+--- 24,29 
+***
+*** 182,188 
+  
+  
+  #if !defined(__LIBC12_SOURCE__)
+! timezone_t __lclptr;
+  #ifdef _REENTRANT
+  rwlock_t __lcl_lock = RWLOCK_INITIALIZER;
+  #endif
+--- 182,188 
+  
+  
+  #if !defined(__LIBC12_SOURCE__)
+! static timezone_t __lclptr;
+  #ifdef _REENTRANT
+  rwlock_t __lcl_lock = RWLOCK_INITIALIZER;
+  #endif
+***
+*** 198,204 
+  
+  static struct tm tm;
+  
+! #if !HAVE_POSIX_DECLS || TZ_TIME_T || defined(__NetBSD__)
+  # if !defined(__LIBC12_SOURCE__)
+  
+  __aconst char *  tzname[2] = {
+--- 198,204 
+  
+  static struct tm tm;
+  
+! #if !HAVE_POSIX_DECLS || TZ_TIME_T || defined(__NetBSD__) || 
defined(__CYGWIN__)
+  # if !defined(__LIBC12_SOURCE__)
+  
+  __aconst char *  tzname[2] = {
+***
+*** 413,419 
+  };
+  
+  /* TZDIR with a trailing '/' rather than a trailing '\0'.  */
+! static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
+  
+  /* Local storage needed for 'tzloadbody'.  */
+  union local_storage {
+--- 413,420 
+  };
+  
+  /* TZDIR with a trailing '/' rather than a trailing '\0'.  */
+! static char const tzdirslash[] = TZDIR "/";
+! #define sizeof_tzdirslash (sizeof tzdirslash - 1)
+  
+  /* Local storage needed for 'tzloadbody'.  */
+  union local_storage {
+***
+*** 428,434 
+  
+   /* The file name to be opened.  */
+   char fullname[/*CONSTCOND*/BIGGEST(sizeof (struct file_analysis),
+!  sizeof t

[PATCH 1/3] Cygwin: tzcode resync v2: basics

2020-05-18 Thread Mark Geisert
Modifies winsup/cygwin/Makefile.in to build localtime.o from items in
new winsup/cygwin/tzcode subdirectory.  Removes existing localtime.cc
and tz_posixrules.h from winsup/cygwin as they are superseded by the
following patches.

---
 winsup/cygwin/Makefile.in |   12 +-
 winsup/cygwin/localtime.cc| 2597 -
 winsup/cygwin/tz_posixrules.h |   48 -
 3 files changed, 10 insertions(+), 2647 deletions(-)
 delete mode 100644 winsup/cygwin/localtime.cc
 delete mode 100644 winsup/cygwin/tz_posixrules.h

diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index f273ba793..59434a930 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -27,7 +27,7 @@ export CCWRAP_HEADERS:=. ${srcdir}
 export CCWRAP_SYSTEM_HEADERS:=@cygwin_headers@ @newlib_headers@
 export CCWRAP_DIRAFTER_HEADERS:=@windows_headers@
 
-VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math
+VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math 
$(srcdir)/tzcode
 
 target_cpu:=@target_cpu@
 target_alias:=@target_alias@
@@ -246,6 +246,14 @@ MATH_OFILES:= \
tgammal.o \
truncl.o
 
+TZCODE_OFILES:=localtime.o
+
+localtime.o: $(srcdir)/tzcode/localtime.cc $(srcdir)/tzcode/localtime.c.patch
+   (cd $(srcdir)/tzcode && \
+   patch -c -o localtime.c.patched localtime.c localtime.c.patch)
+   $(CXX) ${CXXFLAGS} -I$(target_builddir)/winsup/cygwin \
+   -I$(srcdir) -I$(srcdir)/tzcode -c -o $@ $<
+
 DLL_OFILES:= \
advapi32.o \
aio.o \
@@ -333,7 +341,6 @@ DLL_OFILES:= \
ldap.o \
libstdcxx_wrapper.o \
loadavg.o \
-   localtime.o \
lsearch.o \
malloc_wrapper.o \
minires-os-if.o \
@@ -412,6 +419,7 @@ DLL_OFILES:= \
$(EXTRA_OFILES) \
$(MALLOC_OFILES) \
$(MATH_OFILES) \
+   $(TZCODE_OFILES) \
$(MT_SAFE_OBJECTS)
 
 EXCLUDE_STATIC_OFILES:=$(addprefix --exclude=,\
diff --git a/winsup/cygwin/localtime.cc b/winsup/cygwin/localtime.cc
deleted file mode 100644
index 010376637..0
--- a/winsup/cygwin/localtime.cc
+++ /dev/null
@@ -1,2597 +0,0 @@
-/* $NetBSD: localtime.c,v 1.72 2012/10/28 19:02:29 christos Exp $  */
-
-/* Don't reformat the code arbitrarily.
-
-   It uses in wide parts the exact formatting as the upstream NetBSD
-   versions.  The purpose is to simplify subsequent diffs to the NetBSD
-   version, should the need arise again at one point. */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-/* Temporarily merged private.h and tzfile.h for ease of management - DJ */
-
-#include "winsup.h"
-#include "cygerrno.h"
-#include "sync.h"
-#include 
-#define STD_INSPIRED
-#define lint
-
-#define USG_COMPAT
-
-#ifndef lint
-#ifndef NOID
-static charelsieid[] = "@(#)localtime.c8.17";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Leap second handling from Bradley White.
-** POSIX-style TZ environment variable handling from Guy Harris.
-*/
-
-#define NO_ERROR_IN_DST_GAP
-
-/*LINTLIBRARY*/
-
-#ifndef PRIVATE_H
-
-#define PRIVATE_H
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson
-*/
-
-/*
-** This header is for use ONLY with the time conversion code.
-** There is no guarantee that it will remain unchanged,
-** or that it will remain at all.
-** Do NOT copy it to any system include directory.
-** Thank you!
-*/
-
-/*
-** ID
-*/
-
-#ifndef lint
-#ifndef NOID
-static charprivatehid[] = "@(#)private.h   7.48";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
-** Nested includes
-*/
-
-#include "stdio.h"
-#include "limits.h"/* for CHAR_BIT */
-#include "stdlib.h"
-#include "unistd.h"/* for F_OK and R_OK */
-
-/* Unlike 's isdigit, this also works if c < 0 | c > UCHAR_MAX.  */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
-#ifndef __pure
-#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
-# define __pure __attribute__ ((__pure__))
-#else
-# define __pure /* empty */
-#endif
-#endif
-
-/*
-** Finally, some convenience items.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (/*CONSTCOND*/((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
-
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
-
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
-
-#ifndef INT_STRLEN_MAXIMUM
-/*
-** 302 / 1000 is log10(2.0) rounded up.
-** Subtract one for the sign bit if the type is signed;
-** add one for integer division truncation;
-** add one more for a minus sign if the type is signed.
-*/
-#define INT_STRLEN_MAXIMUM(type) \
-((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
-
-/*
-** INITIALIZE(x)
-*/
-
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */

Re [Cygwin PATCH */9] tzcode resync -- for discussion only

2020-05-13 Thread Mark Geisert
I'm not absolutely sure yet but I think this patch set isn't complete. 
What's been posted is OK for discussion (on cygwin-developers?) but would 
need to be augmented if you're going to apply as-is.


I had a git commit/revert mishap and these are recovered file versions.  I 
belatedly discovered there's no record in the patches of my creating 
directory winsup/cygwin/tzcode or of my deleting localtime.cc and 
tz_posixrules.h from winsup/cygwin in my local repository.


When it becomes time to submit the final patch versions, I'll do so from a 
brand new repository.  Sorry for any confusion.


..mark


[Cygwin PATCH 6/9] tzcode resync: namespace.h

2020-05-13 Thread Mark Geisert
Empty file not including current NetBSD namespace.h because Cygwin
doesn't implement that functionality.  This allows compilation that
avoids an error due to a missing include file.

---
 winsup/cygwin/tzcode/namespace.h | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 winsup/cygwin/tzcode/namespace.h

diff --git a/winsup/cygwin/tzcode/namespace.h b/winsup/cygwin/tzcode/namespace.h
new file mode 100644
index 0..e69de29bb
-- 
2.21.0



[Cygwin PATCH 8/9] tzcode resync: tzfile.h

2020-05-13 Thread Mark Geisert
Imported NetBSD tzfile.h, current as of 2020/05/13, version 1.10.

---
 winsup/cygwin/tzcode/tzfile.h | 174 ++
 1 file changed, 174 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/tzfile.h

diff --git a/winsup/cygwin/tzcode/tzfile.h b/winsup/cygwin/tzcode/tzfile.h
new file mode 100644
index 0..5c7a22239
--- /dev/null
+++ b/winsup/cygwin/tzcode/tzfile.h
@@ -0,0 +1,174 @@
+/* $NetBSD: tzfile.h,v 1.10 2019/07/03 15:49:21 christos Exp $ */
+
+#ifndef _TZFILE_H_
+#define _TZFILE_H_
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** Information about time zone files.
+*/
+
+#ifndef TZDIR  /* Time zone object file directory */
+#define TZDIR  "/usr/share/zoneinfo"
+#endif /* !defined TZDIR */
+
+#ifndef TZDEFAULT
+#define TZDEFAULT  "/etc/localtime"
+#endif /* !defined TZDEFAULT */
+
+#ifndef TZDEFRULES
+#define TZDEFRULES "posixrules"
+#endif /* !defined TZDEFRULES */
+
+
+/* See Internet RFC 8536 for more details about the following format.  */
+
+/*
+** Each file begins with. . .
+*/
+
+#defineTZ_MAGIC"TZif"
+
+struct tzhead {
+   chartzh_magic[4];   /* TZ_MAGIC */
+   chartzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
+   chartzh_reserved[15];   /* reserved; must be zero */
+   chartzh_ttisutcnt[4];   /* coded number of trans. time flags */
+   chartzh_ttisstdcnt[4];  /* coded number of trans. time flags */
+   chartzh_leapcnt[4]; /* coded number of leap seconds */
+   chartzh_timecnt[4]; /* coded number of transition times */
+   chartzh_typecnt[4]; /* coded number of local time types */
+   chartzh_charcnt[4]; /* coded number of abbr. chars */
+};
+
+/*
+** . . .followed by. . .
+**
+** tzh_timecnt (char [4])s coded transition times a la time(2)
+** tzh_timecnt (unsigned char)stypes of local time starting at above
+** tzh_typecnt repetitions of
+** one (char [4])  coded UT offset in seconds
+** one (unsigned char) used to set tm_isdst
+** one (unsigned char) that's an abbreviation list index
+** tzh_charcnt (char)s '\0'-terminated zone abbreviations
+** tzh_leapcnt repetitions of
+** one (char [4])  coded leap second transition times
+** one (char [4])  total correction after above
+** tzh_ttisstdcnt (char)s  indexed by type; if 1, transition
+** time is standard time, if 0,
+** transition time is local (wall clock)
+** time; if absent, transition times are
+** assumed to be local time
+** tzh_ttisutcnt (char)s   indexed by type; if 1, transition
+** time is UT, if 0, transition time is
+** local time; if absent, transition
+** times are assumed to be local time.
+** When this is 1, the corresponding
+** std/wall indicator must also be 1.
+*/
+
+/*
+** If tzh_version is '2' or greater, the above is followed by a second instance
+** of tzhead and a second instance of the data in which each coded transition
+** time uses 8 rather than 4 chars,
+** then a POSIX-TZ-environment-variable-style string for use in handling
+** instants after the last transition time stored in the file
+** (with nothing between the newlines if there is no POSIX representation for
+** such instants).
+**
+** If tz_version is '3' or greater, the above is extended as follows.
+** First, the POSIX TZ string's hour offset may range from -167
+** through 167 as compared to the POSIX-required 0 through 24.
+** Second, its DST start time may be January 1 at 00:00 and its stop
+** time December 31 at 24:00 plus the difference between DST and
+** standard time, indicating DST all year.
+*/
+
+/*
+** In the current implementation, "tzset()" refuses to deal with files that
+** exceed any of the limits below.
+*/
+
+#ifndef TZ_MAX_TIMES
+#define TZ_MAX_TIMES   2000
+#endif /* !defined TZ_MAX_TIMES */
+
+#ifndef TZ_MAX_TYPES
+/* This must be at least 17 for Europe/Samara and Europe/Vilnius.  */
+#define TZ_MAX_TYPES   256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined TZ_MAX_TYPES */
+
+#ifndef TZ_MAX_CHARS
+#define TZ_MAX_CHARS   50  /* Maximum number of abbreviation characters */
+   /* (limited by 

[Cygwin PATCH 9/9] tzcode resync: tz_posixrules.h

2020-05-13 Thread Mark Geisert
Internal copy of file /usr/share/zoneinfo/posixrules generated from the
Cygwin tzdata 2020a-1 package.  Current as of 2020/05/13.

---
 winsup/cygwin/tzcode/tz_posixrules.h | 231 +++
 1 file changed, 231 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/tz_posixrules.h

diff --git a/winsup/cygwin/tzcode/tz_posixrules.h 
b/winsup/cygwin/tzcode/tz_posixrules.h
new file mode 100644
index 0..7981fcffc
--- /dev/null
+++ b/winsup/cygwin/tzcode/tz_posixrules.h
@@ -0,0 +1,231 @@
+/* tz_posixrules.h
+ *
+ * The data elements were generated with...
+ * od -vt u1 -A n /usr/share/zoneinfo/posixrules | 
+ * sed 's/$/,/;s/^ //;s/[0-9] /&,/g;s/ ,/, /g' > tz_posixrules.h
+ *
+ * The source posixrules file is from the Cygwin tzdata 2020a-1 package.
+ */
+static NO_COPY unsigned char _posixrules_data[] = {
+ 84,  90, 105, 102,  50,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+  0,   0,   0,   0,   0,   0,   0,   5,   0,   0,   0,   5,   0,   0,   0,   0,
+  0,   0,   0, 236,   0,   0,   0,   5,   0,   0,   0,  20, 128,   0,   0,   0,
+158, 166,  30, 112, 159, 186, 235,  96, 160, 134,   0, 112, 161, 154, 205,  96,
+162, 101, 226, 112, 163, 131, 233, 224, 164, 106, 174, 112, 165,  53, 167,  96,
+166,  83, 202, 240, 167,  21, 137,  96, 168,  51, 172, 240, 168, 254, 165, 224,
+170,  19, 142, 240, 170, 222, 135, 224, 171, 243, 112, 240, 172, 190, 105, 224,
+173, 211,  82, 240, 174, 158,  75, 224, 175, 179,  52, 240, 176, 126,  45, 224,
+177, 156,  81, 112, 178, 103,  74,  96, 179, 124,  51, 112, 180,  71,  44,  96,
+181,  92,  21, 112, 182,  39,  14,  96, 183,  59, 247, 112, 184,   6, 240,  96,
+185,  27, 217, 112, 185, 230, 210,  96, 187,   4, 245, 240, 187, 198, 180,  96,
+188, 228, 215, 240, 189, 175, 208, 224, 190, 196, 185, 240, 191, 143, 178, 224,
+192, 164, 155, 240, 193, 111, 148, 224, 194, 132, 125, 240, 195,  79, 118, 224,
+196, 100,  95, 240, 197,  47,  88, 224, 198,  77, 124, 112, 199,  15,  58, 224,
+200,  45,  94, 112, 200, 248,  87,  96, 202,  13,  64, 112, 202, 216,  57,  96,
+203, 136, 240, 112, 210,  35, 244, 112, 210,  96, 251, 224, 211, 117, 228, 240,
+212,  64, 221, 224, 213,  85, 198, 240, 214,  32, 191, 224, 215,  53, 168, 240,
+216,   0, 161, 224, 217,  21, 138, 240, 217, 224, 131, 224, 218, 254, 167, 112,
+219, 192, 101, 224, 220, 222, 137, 112, 221, 169, 130,  96, 222, 190, 107, 112,
+223, 137, 100,  96, 224, 158,  77, 112, 225, 105,  70,  96, 226, 126,  47, 112,
+227,  73,  40,  96, 228,  94,  17, 112, 229,  87,  46, 224, 230,  71,  45, 240,
+231,  55,  16, 224, 232,  39,  15, 240, 233,  22, 242, 224, 234,   6, 241, 240,
+234, 246, 212, 224, 235, 230, 211, 240, 236, 214, 182, 224, 237, 198, 181, 240,
+238, 191, 211,  96, 239, 175, 210, 112, 240, 159, 181,  96, 241, 143, 180, 112,
+242, 127, 151,  96, 243, 111, 150, 112, 244,  95, 121,  96, 245,  79, 120, 112,
+246,  63,  91,  96, 247,  47,  90, 112, 248,  40, 119, 224, 249,  15,  60, 112,
+250,   8,  89, 224, 250, 248,  88, 240, 251, 232,  59, 224, 252, 216,  58, 240,
+253, 200,  29, 224, 254, 184,  28, 240, 255, 167, 255, 224,   0, 151, 254, 240,
+  1, 135, 225, 224,   2, 119, 224, 240,   3, 112, 254,  96,   4,  96, 253, 112,
+  5,  80, 224,  96,   6,  64, 223, 112,   7,  48, 194,  96,   7, 141,  25, 112,
+  9,  16, 164,  96,   9, 173, 148, 240,  10, 240, 134,  96,  11, 224, 133, 112,
+ 12, 217, 162, 224,  13, 192, 103, 112,  14, 185, 132, 224,  15, 169, 131, 240,
+ 16, 153, 102, 224,  17, 137, 101, 240,  18, 121,  72, 224,  19, 105,  71, 240,
+ 20,  89,  42, 224,  21,  73,  41, 240,  22,  57,  12, 224,  23,  41,  11, 240,
+ 24,  34,  41,  96,  25,   8, 237, 240,  26,   2,  11,  96,  26, 242,  10, 112,
+ 27, 225, 237,  96,  28, 209, 236, 112,  29, 193, 207,  96,  30, 177, 206, 112,
+ 31, 161, 177,  96,  32, 118,   0, 240,  33, 129, 147,  96,  34,  85, 226, 240,
+ 35, 106, 175, 224,  36,  53, 196, 240,  37,  74, 145, 224,  38,  21, 166, 240,
+ 39,  42, 115, 224,  39, 254, 195, 112,  41,  10,  85, 224,  41, 222, 165, 112,
+ 42, 234,  55, 224,  43, 190, 135, 112,  44, 211,  84,  96,  45, 158, 105, 112,
+ 46, 179,  54,  96,  47, 126,  75, 112,  48, 147,  24,  96,  49, 103, 103, 240,
+ 50, 114, 250,  96,  51,  71,  73, 240,  52,  82, 220,  96,  53,  39,  43, 240,
+ 54,  50, 190,  96,  55,   7,  13, 240,  56,  27, 218, 224,  56, 230, 239, 240,
+ 57, 251, 188, 224,  58, 198, 209, 240,  59, 219, 158, 224,  60, 175, 238, 112,
+ 61, 187, 128, 224,  62, 143, 208, 112,  63, 155,  98, 224,  64, 111, 178, 112,
+ 65, 132, 127,  96,  66,  79, 148, 112,  67, 100,  97,  96,  68,  47, 118, 112,
+ 69,  68,  67,  96,  69, 243, 168, 240,  71,  45,  95, 224,  71, 211, 138, 240,
+ 73,  13,  65, 224,  73, 179, 108, 240,  74, 237,  35, 224,  75, 156, 137, 112,
+ 76, 214,  64,  96,  77, 124, 107, 112,  78, 182,  34,  96,  79,  92,  77, 112,
+ 80, 150,   4,  96,  81,  60,  47, 112,  82, 117, 230,  96,  83,  28,  17, 112,
+ 84,  85, 200,  96,  84, 251, 243, 112,  86,  53, 170,  96,  86, 229,  15, 240,
+ 

[Cygwin PATCH 3/9] tzcode resync: localtime.cc

2020-05-13 Thread Mark Geisert
Cygwin's wrapper around NetBSD's localtime.c.

---
 winsup/cygwin/tzcode/localtime.cc | 162 ++
 1 file changed, 162 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/localtime.cc

diff --git a/winsup/cygwin/tzcode/localtime.cc 
b/winsup/cygwin/tzcode/localtime.cc
new file mode 100644
index 0..9ea885ece
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.cc
@@ -0,0 +1,162 @@
+/* localtime.cc: Wrapper of NetBSD tzcode support for Cygwin. See README file.
+
+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 "sync.h"
+#include "../include/cygwin/version.h"
+#include "tz_posixrules.h"
+
+// Set these NetBSD-related option #defines appropriately for Cygwin
+//#define STD_INSPIRED // early-include private.h below does this
+#define lint
+#define USG_COMPAT 1
+#define NO_ERROR_IN_DST_GAP
+#define state __state
+
+static NO_COPY muto tzset_guard;
+
+// Turn these NetBSD ops into the corresponding Cygwin ops
+#define rwlock_wrlock(X) tzset_guard.init ("tzset_guard")->acquire ()
+#define rwlock_unlock(X) tzset_guard.release ()
+
+// Turn a specific known kind of const parameter into non-const
+#define __UNCONST(X) ((char *) (X))
+
+// Turn off these NetBSD audit-related definitions
+#define __aconst
+#define _DIAGASSERT(X)
+
+// Get ready to enclose NetBSD's localtime.c
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Supply this Cygwin-specific function in advance of its use in localtime.c
+static char *
+tzgetwintz (char *wildabbr, char *outbuf)
+{
+TIME_ZONE_INFORMATION tzi;
+char *cp, *dst;
+wchar_t *src;
+div_t d;
+
+GetTimeZoneInformation ();
+dst = cp = outbuf;
+for (src = tzi.StandardName; *src; src++)
+   if (*src >= L'A' && *src <= L'Z')
+   *dst++ = *src;
+if ((dst - cp) < 3)
+  {
+   /* In non-english Windows, converted tz.StandardName
+  may not contain a valid standard timezone name. */
+   strcpy (cp, wildabbr);
+   cp += strlen (wildabbr);
+  }
+else
+   cp = dst;
+d = div (tzi.Bias + tzi.StandardBias, 60);
+__small_sprintf (cp, "%d", d.quot);
+if (d.rem)
+   __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
+if (tzi.StandardDate.wMonth)
+  {
+   cp = strchr (cp, 0);
+   dst = cp;
+   for (src = tzi.DaylightName; *src; src++)
+   if (*src >= L'A' && *src <= L'Z')
+   *dst++ = *src;
+   if ((dst - cp) < 3)
+ {
+   /* In non-english Windows, converted tz.DaylightName
+  may not contain a valid daylight timezone name. */
+   strcpy (cp, wildabbr);
+   cp += strlen (wildabbr);
+ }
+   else
+   cp = dst;
+   d = div (tzi.Bias + tzi.DaylightBias, 60);
+   __small_sprintf (cp, "%d", d.quot);
+   if (d.rem)
+   __small_sprintf (cp = strchr (cp, 0), ":%d", abs (d.rem));
+   cp = strchr (cp, 0);
+   __small_sprintf (cp = strchr (cp, 0), ",M%d.%d.%d/%d",
+tzi.DaylightDate.wMonth,
+tzi.DaylightDate.wDay,
+tzi.DaylightDate.wDayOfWeek,
+tzi.DaylightDate.wHour);
+   if (tzi.DaylightDate.wMinute || tzi.DaylightDate.wSecond)
+   __small_sprintf (cp = strchr (cp, 0), ":%d",
+tzi.DaylightDate.wMinute);
+   if (tzi.DaylightDate.wSecond)
+   __small_sprintf (cp = strchr (cp, 0), ":%d",
+tzi.DaylightDate.wSecond);
+   cp = strchr (cp, 0);
+   __small_sprintf (cp = strchr (cp, 0), ",M%d.%d.%d/%d",
+tzi.StandardDate.wMonth,
+tzi.StandardDate.wDay,
+tzi.StandardDate.wDayOfWeek,
+tzi.StandardDate.wHour);
+   if (tzi.StandardDate.wMinute || tzi.StandardDate.wSecond)
+   __small_sprintf (cp = strchr (cp, 0), ":%d",
+tzi.StandardDate.wMinute);
+   if (tzi.StandardDate.wSecond)
+   __small_sprintf (cp = strchr (cp, 0), ":%d",
+tzi.StandardDate.wSecond);
+  }
+/* __small_printf ("TZ deduced as `%s'\n", outbuf); */
+return outbuf;
+}
+
+// Pull these in early to catch any small issues before the real test
+#include "private.h"
+#include "tzfile.h"
+
+/* Some NetBSD differences were too difficult to work around..
+   so #include a patched copy of localtime.c rather than the NetBSD original.
+   Here is a list of the patches...
+   (1) fix an erroneous decl of tzdirslash size (flagged by g++)
+   (2) add missing casts on all results of malloc() calls (flagged by g++)
+   (3) change all malloc() calls to analogous calloc() calls
+   (4) add conditional call to Cygwin's tzgetwintz() from tzsetlcl()
+   (5) add Cygwin's historical 

[Cygwin PATCH 1/9] tzcode resync: Makefile.in

2020-05-13 Thread Mark Geisert
Establish cygwin subdirectory tzcode to hold updates to imported NetBSD files.

---
 winsup/cygwin/Makefile.in | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index f273ba793..69aa2277e 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -27,7 +27,7 @@ export CCWRAP_HEADERS:=. ${srcdir}
 export CCWRAP_SYSTEM_HEADERS:=@cygwin_headers@ @newlib_headers@
 export CCWRAP_DIRAFTER_HEADERS:=@windows_headers@
 
-VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math
+VPATH+=$(srcdir)/regex $(srcdir)/lib $(srcdir)/libc $(srcdir)/math 
$(srcdir)/tzcode
 
 target_cpu:=@target_cpu@
 target_alias:=@target_alias@
@@ -246,6 +246,8 @@ MATH_OFILES:= \
tgammal.o \
truncl.o
 
+TZCODE_OFILES:=localtime.o
+
 DLL_OFILES:= \
advapi32.o \
aio.o \
@@ -333,7 +335,6 @@ DLL_OFILES:= \
ldap.o \
libstdcxx_wrapper.o \
loadavg.o \
-   localtime.o \
lsearch.o \
malloc_wrapper.o \
minires-os-if.o \
@@ -412,6 +413,7 @@ DLL_OFILES:= \
$(EXTRA_OFILES) \
$(MALLOC_OFILES) \
$(MATH_OFILES) \
+   $(TZCODE_OFILES) \
$(MT_SAFE_OBJECTS)
 
 EXCLUDE_STATIC_OFILES:=$(addprefix --exclude=,\
-- 
2.21.0



[Cygwin PATCH 4/9] tzcode resync: localtime.c.patched

2020-05-13 Thread Mark Geisert
Patched copy of NetBSD's localtime.c to hold changes that could not be
accomplished in the wrapper file localtime.cc.  It is this file that
compilation of localtime.cc includes.

---
 winsup/cygwin/tzcode/localtime.c.patched | 2509 ++
 1 file changed, 2509 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/localtime.c.patched

diff --git a/winsup/cygwin/tzcode/localtime.c.patched 
b/winsup/cygwin/tzcode/localtime.c.patched
new file mode 100644
index 0..58e45d2bc
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c.patched
@@ -0,0 +1,2509 @@
+// localtime.c.patched: based on NetBSD's localtime.c version 1.122
+/* $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
+
+/* Convert timestamp from time_t to struct tm.  */
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+#include 
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static charelsieid[] = "@(#)localtime.c8.17";
+#else
+__RCSID("$NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
+*/
+
+/*LINTLIBRARY*/
+
+#include "namespace.h"
+#include 
+#define LOCALTIME_IMPLEMENTATION
+#include "private.h"
+
+#include "tzfile.h"
+#include 
+
+#if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+#else
+# define NETBSD_INSPIRED_EXTERN static
+#endif
+
+#if defined(__weak_alias)
+__weak_alias(daylight,_daylight)
+__weak_alias(tzname,_tzname)
+#endif
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR   '_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_BINARY | O_CLOEXEC)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_CLOEXEC)
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+** 1.  They might reference tzname[0] before calling tzset (explicitly
+** or implicitly).
+** 2.  They might reference tzname[1] before calling tzset (explicitly
+** or implicitly).
+** 3.  They might reference tzname[1] after setting to a time zone
+** in which Daylight Saving Time is never observed.
+** 4.  They might reference tzname[0] after setting to a time zone
+** in which Standard Time is never observed.
+** 5.  They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR   "   "
+#endif /* !defined WILDABBR */
+
+static const char  wildabbr[] = WILDABBR;
+
+static const char  gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
+
+struct ttinfo {/* time type information */
+   int_fast32_ttt_utoff;   /* UT offset in seconds */
+   booltt_isdst;   /* used to set tm_isdst */
+   int tt_desigidx;/* abbreviation list index */
+   booltt_ttisstd; /* transition is std time */
+   booltt_ttisut;  /* transition is UT */
+};
+
+struct lsinfo {/* leap second information */
+   time_t  ls_trans;   /* transition time */
+   int_fast64_tls_corr;/* correction to apply */
+};
+
+#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
+#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX  TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX  255
+#endif /* !defined TZNAME_MAX */
+
+#define state __state
+struct state {
+   int leapcnt;
+   int timecnt;
+   int typecnt;
+   int charcnt;
+   boolgoback;
+   boolgoahead;

[Cygwin PATCH 5/9] tzcode resync: localtime.c

2020-05-13 Thread Mark Geisert
Imported NetBSD localtime.c, current as of 2020/05/13, version 1.122.

---
 winsup/cygwin/tzcode/localtime.c | 2493 ++
 1 file changed, 2493 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/localtime.c

diff --git a/winsup/cygwin/tzcode/localtime.c b/winsup/cygwin/tzcode/localtime.c
new file mode 100644
index 0..a4d02a4c7
--- /dev/null
+++ b/winsup/cygwin/tzcode/localtime.c
@@ -0,0 +1,2493 @@
+/* $NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $ */
+
+/* Convert timestamp from time_t to struct tm.  */
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+#include 
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static charelsieid[] = "@(#)localtime.c8.17";
+#else
+__RCSID("$NetBSD: localtime.c,v 1.122 2019/07/03 15:50:16 christos Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+** Leap second handling from Bradley White.
+** POSIX-style TZ environment variable handling from Guy Harris.
+*/
+
+/*LINTLIBRARY*/
+
+#include "namespace.h"
+#include 
+#define LOCALTIME_IMPLEMENTATION
+#include "private.h"
+
+#include "tzfile.h"
+#include 
+
+#if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+#else
+# define NETBSD_INSPIRED_EXTERN static
+#endif
+
+#if defined(__weak_alias)
+__weak_alias(daylight,_daylight)
+__weak_alias(tzname,_tzname)
+#endif
+
+#ifndef TZ_ABBR_MAX_LEN
+#define TZ_ABBR_MAX_LEN16
+#endif /* !defined TZ_ABBR_MAX_LEN */
+
+#ifndef TZ_ABBR_CHAR_SET
+#define TZ_ABBR_CHAR_SET \
+   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
+#endif /* !defined TZ_ABBR_CHAR_SET */
+
+#ifndef TZ_ABBR_ERR_CHAR
+#define TZ_ABBR_ERR_CHAR   '_'
+#endif /* !defined TZ_ABBR_ERR_CHAR */
+
+/*
+** SunOS 4.1.1 headers lack O_BINARY.
+*/
+
+#ifdef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_BINARY | O_CLOEXEC)
+#endif /* defined O_BINARY */
+#ifndef O_BINARY
+#define OPEN_MODE  (O_RDONLY | O_CLOEXEC)
+#endif /* !defined O_BINARY */
+
+#ifndef WILDABBR
+/*
+** Someone might make incorrect use of a time zone abbreviation:
+** 1.  They might reference tzname[0] before calling tzset (explicitly
+** or implicitly).
+** 2.  They might reference tzname[1] before calling tzset (explicitly
+** or implicitly).
+** 3.  They might reference tzname[1] after setting to a time zone
+** in which Daylight Saving Time is never observed.
+** 4.  They might reference tzname[0] after setting to a time zone
+** in which Standard Time is never observed.
+** 5.  They might reference tm.TM_ZONE after calling offtime.
+** What's best to do in the above cases is open to debate;
+** for now, we just set things up so that in any of the five cases
+** WILDABBR is used. Another possibility: initialize tzname[0] to the
+** string "tzname[0] used before set", and similarly for the other cases.
+** And another: initialize tzname[0] to "ERA", with an explanation in the
+** manual page of what this "time zone abbreviation" means (doing this so
+** that tzname[0] has the "normal" length of three characters).
+*/
+#define WILDABBR   "   "
+#endif /* !defined WILDABBR */
+
+static const char  wildabbr[] = WILDABBR;
+
+static const char  gmt[] = "GMT";
+
+/*
+** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
+*/
+#ifndef TZDEFRULESTRING
+#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
+
+struct ttinfo {/* time type information */
+   int_fast32_ttt_utoff;   /* UT offset in seconds */
+   booltt_isdst;   /* used to set tm_isdst */
+   int tt_desigidx;/* abbreviation list index */
+   booltt_ttisstd; /* transition is std time */
+   booltt_ttisut;  /* transition is UT */
+};
+
+struct lsinfo {/* leap second information */
+   time_t  ls_trans;   /* transition time */
+   int_fast64_tls_corr;/* correction to apply */
+};
+
+#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
+#define BIGGEST(a, b)  (((a) > (b)) ? (a) : (b))
+
+#ifdef TZNAME_MAX
+#define MY_TZNAME_MAX  TZNAME_MAX
+#endif /* defined TZNAME_MAX */
+#ifndef TZNAME_MAX
+#define MY_TZNAME_MAX  255
+#endif /* !defined TZNAME_MAX */
+
+#define state __state
+struct state {
+   int leapcnt;
+   int timecnt;
+   int typecnt;
+   int charcnt;
+   boolgoback;
+   boolgoahead;
+   time_t  ats[TZ_MAX_TIMES];
+   unsigned char   types[TZ_MAX_TIMES];
+   struct ttinfo   ttis[TZ_MAX_TYPES];
+   charchars[/*CONSTCOND*/BIGGEST(BIGGEST(TZ_MAX_CHARS + 1,

[Cygwin PATCH 2/9] tzcode resync: README

2020-05-13 Thread Mark Geisert
---
 winsup/cygwin/tzcode/README | 37 +
 1 file changed, 37 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/README

diff --git a/winsup/cygwin/tzcode/README b/winsup/cygwin/tzcode/README
new file mode 100644
index 0..a200502ea
--- /dev/null
+++ b/winsup/cygwin/tzcode/README
@@ -0,0 +1,37 @@
+/*
+   How the code in this directory is supposed to work...
+   2020/05/13 Mark Geisert 
+
+   localtime.cc is the Cygwin-specific module that is compiled into
+   the Cygwin DLL when the latter is built.  It's just a wrapper that
+   #defines a bunch of stuff then #includes localtime.c.
+
+   localtime.c, at any point in time, is a reasonably recent version
+   of /src/lib/libc/time/localtime.c from NetBSD.  The same goes for
+   private.h and tzfile.h.  OTOH namespace.h implements something on
+   NetBSD that is not provided on Cygwin, so it's empty here.
+
+   The idea is that in the future, one just needs to bring over newer
+   versions of localtime.c, private.h, and/or tzfile.h from NetBSD as
+   they become available.
+
+   With luck, you can drop those files into this directory and they
+   can be immediately used to build a newer Cygwin DLL that has the
+   newer NetBSD functionality.  Without luck, you'll have to tweak the
+   wrapper localtime.cc.  In the worst case, some other strategy will
+   need to be figured out, such as manually pulling out the parts of
+   the NetBSD code Cygwin needs to build a stand-alone localtime.cc.
+
+   Re tz_posixrules.h: The data elements can be generated from
+   /usr/share/zoneinfo/posixrules in any version of Cygwin's tzdata
+   package.  Instructions are in the comment heading tz_posixrules.h.
+
+   Addendum:
+   Implementation of the strategy above has uncovered a small number
+   of NetBSD-isms in localtime.c that cannot be worked around with
+   preprocessor tricks.  So there is another file localtime.c.patched
+   that holds just these adjustments for Cygwin, and it's this file
+   that localtime.cc #includes.
+
+   ..mark
+*/
-- 
2.21.0



[Cygwin PATCH 7/9] tzcode resync: private.h

2020-05-13 Thread Mark Geisert
Imported NetBSD private.h, current as of 2020/05/13, version 1.55.

---
 winsup/cygwin/tzcode/private.h | 795 +
 1 file changed, 795 insertions(+)
 create mode 100644 winsup/cygwin/tzcode/private.h

diff --git a/winsup/cygwin/tzcode/private.h b/winsup/cygwin/tzcode/private.h
new file mode 100644
index 0..830750ad5
--- /dev/null
+++ b/winsup/cygwin/tzcode/private.h
@@ -0,0 +1,795 @@
+/* Private header for tzdb code.  */
+
+/* $NetBSD: private.h,v 1.55 2019/04/04 22:03:23 christos Exp $*/
+
+#ifndef PRIVATE_H
+#define PRIVATE_H
+
+/* NetBSD defaults */
+#define TM_GMTOFF  tm_gmtoff
+#define TM_ZONEtm_zone
+#define STD_INSPIRED   1
+#define HAVE_LONG_DOUBLE 1
+
+/* For when we build zic as a host tool. */
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+/*
+** This file is in the public domain, so clarified as of
+** 1996-06-05 by Arthur David Olson.
+*/
+
+/*
+** This header is for use ONLY with the time conversion code.
+** There is no guarantee that it will remain unchanged,
+** or that it will remain at all.
+** Do NOT copy it to any system include directory.
+** Thank you!
+*/
+
+/*
+** zdump has been made independent of the rest of the time
+** conversion package to increase confidence in the verification it provides.
+** You can use zdump to help in verifying other implementations.
+** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
+*/
+#ifndef USE_LTZ
+# define USE_LTZ 1
+#endif
+
+/* This string was in the Factory zone through version 2016f.  */
+#define GRANDPARENTED  "Local time zone must be set--see zic manual page"
+
+/*
+** Defaults for preprocessor symbols.
+** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
+*/
+
+#ifndef HAVE_DECL_ASCTIME_R
+#define HAVE_DECL_ASCTIME_R 1
+#endif
+
+#if !defined HAVE_GENERIC && defined __has_extension
+# if __has_extension(c_generic_selections)
+#  define HAVE_GENERIC 1
+# else
+#  define HAVE_GENERIC 0
+# endif
+#endif
+/* _Generic is buggy in pre-4.9 GCC.  */
+#if !defined HAVE_GENERIC && defined __GNUC__
+# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
+#endif
+#ifndef HAVE_GENERIC
+# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
+#endif
+
+#ifndef HAVE_GETTEXT
+#define HAVE_GETTEXT   0
+#endif /* !defined HAVE_GETTEXT */
+
+#ifndef HAVE_INCOMPATIBLE_CTIME_R
+#define HAVE_INCOMPATIBLE_CTIME_R  0
+#endif
+
+#ifndef HAVE_LINK
+#define HAVE_LINK  1
+#endif /* !defined HAVE_LINK */
+
+#ifndef HAVE_POSIX_DECLS
+#define HAVE_POSIX_DECLS 1
+#endif
+
+#ifndef HAVE_STDBOOL_H
+#define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
+#endif
+
+#ifndef HAVE_STRDUP
+#define HAVE_STRDUP 1
+#endif
+
+#ifndef HAVE_STRTOLL
+#define HAVE_STRTOLL 1
+#endif
+
+#ifndef HAVE_SYMLINK
+#define HAVE_SYMLINK   1
+#endif /* !defined HAVE_SYMLINK */
+
+#ifndef HAVE_SYS_STAT_H
+#define HAVE_SYS_STAT_H1
+#endif /* !defined HAVE_SYS_STAT_H */
+
+#ifndef HAVE_SYS_WAIT_H
+#define HAVE_SYS_WAIT_H1
+#endif /* !defined HAVE_SYS_WAIT_H */
+
+#ifndef HAVE_UNISTD_H
+#define HAVE_UNISTD_H  1
+#endif /* !defined HAVE_UNISTD_H */
+
+#ifndef HAVE_UTMPX_H
+#define HAVE_UTMPX_H   1
+#endif /* !defined HAVE_UTMPX_H */
+
+#ifndef NETBSD_INSPIRED
+# define NETBSD_INSPIRED 1
+#endif
+
+#if HAVE_INCOMPATIBLE_CTIME_R
+#define asctime_r _incompatible_asctime_r
+#define ctime_r _incompatible_ctime_r
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
+/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems.  */
+#define _GNU_SOURCE 1
+/* Fix asctime_r on Solaris 11.  */
+#define _POSIX_PTHREAD_SEMANTICS 1
+/* Enable strtoimax on pre-C99 Solaris 11.  */
+#define __EXTENSIONS__ 1
+
+/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
+   enable large files on GNUish systems ...  */
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+#endif
+/* ... and on AIX ...  */
+#define _LARGE_FILES 1
+/* ... and enable large inode numbers on Mac OS X 10.5 and later.  */
+#define _DARWIN_USE_64_BIT_INODE 1
+
+/*
+** Nested includes
+*/
+
+#ifndef __NetBSD__
+/* Avoid clashes with NetBSD by renaming NetBSD's declarations.  */
+#define localtime_rz sys_localtime_rz
+#define mktime_z sys_mktime_z
+#define posix2time_z sys_posix2time_z
+#define time2posix_z sys_time2posix_z
+#define timezone_t sys_timezone_t
+#define tzalloc sys_tzalloc
+#define tzfree sys_tzfree
+#include 
+#undef localtime_rz
+#undef mktime_z
+#undef posix2time_z
+#undef time2posix_z
+#undef timezone_t
+#undef tzalloc
+#undef tzfree
+#else
+#include "time.h"
+#endif
+
+#include  /* for time_t */
+#include 
+#include /* for CHAR_BIT et al. */
+#include 
+
+#include 
+
+#ifndef ENAMETOOLONG
+# define ENAMETOOLONG EINVAL
+#endif
+#ifndef ENOTSUP
+# define ENOTSUP EINVAL
+#endif
+#ifndef EOVERFLOW
+# define EOVERFLOW EINVAL
+#endif
+
+#if HAVE_GETTEXT
+#include 
+#endif /* HAVE_GETTEXT */
+
+#if HAVE_UNISTD_H

[PATCH] Cygwin: Add missing Linux #define of CPU_SETSIZE

2019-12-22 Thread Mark Geisert
Though our implementation of cpu sets doesn't need it, software from
Linux environments expects this definition to be present.  It's
documented on the Linux CPU_SET(3) man page but was left out due to
oversight.

Addresses https://cygwin.com/ml/cygwin/2019-12/msg00248.html

---
 winsup/cygwin/include/sys/cpuset.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 1adf48d54..572565165 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -89,6 +89,7 @@ int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 #define CPU_XOR(dst, src1, src2)  CPU_XOR_S(sizeof (cpu_set_t), dst, src1, 
src2)
 #define CPU_EQUAL(src1, src2) CPU_EQUAL_S(sizeof (cpu_set_t), src1, src2)
 
+#define CPU_SETSIZE   __CPU_SETSIZE
 #endif /* __GNU_VISIBLE */
 
 #ifdef __cplusplus
-- 
2.21.0



[PATCH] Cygwin: Raise dumpstack frame limit to 32

2019-11-07 Thread Mark Geisert
Create a #define for the limit and raise it from 16 to 32.
---
 winsup/cygwin/exceptions.cc | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 132fea427..3e7d7275c 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -42,6 +42,7 @@ details. */
 
 #define CALL_HANDLER_RETRY_OUTER 10
 #define CALL_HANDLER_RETRY_INNER 10
+#define DUMPSTACK_FRAME_LIMIT32
 
 PWCHAR debugger_command;
 extern uint8_t _sigbe;
@@ -382,7 +383,7 @@ cygwin_exception::dumpstack ()
 #else
   small_printf ("Stack trace:\r\nFrame Function  Args\r\n");
 #endif
-  for (i = 0; i < 16 && thestack++; i++)
+  for (i = 0; i < DUMPSTACK_FRAME_LIMIT && thestack++; i++)
{
  small_printf (_AFMT "  " _AFMT, thestack.sf.AddrFrame.Offset,
thestack.sf.AddrPC.Offset);
@@ -392,7 +393,8 @@ cygwin_exception::dumpstack ()
  small_printf (")\r\n");
}
   small_printf ("End of stack trace%s\n",
-   i == 16 ? " (more stack frames may be present)" : "");
+   i == DUMPSTACK_FRAME_LIMIT ?
+   " (more stack frames may be present)" : "");
   if (h)
NtClose (h);
 }
-- 
2.21.0



[PATCH] Cygwin: Doc change to note stackdump limit patch

2019-11-07 Thread Mark Geisert
---
 winsup/cygwin/release/3.1.0 | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/winsup/cygwin/release/3.1.0 b/winsup/cygwin/release/3.1.0
index 1b9d23615..345dd62a5 100644
--- a/winsup/cygwin/release/3.1.0
+++ b/winsup/cygwin/release/3.1.0
@@ -35,6 +35,9 @@ What changed:
 
 - Improve /proc/cpuinfo output and align more closely with Linux.
 
+- Raise stackdump frame limit from 16 to 32.
+  Addresses: https://cygwin.com/ml/cygwin/2019-11/msg00038.html
+
 
 Bug Fixes
 -
-- 
2.21.0



[PATCH] Cygwin: ldd: Try harder to get dll names

2019-08-15 Thread Mark Geisert
Borrow a trick from strace to lessen occurrences of "??? => ???" in ldd
output.  Specifically, if the module name isn't found in the usual place
in the mapped image, use the file handle we have to look up the name.

---
 winsup/utils/Makefile.in |  2 +-
 winsup/utils/ldd.cc  | 44 +++-
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/winsup/utils/Makefile.in b/winsup/utils/Makefile.in
index cebf39572..5bb62bc6f 100644
--- a/winsup/utils/Makefile.in
+++ b/winsup/utils/Makefile.in
@@ -101,7 +101,7 @@ cygpath.exe: CYGWIN_LDFLAGS += -lcygwin -luserenv -lntdll
 ps.exe: CYGWIN_LDFLAGS += -lcygwin -lpsapi -lntdll
 strace.exe: MINGW_LDFLAGS += -lntdll
 
-ldd.exe:CYGWIN_LDFLAGS += -lpsapi
+ldd.exe:CYGWIN_LDFLAGS += -lpsapi -lntdll
 pldd.exe: CYGWIN_LDFLAGS += -lpsapi
 minidumper.exe: CYGWIN_LDFLAGS += -ldbghelp
 
diff --git a/winsup/utils/ldd.cc b/winsup/utils/ldd.cc
index bbc62f12f..9bcc1df7f 100644
--- a/winsup/utils/ldd.cc
+++ b/winsup/utils/ldd.cc
@@ -39,6 +39,7 @@
 
 #define _WIN32_WINNT 0x0a00
 #include 
+#include 
 #include 
 #include 
 
@@ -55,6 +56,7 @@ struct option longopts[] =
 const char *opts = "dhruvV";
 
 static int process_file (const wchar_t *);
+static void *drive_map;
 
 static int
 error (const char *fmt, ...)
@@ -152,6 +154,32 @@ get_module_filename (HANDLE hp, HMODULE hm)
   return buf;
 }
 
+static BOOL
+GetFileNameFromHandle(HANDLE hFile, WCHAR pszFilename[MAX_PATH+1])
+{
+  BOOL result = FALSE;
+  ULONG len = 0;
+  OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) alloca (65536);
+  NTSTATUS status = NtQueryObject (hFile, ObjectNameInformation,
+   ntfn, 65536, );
+  if (NT_SUCCESS (status))
+{
+  PWCHAR win32path = ntfn->Name.Buffer;
+  win32path[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
+
+  /* NtQueryObject returns a native NT path.  (Try to) convert to Win32. */
+  if (!drive_map)
+drive_map = (void *) cygwin_internal (CW_ALLOC_DRIVE_MAP);
+  if (drive_map)
+win32path = (PWCHAR) cygwin_internal (CW_MAP_DRIVE_MAP, drive_map,
+  win32path);
+  pszFilename[0] = L'\0';
+  wcsncat (pszFilename, win32path, MAX_PATH);
+  result = TRUE;
+}
+  return result;
+}
+
 static wchar_t *
 load_dll (const wchar_t *fn)
 {
@@ -215,6 +243,7 @@ start_process (const wchar_t *fn, bool& isdll)
 struct dlls
   {
 LPVOID lpBaseOfDll;
+HANDLE hFile;
 struct dlls *next;
   };
 
@@ -256,7 +285,17 @@ print_dlls (dlls *dll, const wchar_t *dllfn, const wchar_t 
*process_fn)
   char *fn;
   wchar_t *fullpath = get_module_filename (hProcess, (HMODULE) 
dll->lpBaseOfDll);
   if (!fullpath)
-   fn = strdup ("???");
+   {
+ // if no path found yet, try getting it from an open handle to the DLL
+ wchar_t dllname[MAX_PATH+1];
+ if (GetFileNameFromHandle (dll->hFile, dllname))
+   {
+ fn = tocyg (dllname);
+ saw_file (basename (fn));
+   }
+ else
+   fn = strdup ("???");
+   }
   else if (dllfn && wcscmp (fullpath, dllfn) == 0)
{
  free (fullpath);
@@ -340,6 +379,7 @@ report (const char *in_fn, bool multiple)
case LOAD_DLL_DEBUG_EVENT:
  dll_last->next = (dlls *) malloc (sizeof (dlls));
  dll_last->next->lpBaseOfDll = ev.u.LoadDll.lpBaseOfDll;
+ dll_last->next->hFile = ev.u.LoadDll.hFile;
  dll_last->next->next = NULL;
  dll_last = dll_last->next;
  break;
@@ -423,6 +463,8 @@ main (int argc, char **argv)
   while ((fn = *argv++))
 if (report (fn, multiple))
   ret = 1;
+  if (drive_map)
+cygwin_internal (CW_FREE_DRIVE_MAP, drive_map);
   exit (ret);
 }
 
-- 
2.21.0



Re: [PATCH v2] Cygwin: Implement CPU_SET(3) macros

2019-08-04 Thread Mark Geisert

Sorry for the repetition...

On Sun, 4 Aug 2019, Mark Geisert wrote:

This patch supplies an implementation of the CPU_SET(3) processor
affinity macros as documented on the relevant Linux man page.

There is a different implementation of cpusets under libc/sys/RTEMS that
has FreeBSD compatibility and is built on top of FreeBSD bitsets.  This
implementation can be combined with that one if necessary in the future.


If the 2nd para is to be kept, please adjust it to read as follows:

There is a mostly superset implementation of cpusets under newlib's
libc/sys/RTEMS/include/sys that has Linux and FreeBSD compatibility
and is built on top of FreeBSD bitsets.  This Cygwin implementation
and the RTEMS one could be combined if desired at some future point.

Thanks,

..mark


[PATCH v2] Cygwin: Implement CPU_SET(3) macros

2019-08-04 Thread Mark Geisert
This patch supplies an implementation of the CPU_SET(3) processor
affinity macros as documented on the relevant Linux man page.

There is a different implementation of cpusets under libc/sys/RTEMS that
has FreeBSD compatibility and is built on top of FreeBSD bitsets.  This
implementation can be combined with that one if necessary in the future.

---
 winsup/cygwin/include/sys/cpuset.h | 64 +-
 1 file changed, 62 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 4857b879d..2056f6af7 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -18,8 +18,8 @@ typedef __SIZE_TYPE__ __cpu_mask;
 #define __NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
 #define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  // maximum group number
 
-#define __CPUELT(cpu)   ((cpu) / __NCPUBITS)
-#define __CPUMASK(cpu)  ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
+#define __CPUELT(cpu)  ((cpu) / __NCPUBITS)
+#define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
 
 typedef struct
 {
@@ -28,6 +28,66 @@ typedef struct
 
 int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
 
+/* These macros alloc or free dynamically-sized cpu sets of size 'num' cpus.
+   Allocations are padded such that full-word operations can be done easily. */
+#define CPU_ALLOC_SIZE(num) ((num+__NCPUBITS-1) / __NCPUBITS) * sizeof 
(__cpu_mask)
+#define CPU_ALLOC(num)  __builtin_malloc (CPU_ALLOC_SIZE(num))
+#define CPU_FREE(set)   __builtin_free (set)
+
+/* These _S macros operate on dynamically-sized cpu sets of size 'siz' bytes */
+#define CPU_ZERO_S(siz, set)__builtin_memset (set, 0, siz)
+
+#define CPU_SET_S(cpu,siz,set) \
+   if (cpu < 8 * siz) \
+ (set)->__bits[__CPUELT(cpu)] |= __CPUMASK(cpu);
+
+#define CPU_CLR_S(cpu,siz,set) \
+   if (cpu < 8 * siz) \
+ (set)->__bits[__CPUELT(cpu)] &= ~(__CPUMASK(cpu));
+
+#define CPU_ISSET_S(cpu,siz,set) \
+  ({int res = 0; \
+   if (cpu < 8 * siz) \
+ res = !!((set)->__bits[__CPUELT(cpu)] & __CPUMASK(cpu)); \
+   res;})
+
+#define CPU_COUNT_S(siz, set) \
+  ({int tot = 0;\
+   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
+ tot += __builtin_popcountl ((set)->__bits[i]); \
+   tot;})
+
+#define CPU_AND_S(siz, dst, src1, src2) \
+   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
+ (dst)->__bits[i] = (src1)->__bits[i] & (src2)->__bits[i];
+
+#define CPU_OR_S(siz, dst, src1, src2) \
+   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
+ (dst)->__bits[i] = (src1)->__bits[i] | (src2)->__bits[i];
+
+#define CPU_XOR_S(siz, dst, src1, src2) \
+   for (int i = 0; i < siz / sizeof (__cpu_mask); i++) \
+ (dst)->__bits[i] = (src1)->__bits[i] ^ (src2)->__bits[i];
+
+#define CPU_EQUAL_S(siz, src1, src2) \
+  ({int res = 1; \
+   for (int i = 0; res && i < siz / sizeof (__cpu_mask); i++) \
+ res &= (src1)->__bits[i] == (src2)->__bits[i]; \
+   res;})
+
+/* These macros operate on fixed-size cpu sets of size __CPU_SETSIZE cpus */
+#define CPU_ZERO(set) CPU_ZERO_S(sizeof (cpu_set_t), set)
+
+#define CPU_SET(cpu, set) CPU_SET_S(cpu, sizeof (cpu_set_t), set)
+#define CPU_CLR(cpu, set) CPU_CLR_S(cpu, sizeof (cpu_set_t), set)
+#define CPU_ISSET(cpu, set)   CPU_ISSET_S(cpu, sizeof (cpu_set_t), set)
+
+#define CPU_COUNT(set)CPU_COUNT_S(sizeof (cpu_set_t), set)
+#define CPU_AND(dst, src1, src2)  CPU_AND_S(sizeof (cpu_set_t), dst, src1, 
src2)
+#define CPU_OR(dst, src1, src2)   CPU_OR_S(sizeof (cpu_set_t), dst, src1, src2)
+#define CPU_XOR(dst, src1, src2)  CPU_XOR_S(sizeof (cpu_set_t), dst, src1, 
src2)
+#define CPU_EQUAL(src1, src2) CPU_EQUAL_S(sizeof (cpu_set_t), src1, src2)
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.21.0



Re: [PATCH] Cygwin: Implement CPU_SET(3) macros

2019-07-30 Thread Mark Geisert

On Fri, 26 Jul 2019, Corinna Vinschen wrote:

On Jul 25 14:15, Mark Geisert wrote:

Corinna Vinschen wrote:

Hi Mark,

On Jul  1 01:55, Mark Geisert wrote:

Corinna Vinschen wrote:

On Jun 30 15:59, Mark Geisert wrote:

This patch supplies an implementation of the CPU_SET(3) processor
affinity macros as documented on the relevant Linux man page.
---
   winsup/cygwin/include/sys/cpuset.h | 62 +++---
   winsup/cygwin/sched.cc |  8 ++--
   2 files changed, 60 insertions(+), 10 deletions(-)
[...]
+#define CPU_SETSIZE  1024  // maximum number of logical processors tracked
+#define NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
+#define CPU_GROUPMAX (CPU_SETSIZE / NCPUBITS)  // maximum group number
-#define __CPUELT(cpu)   ((cpu) / __NCPUBITS)
-#define __CPUMASK(cpu)  ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
+#define CPU_WORD(cpu) ((cpu) / NCPUBITS)
+#define CPU_MASK(cpu) ((__cpu_mask) 1 << ((cpu) % NCPUBITS))


I wouldn't do that.  Three problems:
[...]
There's also the request from Sebastian on the newlib list to
consolidate the cpuset stuff from RTEMS and Cygwin into a single
definition.
[...]

I've also found that taskset isn't working properly on my build system with
the new CPU_SET code, though my other testcases are.  So even as submitted,
and fixed per your comments here, there's a bit more to be done.

..mark


any chance to pick this up again?


I've been looking at this suggestion to consolidate the cpuset stuff from 
RTEMS and Cygwin.  There is no location common to both platforms to put 
this stuff other than Newlib's libc directory or maybe a non-sys subdir 
of libc.  If situated there, it could impact other newlib platforms, 
possibly.  It also seems a little messy to me to have to put four include 
files there.. cpuset.h, _cpuset.h, bitset.h, and _bitset.h.  Maybe I'm 
overthinking it.


RTEMS' cpuset.h is built on bitset.h, which is fine but the cpuset.h I 
wrote is self-contained and makes use of gcc builtins rather than C 
library calls for malloc, free, popcount, etc.  Mine is 32/64 agnostic, I 
believe RTEMS is too but I'm not totally sure; it depends on the length 
of 'long' items.


RTEMS' implementation includes some code modules needing to be linked into 
libc while the one I wrote is all in header files with some inline code.


These are all just minor implementation differences but I'm still hung up 
on the question of just where a common implementation could be placed in 
the source tree so both RTEMS and Cygwin can use them but other newlib 
platforms won't be tripped up.


..mark

P.S. IRC would be better for this kind of discussion. I'm waiting for my 
freenode registration to be processed.


Re: [PATCH] Cygwin: Implement CPU_SET(3) macros

2019-07-25 Thread Mark Geisert

Corinna Vinschen wrote:

Hi Mark,

On Jul  1 01:55, Mark Geisert wrote:

Corinna Vinschen wrote:

On Jun 30 15:59, Mark Geisert wrote:

This patch supplies an implementation of the CPU_SET(3) processor
affinity macros as documented on the relevant Linux man page.
---
   winsup/cygwin/include/sys/cpuset.h | 62 +++---
   winsup/cygwin/sched.cc |  8 ++--
   2 files changed, 60 insertions(+), 10 deletions(-)
[...]
+#define CPU_SETSIZE  1024  // maximum number of logical processors tracked
+#define NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
+#define CPU_GROUPMAX (CPU_SETSIZE / NCPUBITS)  // maximum group number
-#define __CPUELT(cpu)   ((cpu) / __NCPUBITS)
-#define __CPUMASK(cpu)  ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
+#define CPU_WORD(cpu) ((cpu) / NCPUBITS)
+#define CPU_MASK(cpu) ((__cpu_mask) 1 << ((cpu) % NCPUBITS))


I wouldn't do that.  Three problems:
[...]
There's also the request from Sebastian on the newlib list to
consolidate the cpuset stuff from RTEMS and Cygwin into a single
definition.
[...]

I've also found that taskset isn't working properly on my build system with
the new CPU_SET code, though my other testcases are.  So even as submitted,
and fixed per your comments here, there's a bit more to be done.

..mark


any chance to pick this up again?


Hi; yes, certainly. I'm back but ill. It may be a week or so before I have an 
update/fix. Top of my list of pending items that require concentration ;-).


..mark


Re: [PATCH] Cygwin: Implement CPU_SET(3) macros

2019-07-01 Thread Mark Geisert

Corinna Vinschen wrote:

Hi Mark,

On Jun 30 15:59, Mark Geisert wrote:

This patch supplies an implementation of the CPU_SET(3) processor
affinity macros as documented on the relevant Linux man page.
---
  winsup/cygwin/include/sys/cpuset.h | 62 +++---
  winsup/cygwin/sched.cc |  8 ++--
  2 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/winsup/cygwin/include/sys/cpuset.h 
b/winsup/cygwin/include/sys/cpuset.h
index 4857b879d..9c8417b73 100644
--- a/winsup/cygwin/include/sys/cpuset.h
+++ b/winsup/cygwin/include/sys/cpuset.h
@@ -14,20 +14,70 @@ extern "C" {
  #endif
  
  typedef __SIZE_TYPE__ __cpu_mask;

-#define __CPU_SETSIZE 1024  // maximum number of logical processors tracked
-#define __NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
-#define __CPU_GROUPMAX (__CPU_SETSIZE / __NCPUBITS)  // maximum group number
+#define CPU_SETSIZE  1024  // maximum number of logical processors tracked
+#define NCPUBITS (8 * sizeof (__cpu_mask))  // max size of processor group
+#define CPU_GROUPMAX (CPU_SETSIZE / NCPUBITS)  // maximum group number
  
-#define __CPUELT(cpu)   ((cpu) / __NCPUBITS)

-#define __CPUMASK(cpu)  ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
+#define CPU_WORD(cpu) ((cpu) / NCPUBITS)
+#define CPU_MASK(cpu) ((__cpu_mask) 1 << ((cpu) % NCPUBITS))


I wouldn't do that.  Three problems:

- The non-underscored definitions should only be exposed #if __GNU_VISIBLE
   because otherwise they clutter the application namespace.


Ah, I didn't consider that.  Will wrap appropriately.


- CPU_WORD and CPU_MASK don't exist at all in glibc, so I don't see
   why you rename __CPUELT and __CPUMASK at all.


Conflicting goals and I made a wrong choice.  I thought leading underscores 
meant "implementation details" and so should not be directly used by apps.  And 
I was trying to distinguish this implementation from glibc's per Eric's comment 
on the newlib list.  I figured these two macros would be useful to app coders so 
renamed them to indicate they can use them.


And then I found taskset uses one or more of the underscored ones... So I'll 
revert this bit.



- CPU_GROUPMAX does not exist in glibc either. As a non-standard
   macro it should be kept underscored.


Not in glibc because it's a Windows-related construct.  Will keep underscored.


Keep (and use) the underscored variations throughout, and only expose
the non-underscored macro set #if __GNU_VISIBLE.


Got it.  Thanks!


There's also the request from Sebastian on the newlib list to
consolidate the cpuset stuff from RTEMS and Cygwin into a single
definition.  It's not exactly straightforward given the different
definition of cpuset_t from FreeBSD, but it's probably not very
complicated either.  Maybe something for after your vaca?


Yes, later if at all :-).  I looked at the FreeBSD 11.0 man page for CPUSET(9), 
as they call it, from

https://www.freebsd.org/cgi/man.cgi?query=cpuset=9=0=FreeBSD+11.0-RELEASE+and+Ports
and see that there's some family resemblance but many differences.  I'll have to 
look at RTEMS' again to see how they combined FreeBSD and Linux variants.


I've also found that taskset isn't working properly on my build system with the 
new CPU_SET code, though my other testcases are.  So even as submitted, and 
fixed per your comments here, there's a bit more to be done.


..mark


  1   2   >