Skip to content

Commit 3cd02df

Browse files
committed
Merge branch 'js/windows'
* js/windows: Do not use date.c:tm_to_time_t() from compat/mingw.c MSVC: Windows-native implementation for subset of Pthreads API MSVC: Fix an "incompatible pointer types" compiler warning Windows: avoid the "dup dance" when spawning a child process Windows: simplify the pipe(2) implementation Windows: boost startup by avoiding a static dependency on shell32.dll Windows: disable Python
2 parents ff6d26a + a6d15bc commit 3cd02df

File tree

8 files changed

+329
-133
lines changed

8 files changed

+329
-133
lines changed

Makefile

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,7 @@ LIB_H += commit.h
478478
LIB_H += compat/bswap.h
479479
LIB_H += compat/cygwin.h
480480
LIB_H += compat/mingw.h
481+
LIB_H += compat/win32/pthread.h
481482
LIB_H += csum-file.h
482483
LIB_H += decorate.h
483484
LIB_H += delta.h
@@ -995,15 +996,16 @@ ifeq ($(uname_S),Windows)
995996
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
996997
NO_REGEX = YesPlease
997998
NO_CURL = YesPlease
998-
NO_PTHREADS = YesPlease
999+
NO_PYTHON = YesPlease
9991000
BLK_SHA1 = YesPlease
1001+
THREADED_DELTA_SEARCH = YesPlease
10001002

10011003
CC = compat/vcbuild/scripts/clink.pl
10021004
AR = compat/vcbuild/scripts/lib.pl
10031005
CFLAGS =
10041006
BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
1005-
COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o
1006-
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\"
1007+
COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
1008+
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
10071009
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
10081010
EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib
10091011
lib =
@@ -1045,10 +1047,13 @@ ifneq (,$(findstring MINGW,$(uname_S)))
10451047
UNRELIABLE_FSTAT = UnfortunatelyYes
10461048
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
10471049
NO_REGEX = YesPlease
1050+
NO_PYTHON = YesPlease
10481051
BLK_SHA1 = YesPlease
1052+
THREADED_DELTA_SEARCH = YesPlease
10491053
COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch
10501054
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
1051-
COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
1055+
COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
1056+
compat/win32/pthread.o
10521057
EXTLIBS += -lws2_32
10531058
X = .exe
10541059
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
@@ -1058,10 +1063,8 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
10581063
EXTLIBS += /mingw/lib/libz.a
10591064
NO_R_TO_GCC_LINKER = YesPlease
10601065
INTERNAL_QSORT = YesPlease
1061-
THREADED_DELTA_SEARCH = YesPlease
10621066
else
10631067
NO_CURL = YesPlease
1064-
NO_PTHREADS = YesPlease
10651068
endif
10661069
endif
10671070

builtin-pack-objects.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,15 +1256,15 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
12561256

12571257
#ifdef THREADED_DELTA_SEARCH
12581258

1259-
static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
1259+
static pthread_mutex_t read_mutex;
12601260
#define read_lock() pthread_mutex_lock(&read_mutex)
12611261
#define read_unlock() pthread_mutex_unlock(&read_mutex)
12621262

1263-
static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
1263+
static pthread_mutex_t cache_mutex;
12641264
#define cache_lock() pthread_mutex_lock(&cache_mutex)
12651265
#define cache_unlock() pthread_mutex_unlock(&cache_mutex)
12661266

1267-
static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
1267+
static pthread_mutex_t progress_mutex;
12681268
#define progress_lock() pthread_mutex_lock(&progress_mutex)
12691269
#define progress_unlock() pthread_mutex_unlock(&progress_mutex)
12701270

@@ -1591,7 +1591,26 @@ struct thread_params {
15911591
unsigned *processed;
15921592
};
15931593

