git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/7] Miscellaneous improvements on Windows

From
Johannes Sixt <j6t@kdbg.org>
Date
Jan 15, 2010, 20:12 UTC
Message-ID
<cover.1263584975.git.j6t@kdbg.org>
In-Reply-To
<cover.1262895936.git.j6t@kdbg.org>

This round updates Andrzej's pthread patch to use Interlocked* functions. I merged my follow-up that enables pthreads on MinGW into this patch.

There are three new patches:
- Erik's patch that disables Python
- Ramsay's MSVC warning fix.
- A new gettimeofday implementation that does not call out from mingw.c
  (compatibility layer) to the generic code anymore.
The interdiff to the previous round is below.
Andrzej K. Haczewski (1):
  MSVC: Windows-native implementation for subset of Pthreads API
Erik Faye-Lund (1):
  Windows: disable Python
Johannes Sixt (4):
  Windows: boost startup by avoiding a static dependency on shell32.dll
  Windows: simplify the pipe(2) implementation
  Windows: avoid the "dup dance" when spawning a child process
  Do not use date.c:tm_to_time_t() from compat/mingw.c
Ramsay Allan Jones (1):
  MSVC: Fix an "incompatible pointer types" compiler warning
 Makefile               |   15 ++++---
 builtin-pack-objects.c |   31 +++++++++++--
 compat/mingw.c         |  116 ++++++++++++++++++++++++-----------------------
 compat/mingw.h         |   12 ++++-
 compat/msvc.h          |   40 +++++++----------
 compat/win32/pthread.c |  110 +++++++++++++++++++++++++++++++++++++++++++++
 compat/win32/pthread.h |   67 +++++++++++++++++++++++++++
 run-command.c          |   71 +++++++++++++----------------
 8 files changed, 329 insertions(+), 133 deletions(-)
 create mode 100644 compat/win32/pthread.c
 create mode 100644 compat/win32/pthread.h
Interdiff:
diff --git a/Makefile b/Makefile
index ffcac04..7f5814c 100644
--- a/Makefile
+++ b/Makefile
@@ -996,8 +996,9 @@ ifeq ($(uname_S),Windows)
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 	NO_REGEX = YesPlease
 	NO_CURL = YesPlease
-	THREADED_DELTA_SEARCH = YesPlease
+	NO_PYTHON = YesPlease
 	BLK_SHA1 = YesPlease
+	THREADED_DELTA_SEARCH = YesPlease
 
 	CC = compat/vcbuild/scripts/clink.pl
 	AR = compat/vcbuild/scripts/lib.pl
@@ -1046,6 +1047,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
 	UNRELIABLE_FSTAT = UnfortunatelyYes
 	OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
 	NO_REGEX = YesPlease
+	NO_PYTHON = YesPlease
 	BLK_SHA1 = YesPlease
 	THREADED_DELTA_SEARCH = YesPlease
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
diff --git a/compat/mingw.c b/compat/mingw.c
index 74ffc18..ab65f77 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -140,12 +140,20 @@ int mingw_open (const char *filename, int oflags, ...)
 	return fd;
 }
 
