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; -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html