1594-
static pthread_cond_t progress_cond = PTHREAD_COND_INITIALIZER;
1594+
static pthread_cond_t progress_cond;
1595+
1596+
/*
1597+
* Mutex and conditional variable can't be statically-initialized on Windows.
1598+
*/
1599+
static void init_threaded_search(void)
1600+
{
1601+
pthread_mutex_init(&read_mutex, NULL);
1602+
pthread_mutex_init(&cache_mutex, NULL);
1603+
pthread_mutex_init(&progress_mutex, NULL);
1604+
pthread_cond_init(&progress_cond, NULL);
1605+
}
1606+
1607+
static void cleanup_threaded_search(void)
1608+
{
1609+
pthread_cond_destroy(&progress_cond);
1610+
pthread_mutex_destroy(&read_mutex);
1611+
pthread_mutex_destroy(&cache_mutex);
1612+
pthread_mutex_destroy(&progress_mutex);
1613+
}
15951614

15961615
static void *threaded_find_deltas(void *arg)
15971616
{
@@ -1630,10 +1649,13 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
16301649
struct thread_params *p;
16311650
int i, ret, active_threads = 0;
16321651

1652+
init_threaded_search();
1653+
16331654
if (!delta_search_threads) /* --threads=0 means autodetect */
16341655
delta_search_threads = online_cpus();
16351656
if (delta_search_threads <= 1) {
16361657
find_deltas(list, &list_size, window, depth, processed);
1658+
cleanup_threaded_search();
16371659
return;
16381660
}
16391661
if (progress > pack_to_stdout)
@@ -1748,6 +1770,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
17481770
active_threads--;
17491771
}
17501772
}
1773+
cleanup_threaded_search();
17511774
free(p);
17521775
}
17531776

compat/mingw.c

Lines changed: 59 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
#include <conio.h>
44
#include "../strbuf.h"
55

6-
#include <shellapi.h>
7-
8-
static int err_win_to_posix(DWORD winerr)
6+
int err_win_to_posix(DWORD winerr)
97
{
108
int error = ENOSYS;
119
switch(winerr) {
@@ -142,12 +140,20 @@ int mingw_open (const char *filename, int oflags, ...)
142140
return fd;
143141
}
144142

145-
static inline time_t filetime_to_time_t(const FILETIME *ft)
143+
/*
144+
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
145+
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
146+
*/
147+
static inline long long filetime_to_hnsec(const FILETIME *ft)
146148
{
147149
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
148-
winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
149-
winTime /= 10000000; /* Nano to seconds resolution */
150-
return (time_t)winTime;
150+
/* Windows to Unix Epoch conversion */
151+
return winTime - 116444736000000000LL;
152+
}
153+
154+
static inline time_t filetime_to_time_t(const FILETIME *ft)
155+
{
156+
return (time_t)(filetime_to_hnsec(ft) / 10000000);
151157
}
152158

153159
/* We keep the do_lstat code in a separate function to avoid recursion.
@@ -283,64 +289,37 @@ int mkstemp(char *template)
283289

284290
int gettimeofday(struct timeval *tv, void *tz)
285291
{
286-
SYSTEMTIME st;
287-
struct tm tm;
288-
GetSystemTime(&st);
289-
tm.tm_year = st.wYear-1900;
290-
tm.tm_mon = st.wMonth-1;
291-
tm.tm_mday = st.wDay;
292-
tm.tm_hour = st.wHour;
293-
tm.tm_min = st.wMinute;
294-
tm.tm_sec = st.wSecond;
295-
tv->tv_sec = tm_to_time_t(&tm);
296-
if (tv->tv_sec < 0)
297-
return -1;
298-
tv->tv_usec = st.wMilliseconds*1000;
292+
FILETIME ft;
293+
long long hnsec;
294+
295+
GetSystemTimeAsFileTime(&ft);
296+
hnsec = filetime_to_hnsec(&ft);
297+
tv->tv_sec = hnsec / 10000000;
298+
tv->tv_usec = (hnsec % 10000000) / 10;
299299
return 0;
300300
}
301301

302302
int pipe(int filedes[2])
303303
{
304-
int fd;
305-
HANDLE h[2], parent;
304+
HANDLE h[2];
306305

307-
if (_pipe(filedes, 8192, 0) < 0)
308-
return -1;
309-
310-
parent = GetCurrentProcess();
311-
312-
if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),
313-
parent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
314-
close(filedes[0]);
315-
close(filedes[1]);
316-
return -1;
317-
}
318-
if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),
319-
parent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
320-
close(filedes[0]);
321-
close(filedes[1]);
322-
CloseHandle(h[0]);
306+
/* this creates non-inheritable handles */
307+
if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
308+
errno = err_win_to_posix(GetLastError());
323309
return -1;
324310
}
325-
fd = _open_osfhandle((int)h[0], O_NOINHERIT);
326-
if (fd < 0) {
327-
close(filedes[0]);
328-
close(filedes[1]);
311+
filedes[0] = _open_osfhandle((int)h[0], O_NOINHERIT);
312+
if (filedes[0] < 0) {
329313
CloseHandle(h[0]);
330314
CloseHandle(h[1]);
331315
return -1;
332316
}
333-
close(filedes[0]);
334-
filedes[0] = fd;
335-
fd = _open_osfhandle((int)h[1], O_NOINHERIT);
336-
if (fd < 0) {
317+
filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
318+
if (filedes[0] < 0) {
337319
close(filedes[0]);
338-
close(filedes[1]);
339320
CloseHandle(h[1]);
340321
return -1;
341322
}
342-
close(filedes[1]);
343-
filedes[1] = fd;
344323
return 0;
345324
}
346325

@@ -638,8 +617,8 @@ static int env_compare(const void *a, const void *b)
638617
return strcasecmp(*ea, *eb);
639618
}
640619

