Rebase our patches on wine-1.7.19
I've confirmed this
- can compile on gTrusty
- can work with VS2013-update2 (I've compiled chrome on this)
- can work with VS2014-CTP
Also, now we don't need TLS-hack any more. So, I've remove such changes
from this CL.
The followings are patches this CL contains.
- workaround fix SetThreadPreferredUILanguages
- workaround fix LoadLibrary for datafile?
- Implement SRWLock
- FIXME->TRACE for SRWLock
- add WINEELFLOADER hack to wine-preloader
- Use timeout for futex_wait in SRWLock
- Add WINENOWINEBOOT environment variable to disable wineboot
- A simple hello world becomes faster (0.121 => 0.024).
- Add codereview.settings
- Workaround for VS2013
-- Workaround for cl.exe deadlock for VS2013.
-- cl.exe for VS2013 sometimes cannot find headers.
- Make wineserver exit immediately
Change-Id: I8c2f39c9f73947bfd644141c14a78aea0b075fd0
diff --git a/codereview.settings b/codereview.settings
new file mode 100644
index 0000000..aa631d7
--- /dev/null
+++ b/codereview.settings
@@ -0,0 +1,6 @@
+# This file is used by git-cl to get repository specific information.
+GERRIT_HOST: goma.googlesource.com
+GERRIT_PORT: 443
+CODE_REVIEW_SERVER: goma-review.googlesource.com
+# gerrit only accepts regiestered users for cc.
+# CC_LIST: goma+review@google.com
diff --git a/dlls/kernel32/module.c b/dlls/kernel32/module.c
index d1555f1..f3adb0a 100644
--- a/dlls/kernel32/module.c
+++ b/dlls/kernel32/module.c
@@ -904,8 +904,13 @@
LOAD_LIBRARY_SEARCH_SYSTEM32 |
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS;
- if( flags & unsupported_flags)
- FIXME("unsupported flag(s) used (flags: 0x%08x)\n", flags);
+ if( flags & unsupported_flags) {
+ FIXME("%s unsupported flag(s) used (flags: 0x%08x)\n", debugstr_wn( libname->Buffer, libname->Length / sizeof(WCHAR) ), flags);
+ if (flags & (LOAD_LIBRARY_AS_IMAGE_RESOURCE|LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE)) {
+ flags |= LOAD_LIBRARY_AS_DATAFILE;
+ FIXME("fix flag: 0x%08x)\n", flags);
+ }
+ }
load_path = MODULE_get_dll_load_path( flags & LOAD_WITH_ALTERED_SEARCH_PATH ? libname->Buffer : NULL );
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 0b70a55..796622d 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -997,6 +997,8 @@
*/
static void start_wineboot( HANDLE handles[2] )
{
+ if (getenv("WINENOWINEBOOT"))
+ return;
static const WCHAR wineboot_eventW[] = {'_','_','w','i','n','e','b','o','o','t','_','e','v','e','n','t',0};
handles[1] = 0;
diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c
index 5d87cdd..ed3a00a 100644
--- a/dlls/kernel32/thread.c
+++ b/dlls/kernel32/thread.c
@@ -25,6 +25,9 @@
#include <fcntl.h>
#include <stdarg.h>
#include <sys/types.h>
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
@@ -827,8 +830,215 @@
*/
BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, PULONG count, PCZZWSTR buffer, PULONG buffersize )
{
- FIXME( "%u, %p, %p %p\n", flags, count, buffer, buffersize );
+ FIXME( "%u, %p(%d), %p %p(%d)\n", flags, count, *count, buffer, buffersize, *buffersize );
*count = 0;
- *buffersize = 0;
+ if (buffer == NULL) {
+ *buffersize = 2;
+ } else {
+ memset(buffer, 0, *buffersize*sizeof(WCHAR));
+ }
return TRUE;
}
+
+// TODO(ukai): move ntdlls/critsection.c?
+
+// copy from ntdlls/critsection.c
+#ifdef __linux__
+
+static int wait_op = 128; /*FUTEX_WAIT|FUTEX_PRIVATE_FLAG*/
+static int wake_op = 129; /*FUTEX_WAKE|FUTEX_PRIVATE_FLAG*/
+
+static inline int futex_wait( int *addr, int val, struct timespec *timeout )
+{
+ return syscall( SYS_futex, addr, wait_op, val, timeout, 0, 0 );
+}
+
+static inline int futex_wake( int *addr, int val )
+{
+ return syscall( SYS_futex, addr, wake_op, val, NULL, 0, 0 );
+}
+
+// srwlock->Ptr
+#define SRW_LOCKED 0x80000000
+#define SRW_WRITE_ACTIVE 0x00800000
+#define SRW_READERS_ACTIVE_MASK 0x0000FFFF
+
+void lock_srwlock(PSRWLOCK srwlock) {
+ TRACE("lock (%p %p)\n", srwlock, srwlock->Ptr);
+ DWORD oldval = 0;
+ for (;;) {
+ DWORD lockval = oldval | SRW_LOCKED;
+ DWORD val = (DWORD)interlocked_cmpxchg_ptr(&srwlock->Ptr, (void*)lockval, (void*)oldval);
+ if (val & SRW_LOCKED) {
+ // other thread holding lock
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000;
+ futex_wait((int*)&srwlock->Ptr, val, &ts);
+ continue;
+ }
+ if (val != oldval) {
+ oldval = val & ~SRW_LOCKED;
+ continue;
+ }
+ TRACE("lock->(%p %p)\n", srwlock, srwlock->Ptr);
+ return;
+ }
+}
+
+void unlock_srwlock(PSRWLOCK srwlock) {
+ TRACE("unlock (%p, %p)\n", srwlock, srwlock->Ptr);
+ DWORD oldval = (DWORD)srwlock->Ptr;
+ DWORD unlockval = oldval & ~SRW_LOCKED;
+ interlocked_cmpxchg_ptr(&srwlock->Ptr, (void*)unlockval, (void*)oldval);
+ TRACE("unlock-> (%p, %p)\n", srwlock, srwlock->Ptr);
+ futex_wake((int*)&srwlock->Ptr, 1);
+}
+
+void wait_srwlock(PSRWLOCK srwlock) {
+ TRACE("wait (%p, %p)\n", srwlock, srwlock->Ptr);
+ DWORD val = 0;
+ unlock_srwlock(srwlock);
+ val = (DWORD)interlocked_cmpxchg_ptr(&srwlock->Ptr, (void*)0, (void*)0);
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 100 * 1000 * 1000;
+ futex_wait((int*)&srwlock->Ptr, val, &ts);
+ lock_srwlock(srwlock);
+}
+
+void wake_srwlock(PSRWLOCK srwlock) {
+ TRACE("wake (%p, %p)\n", srwlock, srwlock->Ptr);
+ DWORD val = (DWORD)srwlock->Ptr;
+ futex_wake((int*)&srwlock->Ptr, 32); // TODO(ukai): # of waiting threads?
+}
+
+void srwlock_write_active(PSRWLOCK srwlock, BOOL active) {
+ DWORD val = (DWORD)srwlock->Ptr;
+ if (active) {
+ val |= SRW_WRITE_ACTIVE;
+ } else {
+ val &= ~SRW_WRITE_ACTIVE;
+ }
+ TRACE("srwlock write (%p, %p->%p)\n", srwlock, srwlock->Ptr, val);
+ srwlock->Ptr = (void*)val;
+}
+
+BOOL srwlock_write_locked(PSRWLOCK srwlock) {
+ DWORD val = (DWORD)srwlock->Ptr;
+ return (val & SRW_WRITE_ACTIVE) != 0;
+}
+
+void srwlock_read_active(PSRWLOCK srwlock, BOOL active) {
+ DWORD val = (DWORD)srwlock->Ptr;
+ DWORD readers = val & SRW_READERS_ACTIVE_MASK;
+ val &= ~SRW_READERS_ACTIVE_MASK;
+ if (active) {
+ ++readers;
+ } else {
+ --readers;
+ }
+ val |= (readers & SRW_READERS_ACTIVE_MASK);
+ TRACE("srwlock read (%p, %p->%p)\n", srwlock, srwlock->Ptr, val);
+ srwlock->Ptr = (void*)val;
+}
+
+int srwlock_read_locked(PSRWLOCK srwlock) {
+ DWORD val = (DWORD)srwlock->Ptr;
+ return (val & SRW_READERS_ACTIVE_MASK);
+}
+
+#endif
+
+/***********************************************************************
+ * InitializeSRWLock (KERNEL32.@)
+ */
+VOID WINAPI InitializeSRWLock( PSRWLOCK srwlock )
+{
+ TRACE("(%p)\n", srwlock);
+ srwlock->Ptr = 0;
+ TRACE("(%p, %p) initialized\n", srwlock, srwlock->Ptr);
+}
+
+/***********************************************************************
+ * AcquireSRWLockExclusive (KERNEL32.@)
+ */
+VOID WINAPI AcquireSRWLockExclusive( PSRWLOCK srwlock )
+{
+#ifndef __linux__
+ FIXME( "(%p): stub\n", srwlock );
+#else
+ TRACE( "(%p)\n", srwlock );
+ lock_srwlock(srwlock);
+ for (;;) {
+ if (srwlock_write_locked(srwlock) || srwlock_read_locked(srwlock) > 0) {
+ TRACE( "(%p): wait write\n", srwlock );
+ wait_srwlock(srwlock);
+ continue;
+ }
+ srwlock_write_active(srwlock, 1);
+ break;
+ }
+ unlock_srwlock(srwlock);
+ TRACE( "->(%p): stub\n", srwlock );
+#endif
+}
+
+/***********************************************************************
+ * ReleaseSRWLockExclusive (KERNEL32.@)
+ */
+VOID WINAPI ReleaseSRWLockExclusive( PSRWLOCK srwlock )
+{
+#ifndef __linux__
+ FIXME( "(%p): stub\n", srwlock );
+#else
+ TRACE( "(%p)\n", srwlock );
+ lock_srwlock(srwlock);
+ srwlock_write_active(srwlock, 0);
+ unlock_srwlock(srwlock);
+ wake_srwlock(srwlock);
+ TRACE( "->(%p): stub\n", srwlock );
+#endif
+}
+
+/***********************************************************************
+ * AcquireSRWLockShared (KERNEL32.@)
+ */
+VOID WINAPI AcquireSRWLockShared( PSRWLOCK srwlock )
+{
+#ifndef __linux__
+ FIXME( "(%p): stub\n", srwlock );
+#else
+ TRACE( "(%p)\n", srwlock );
+ lock_srwlock(srwlock);
+ for (;;) {
+ if (srwlock_write_locked(srwlock)) {
+ TRACE( "(%p): wait read\n", srwlock );
+ wait_srwlock(srwlock);
+ continue;
+ }
+ srwlock_read_active(srwlock, 1);
+ break;
+ }
+ unlock_srwlock(srwlock);
+ TRACE( "->(%p): stub\n", srwlock );
+#endif
+}
+
+/***********************************************************************
+ * ReleaseSRWLockShared (KERNEL32.@)
+ */
+VOID WINAPI ReleaseSRWLockShared( PSRWLOCK srwlock )
+{
+#ifndef __linux__
+ FIXME( "(%p): stub\n", srwlock );
+#else
+ TRACE( "(%p)\n", srwlock );
+ lock_srwlock(srwlock);
+ srwlock_read_active(srwlock, 0);
+ unlock_srwlock(srwlock);
+ wake_srwlock(srwlock);
+ TRACE( "->(%p): stub\n", srwlock );
+#endif
+}
+
diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c
index 839c7ca..fe16738 100644
--- a/dlls/ntdll/critsection.c
+++ b/dlls/ntdll/critsection.c
@@ -510,6 +510,18 @@
return ret;
}
+static BOOL IsAllZero(const void* begin, size_t size)
+{
+ const char* m = begin;
+ int i;
+
+ for (i = 0; i < size; ++i) {
+ if (m[i] != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
/***********************************************************************
* RtlEnterCriticalSection (NTDLL.@)
@@ -530,6 +542,25 @@
*/
NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
{
+ // VS2013 cl.exe calls this with zero cleared crit.
+ // As far as we examined, this does not happen in real Windows.
+ // So maybe there is a wine bug that causes this. However, I have no idea
+ // about what causes this.
+ // Let's allow it to enter critical section for workaround.
+ if (IsAllZero(crit, sizeof(RTL_CRITICAL_SECTION))) {
+ if (interlocked_cmpxchg(&crit->SpinCount, 4000, 0) == 0) {
+ // OK. SpinCount was 0, and now 4000.
+ crit->LockCount = -1;
+ }
+
+ // When interlocked_cmpxchg was failed, someone changed SpinCount
+ // after IsAllZero(). With this workaround, someone will change or
+ // has changed crit->LockCount to -1. Leaving LockCount as is so that
+ // this thread (or the other thread) will wait for lock release.
+ // In usual case, cl.exe will return critical section with zero-cleared
+ // crit only once. So this shouldn't happen, though.
+ }
+
if (crit->SpinCount)
{
ULONG count;
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 04a5b75..c7a0b7b 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -1376,7 +1376,7 @@
union file_directory_info *info;
int i, long_len, short_len, total_len;
struct stat st;
- WCHAR long_nameW[MAX_DIR_ENTRY_LEN];
+ WCHAR long_nameW[MAX_DIR_ENTRY_LEN] = { (WCHAR)0 };
WCHAR short_nameW[12];
WCHAR *filename;
UNICODE_STRING str;
diff --git a/include/winnls.h b/include/winnls.h
index 9ed4344..9601665 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -568,6 +568,10 @@
#define LGRPID_GEORGIAN 0x10
#define LGRPID_ARMENIAN 0x11
+// WINVER >= 0x0600
+#define MUI_LANGUAGE_ID 0x04
+#define MUI_LANGUAGE_NAME 0x08
+
/* IDN defines. */
#define IDN_ALLOW_UNASSIGNED 0x1
#define IDN_USE_STD3_ASCII_RULES 0x2
diff --git a/loader/preloader.c b/loader/preloader.c
index f38e17a..ebf512a 100644
--- a/loader/preloader.c
+++ b/loader/preloader.c
@@ -1160,8 +1160,8 @@
{
long i, *pargc;
char **argv, **p;
- char *interp, *reserve = NULL;
- struct wld_auxv new_av[12], delete_av[3], *av;
+ char *interp = NULL, *reserve = NULL;
+ ElfW(auxv_t) new_av[12], delete_av[3], *av;
struct wld_link_map main_binary_map, ld_so_map;
struct wine_preload_info **wine_main_preload_info;
@@ -1176,7 +1176,9 @@
while (*p)
{
static const char res[] = "WINEPRELOADRESERVE=";
+ static const char elfld[] = "WINEELFLOADER=";
if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
+ if (!wld_strncmp( *p, elfld, sizeof(elfld)-1 )) interp = *p + sizeof(elfld) - 1;
p++;
}
@@ -1224,7 +1226,8 @@
map_so_lib( argv[1], &main_binary_map );
/* load the ELF interpreter */
- interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
+ if (!interp)
+ interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
map_so_lib( interp, &ld_so_map );
/* store pointer to the preload info into the appropriate main binary variable */
diff --git a/server/main.c b/server/main.c
index 7aed338..2ec98b9 100644
--- a/server/main.c
+++ b/server/main.c
@@ -41,7 +41,7 @@
/* command-line options */
int debug_level = 0;
int foreground = 0;
-timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
+timeout_t master_socket_timeout = 0;
const char *server_argv0;
/* parse-line args */