-static inline time_t filetime_to_time_t(const FILETIME *ft)
+/*
+ * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
+ * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
+ */
+static inline long long filetime_to_hnsec(const FILETIME *ft)
 {
 	long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
-	winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
-	winTime /= 10000000;		 /* Nano to seconds resolution */
-	return (time_t)winTime;
+	/* Windows to Unix Epoch conversion */
+	return winTime - 116444736000000000LL;
+}
+
+static inline time_t filetime_to_time_t(const FILETIME *ft)
+{
+	return (time_t)(filetime_to_hnsec(ft) / 10000000);
 }
 
 /* We keep the do_lstat code in a separate function to avoid recursion.
@@ -281,19 +289,13 @@ int mkstemp(char *template)
 
 int gettimeofday(struct timeval *tv, void *tz)
 {
-	SYSTEMTIME st;
-	struct tm tm;
-	GetSystemTime(&st);
-	tm.tm_year = st.wYear-1900;
-	tm.tm_mon = st.wMonth-1;
-	tm.tm_mday = st.wDay;
-	tm.tm_hour = st.wHour;
-	tm.tm_min = st.wMinute;
-	tm.tm_sec = st.wSecond;
-	tv->tv_sec = tm_to_time_t(&tm);
-	if (tv->tv_sec < 0)
-		return -1;
-	tv->tv_usec = st.wMilliseconds*1000;
+	FILETIME ft;
+	long long hnsec;
+
+	GetSystemTimeAsFileTime(&ft);
+	hnsec = filetime_to_hnsec(&ft);
+	tv->tv_sec = hnsec / 10000000;
+	tv->tv_usec = (hnsec % 10000000) / 10;
 	return 0;
 }
 
diff --git a/compat/mingw.h b/compat/mingw.h
index 238fd70..e254fb4 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -209,13 +209,15 @@ int mingw_getpagesize(void);
  * mingw_fstat() instead of fstat() on Windows.
  */
 #define off_t off64_t
-#define stat _stati64
 #define lseek _lseeki64
+#ifndef ALREADY_DECLARED_STAT_FUNCS
+#define stat _stati64
 int mingw_lstat(const char *file_name, struct stat *buf);
 int mingw_fstat(int fd, struct stat *buf);
 #define fstat mingw_fstat
 #define lstat mingw_lstat
 #define _stati64(x,y) mingw_lstat(x,y)
+#endif
 
 int mingw_utime(const char *file_name, const struct utimbuf *times);
 #define utime mingw_utime
diff --git a/compat/msvc.h b/compat/msvc.h
index 9c753a5..023aba0 100644
--- a/compat/msvc.h
+++ b/compat/msvc.h
@@ -21,30 +21,22 @@ static __inline int strcasecmp (const char *s1, const char *s2)
 }
 
 #undef ERROR
-#undef stat
-#undef _stati64
-#include "compat/mingw.h"
-#undef stat
-#define stat _stati64
+
+/* Use mingw_lstat() instead of lstat()/stat() and mingw_fstat() instead
+ * of fstat(). We add the declaration of these functions here, suppressing
+ * the corresponding declarations in mingw.h, so that we can use the
+ * appropriate structure type (and function) names from the msvc headers.
+ */
+#define stat _stat64
+int mingw_lstat(const char *file_name, struct stat *buf);
+int mingw_fstat(int fd, struct stat *buf);
+#define fstat mingw_fstat
+#define lstat mingw_lstat
 #define _stat64(x,y) mingw_lstat(x,y)
+#define ALREADY_DECLARED_STAT_FUNCS
+
+#include "compat/mingw.h"
+
+#undef ALREADY_DECLARED_STAT_FUNCS
 