641-
static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
642-
int prepend_cmd)
620+
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
621+
int prepend_cmd, int fhin, int fhout, int fherr)
643622
{
644623
STARTUPINFO si;
645624
PROCESS_INFORMATION pi;
@@ -675,9 +654,9 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
675654
memset(&si, 0, sizeof(si));
676655
si.cb = sizeof(si);
677656
si.dwFlags = STARTF_USESTDHANDLES;
678-
si.hStdInput = (HANDLE) _get_osfhandle(0);
679-
si.hStdOutput = (HANDLE) _get_osfhandle(1);
680-
si.hStdError = (HANDLE) _get_osfhandle(2);
657+
si.hStdInput = (HANDLE) _get_osfhandle(fhin);
658+
si.hStdOutput = (HANDLE) _get_osfhandle(fhout);
659+
si.hStdError = (HANDLE) _get_osfhandle(fherr);
681660

682661
/* concatenate argv, quoting args as we go */
683662
strbuf_init(&args, 0);
@@ -732,7 +711,14 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
732711
return (pid_t)pi.hProcess;
733712
}
734713

735-
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
714+
static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
715+
int prepend_cmd)
716+
{
717+
return mingw_spawnve_fd(cmd, argv, env, prepend_cmd, 0, 1, 2);
718+
}
719+
720+
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
721+
int fhin, int fhout, int fherr)
736722
{
737723
pid_t pid;
738724
char **path = get_path_split();
@@ -754,13 +740,15 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
754740
pid = -1;
755741
}
756742
else {
757-
pid = mingw_spawnve(iprog, argv, env, 1);
743+
pid = mingw_spawnve_fd(iprog, argv, env, 1,
744+
fhin, fhout, fherr);
758745
free(iprog);
759746
}
760747
argv[0] = argv0;
761748
}
762749
else
763-
pid = mingw_spawnve(prog, argv, env, 0);
750+
pid = mingw_spawnve_fd(prog, argv, env, 0,
751+
fhin, fhout, fherr);
764752
free(prog);
765753
}
766754
free_path_split(path);
@@ -1338,8 +1326,22 @@ static const char *make_backslash_path(const char *path)
13381326
void mingw_open_html(const char *unixpath)
13391327
{
13401328
const char *htmlpath = make_backslash_path(unixpath);
1329+
typedef HINSTANCE (WINAPI *T)(HWND, const char *,
1330+
const char *, const char *, const char *, INT);
1331+
T ShellExecute;
1332+
HMODULE shell32;
1333+
1334+
shell32 = LoadLibrary("shell32.dll");
1335+
if (!shell32)
1336+
die("cannot load shell32.dll");
1337+
ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
1338+
if (!ShellExecute)
1339+
die("cannot run browser");
1340+
13411341
printf("Launching default browser to display HTML ...\n");
13421342
ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);
1343+
1344+
FreeLibrary(shell32);
13431345
}
13441346

