Skip to content

Commit

Permalink
Merge branch 'js/windows'
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Junio C Hamano committed Jan 19, 2010
2 parents ff6d26a + a6d15bc commit 3cd02df
Show file tree
Hide file tree
Showing 8 changed files with 329 additions and 133 deletions.
15 changes: 9 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ LIB_H += commit.h
LIB_H += compat/bswap.h
LIB_H += compat/cygwin.h
LIB_H += compat/mingw.h
LIB_H += compat/win32/pthread.h
LIB_H += csum-file.h
LIB_H += decorate.h
LIB_H += delta.h
Expand Down Expand Up @@ -995,15 +996,16 @@ ifeq ($(uname_S),Windows)
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
NO_REGEX = YesPlease
NO_CURL = YesPlease
NO_PTHREADS = YesPlease
NO_PYTHON = YesPlease
BLK_SHA1 = YesPlease
THREADED_DELTA_SEARCH = YesPlease

CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
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
COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o
COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\"
COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
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\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib
lib =
Expand Down Expand Up @@ -1045,10 +1047,13 @@ 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
COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o
COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \
compat/win32/pthread.o
EXTLIBS += -lws2_32
X = .exe
ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
Expand All @@ -1058,10 +1063,8 @@ ifneq (,$(wildcard ../THIS_IS_MSYSGIT))
EXTLIBS += /mingw/lib/libz.a
NO_R_TO_GCC_LINKER = YesPlease
INTERNAL_QSORT = YesPlease
THREADED_DELTA_SEARCH = YesPlease
else
NO_CURL = YesPlease
NO_PTHREADS = YesPlease
endif
endif

Expand Down
31 changes: 27 additions & 4 deletions builtin-pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,15 +1256,15 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,

#ifdef THREADED_DELTA_SEARCH

static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t read_mutex;
#define read_lock() pthread_mutex_lock(&read_mutex)
#define read_unlock() pthread_mutex_unlock(&read_mutex)

static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t cache_mutex;
#define cache_lock() pthread_mutex_lock(&cache_mutex)
#define cache_unlock() pthread_mutex_unlock(&cache_mutex)

static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t progress_mutex;
#define progress_lock() pthread_mutex_lock(&progress_mutex)
#define progress_unlock() pthread_mutex_unlock(&progress_mutex)

Expand Down Expand Up @@ -1591,7 +1591,26 @@ struct thread_params {
unsigned *processed;
};

static pthread_cond_t progress_cond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t progress_cond;

/*
* Mutex and conditional variable can't be statically-initialized on Windows.
*/
static void init_threaded_search(void)
{
pthread_mutex_init(&read_mutex, NULL);
pthread_mutex_init(&cache_mutex, NULL);
pthread_mutex_init(&progress_mutex, NULL);
pthread_cond_init(&progress_cond, NULL);
}

static void cleanup_threaded_search(void)
{
pthread_cond_destroy(&progress_cond);
pthread_mutex_destroy(&read_mutex);
pthread_mutex_destroy(&cache_mutex);
pthread_mutex_destroy(&progress_mutex);
}

static void *threaded_find_deltas(void *arg)
{
Expand Down Expand Up @@ -1630,10 +1649,13 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
struct thread_params *p;
int i, ret, active_threads = 0;

init_threaded_search();

if (!delta_search_threads) /* --threads=0 means autodetect */
delta_search_threads = online_cpus();
if (delta_search_threads <= 1) {
find_deltas(list, &list_size, window, depth, processed);
cleanup_threaded_search();
return;
}
if (progress > pack_to_stdout)
Expand Down Expand Up @@ -1748,6 +1770,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
active_threads--;
}
}
cleanup_threaded_search();
free(p);
}

Expand Down
116 changes: 59 additions & 57 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
#include <conio.h>
#include "../strbuf.h"

#include <shellapi.h>

static int err_win_to_posix(DWORD winerr)
int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
Expand Down Expand Up @@ -142,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.
Expand Down Expand Up @@ -283,64 +289,37 @@ 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;
}