-/*
-   Even though _stati64 is normally just defined at _stat64
-   on Windows, we specify it here as a proper struct to avoid
-   compiler warnings about macro redefinition due to magic in
-   mingw.h. Struct taken from ReactOS (GNU GPL license).
-*/
-struct _stati64 {
-	_dev_t  st_dev;
-	_ino_t  st_ino;
-	unsigned short st_mode;
-	short   st_nlink;
-	short   st_uid;
-	short   st_gid;
-	_dev_t  st_rdev;
-	__int64 st_size;
-	time_t  st_atime;
-	time_t  st_mtime;
-	time_t  st_ctime;
-};
 #endif
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 652d7b4..631c0a4 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c
@@ -53,8 +53,6 @@ int pthread_cond_init(pthread_cond_t *cond, const void *unused)
 {
 	cond->waiters = 0;
 
-	InitializeCriticalSection(&cond->waiters_lock);
-
 	cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
 	if (!cond->sema)
 		die("CreateSemaphore() failed");
@@ -66,17 +64,12 @@ int pthread_cond_destroy(pthread_cond_t *cond)
 	CloseHandle(cond->sema);
 	cond->sema = NULL;
 
-	DeleteCriticalSection(&cond->waiters_lock);
-
 	return 0;
 }
 
 int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
 {
-	/* serialize access to waiters count */
-	EnterCriticalSection(&cond->waiters_lock);
-	++cond->waiters;
-	LeaveCriticalSection(&cond->waiters_lock);
+	InterlockedIncrement(&cond->waiters);
 
 	/*
 	 * Unlock external mutex and wait for signal.
@@ -90,9 +83,7 @@ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
 	WaitForSingleObject(cond->sema, INFINITE);
 
 	/* we're done waiting, so make sure we decrease waiters count */
-	EnterCriticalSection(&cond->waiters_lock);
-	--cond->waiters;
-	LeaveCriticalSection(&cond->waiters_lock);
+	InterlockedDecrement(&cond->waiters);
 
 	/* lock external mutex again */
 	EnterCriticalSection(mutex);
@@ -102,12 +93,11 @@ int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
 
 int pthread_cond_signal(pthread_cond_t *cond)
 {
-	int have_waiters;
-
-	/* serialize access to waiters count */
-	EnterCriticalSection(&cond->waiters_lock);
-	have_waiters = cond->waiters > 0;
-	LeaveCriticalSection(&cond->waiters_lock);
+	/*
+	 * Access to waiters count is atomic; see "Interlocked Variable Access"
+	 * http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx
+	 */
+	int have_waiters = cond->waiters > 0;
 
 	/*
 	 * Signal only when there are waiters
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index 47888e4..b8e1bcb 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h
@@ -32,8 +32,7 @@
  * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
  */
 typedef struct {
-	LONG waiters;
-	CRITICAL_SECTION waiters_lock;
+	volatile LONG waiters;
 	HANDLE sema;
 } pthread_cond_t;
 
Previous: Johannes SixtNext: Johannes Sixt
Message 17 of 24 in “Miscellaneous improvements on Windows”
  1. 0/5 Miscellaneous improvements on WindowsJohannes Sixt, Jan 7, 2010
  2. 1/5 MSVC: Windows-native implementation for subset of Pthreads APIJohannes Sixt, Jan 7, 2010
  3. Dmitry PotapovJan 8, 2010
  4. Erik Faye-LundJan 8, 2010
  5. Johannes SixtJan 8, 2010
  6. Dmitry PotapovJan 8, 2010
  7. Johannes SixtJan 12, 2010
  8. Dmitry PotapovJan 13, 2010
  9. Johannes SixtJan 13, 2010
  10. Dmitry PotapovJan 14, 2010
  11. Peter HarrisJan 14, 2010
  12. Johannes SixtJan 14, 2010
  13. 2/5 MinGW: enable pthreadsJohannes Sixt, Jan 7, 2010
  14. 3/5 Windows: boost startup by avoiding a static dependency on shell32.dllJohannes Sixt, Jan 7, 2010
  15. 4/5 Windows: simplify the pipe(2) implementationJohannes Sixt, Jan 7, 2010
  16. 5/5 Windows: avoid the "dup dance" when spawning a child processJohannes Sixt, Jan 7, 2010
  17. 0/7 Miscellaneous improvements on WindowsJohannes Sixt, Jan 15, 2010
  18. 1/7 Windows: disable PythonJohannes Sixt, Jan 15, 2010
  19. 2/7 Windows: boost startup by avoiding a static dependency on shell32.dllJohannes Sixt, Jan 15, 2010
  20. 3/7 Windows: simplify the pipe(2) implementationJohannes Sixt, Jan 15, 2010
  21. 4/7 Windows: avoid the "dup dance" when spawning a child processJohannes Sixt, Jan 15, 2010
  22. 5/7 MSVC: Fix an "incompatible pointer types" compiler warningJohannes Sixt, Jan 15, 2010
  23. 6/7 MSVC: Windows-native implementation for subset of Pthreads APIJohannes Sixt, Jan 15, 2010
  24. 7/7 Do not use date.c:tm_to_time_t() from compat/mingw.cJohannes Sixt, Jan 15, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.