13451347
int link(const char *oldpath, const char *newpath)

compat/mingw.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,18 +209,21 @@ int mingw_getpagesize(void);
209209
* mingw_fstat() instead of fstat() on Windows.
210210
*/
211211
#define off_t off64_t
212-
#define stat _stati64
213212
#define lseek _lseeki64
213+
#ifndef ALREADY_DECLARED_STAT_FUNCS
214+
#define stat _stati64
214215
int mingw_lstat(const char *file_name, struct stat *buf);
215216
int mingw_fstat(int fd, struct stat *buf);
216217
#define fstat mingw_fstat
217218
#define lstat mingw_lstat
218219
#define _stati64(x,y) mingw_lstat(x,y)
220+
#endif
219221

220222
int mingw_utime(const char *file_name, const struct utimbuf *times);
221223
#define utime mingw_utime
222224

223-
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
225+
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
226+
int fhin, int fhout, int fherr);
224227
void mingw_execvp(const char *cmd, char *const *argv);
225228
#define execvp mingw_execvp
226229

@@ -307,3 +310,8 @@ struct mingw_dirent
307310
#define readdir(x) mingw_readdir(x)
308311
struct dirent *mingw_readdir(DIR *dir);
309312
#endif // !NO_MINGW_REPLACE_READDIR
313+
314+
/*
315+
* Used by Pthread API implementation for Windows
316+
*/
317+
extern int err_win_to_posix(DWORD winerr);

compat/msvc.h

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,22 @@ static __inline int strcasecmp (const char *s1, const char *s2)
2121
}
2222

2323
#undef ERROR
24-
#undef stat
25-
#undef _stati64
26-
#include "compat/mingw.h"
27-
#undef stat
28-
#define stat _stati64
24+
25+
/* Use mingw_lstat() instead of lstat()/stat() and mingw_fstat() instead
26+
* of fstat(). We add the declaration of these functions here, suppressing
27+
* the corresponding declarations in mingw.h, so that we can use the
28+
* appropriate structure type (and function) names from the msvc headers.
29+
*/
30+
#define stat _stat64
31+
int mingw_lstat(const char *file_name, struct stat *buf);
32+
int mingw_fstat(int fd, struct stat *buf);
33+
#define fstat mingw_fstat
34+
#define lstat mingw_lstat
2935
#define _stat64(x,y) mingw_lstat(x,y)
36+
#define ALREADY_DECLARED_STAT_FUNCS
37+
38+
#include "compat/mingw.h"
39+
40+
#undef ALREADY_DECLARED_STAT_FUNCS
3041

31-
/*
32-
Even though _stati64 is normally just defined at _stat64
33-
on Windows, we specify it here as a proper struct to avoid
34-
compiler warnings about macro redefinition due to magic in
35-
mingw.h. Struct taken from ReactOS (GNU GPL license).
36-
*/
37-
struct _stati64 {
38-
_dev_t st_dev;
39-
_ino_t st_ino;
40-
unsigned short st_mode;
41-
short st_nlink;
42-
short st_uid;
43-
short st_gid;
44-
_dev_t st_rdev;
45-
__int64 st_size;
46-
time_t st_atime;
47-
time_t st_mtime;
48-
time_t st_ctime;
49-
};
5042
#endif

0 commit comments

Comments
 (0)