int pipe(int filedes[2])
{
int fd;
HANDLE h[2], parent;
HANDLE h[2];

if (_pipe(filedes, 8192, 0) < 0)
return -1;

parent = GetCurrentProcess();

if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[0]),
parent, &h[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
close(filedes[0]);
close(filedes[1]);
return -1;
}
if (!DuplicateHandle (parent, (HANDLE)_get_osfhandle(filedes[1]),
parent, &h[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) {
close(filedes[0]);
close(filedes[1]);
CloseHandle(h[0]);
/* this creates non-inheritable handles */
if (!CreatePipe(&h[0], &h[1], NULL, 8192)) {
errno = err_win_to_posix(GetLastError());
return -1;
}
fd = _open_osfhandle((int)h[0], O_NOINHERIT);
if (fd < 0) {
close(filedes[0]);
close(filedes[1]);
filedes[0] = _open_osfhandle((int)h[0], O_NOINHERIT);
if (filedes[0] < 0) {
CloseHandle(h[0]);
CloseHandle(h[1]);
return -1;
}
close(filedes[0]);
filedes[0] = fd;
fd = _open_osfhandle((int)h[1], O_NOINHERIT);
if (fd < 0) {
filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT);
if (filedes[0] < 0) {
close(filedes[0]);
close(filedes[1]);
CloseHandle(h[1]);
return -1;
}
close(filedes[1]);
filedes[1] = fd;
return 0;
}

Expand Down Expand Up @@ -638,8 +617,8 @@ static int env_compare(const void *a, const void *b)
return strcasecmp(*ea, *eb);
}

static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
int prepend_cmd)
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
int prepend_cmd, int fhin, int fhout, int fherr)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
Expand Down Expand Up @@ -675,9 +654,9 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = (HANDLE) _get_osfhandle(0);
si.hStdOutput = (HANDLE) _get_osfhandle(1);
si.hStdError = (HANDLE) _get_osfhandle(2);
si.hStdInput = (HANDLE) _get_osfhandle(fhin);
si.hStdOutput = (HANDLE) _get_osfhandle(fhout);
si.hStdError = (HANDLE) _get_osfhandle(fherr);

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

pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
int prepend_cmd)
{
return mingw_spawnve_fd(cmd, argv, env, prepend_cmd, 0, 1, 2);
}

pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
int fhin, int fhout, int fherr)
{
pid_t pid;
char **path = get_path_split();
Expand All @@ -754,13 +740,15 @@ pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)
pid = -1;
}
else {
pid = mingw_spawnve(iprog, argv, env, 1);
pid = mingw_spawnve_fd(iprog, argv, env, 1,
fhin, fhout, fherr);
free(iprog);
}
argv[0] = argv0;
}
else
pid = mingw_spawnve(prog, argv, env, 0);
pid = mingw_spawnve_fd(prog, argv, env, 0,
fhin, fhout, fherr);
free(prog);
}
free_path_split(path);
Expand Down Expand Up @@ -1338,8 +1326,22 @@ static const char *make_backslash_path(const char *path)
void mingw_open_html(const char *unixpath)
{
const char *htmlpath = make_backslash_path(unixpath);
typedef HINSTANCE (WINAPI *T)(HWND, const char *,
const char *, const char *, const char *, INT);
T ShellExecute;
HMODULE shell32;

shell32 = LoadLibrary("shell32.dll");
if (!shell32)
die("cannot load shell32.dll");
ShellExecute = (T)GetProcAddress(shell32, "ShellExecuteA");
if (!ShellExecute)
die("cannot run browser");

printf("Launching default browser to display HTML ...\n");
ShellExecute(NULL, "open", htmlpath, NULL, "\\", 0);

FreeLibrary(shell32);
}

int link(const char *oldpath, const char *newpath)
Expand Down
12 changes: 10 additions & 2 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,18 +209,21 @@ 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

pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env);
pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env,
int fhin, int fhout, int fherr);
void mingw_execvp(const char *cmd, char *const *argv);
#define execvp mingw_execvp

Expand Down Expand Up @@ -307,3 +310,8 @@ struct mingw_dirent
#define readdir(x) mingw_readdir(x)
struct dirent *mingw_readdir(DIR *dir);
#endif // !NO_MINGW_REPLACE_READDIR

/*
* Used by Pthread API implementation for Windows
*/
extern int err_win_to_posix(DWORD winerr);
40 changes: 16 additions & 24 deletions compat/msvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 3cd02df

Please sign in to comment.