wine-1.7.28 updated.
This commit is contained in:
parent
1572172a46
commit
c53c515006
|
@ -0,0 +1,629 @@
|
||||||
|
From 9e081cd4a04e3326d4927aa082695f15432590e2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
|
||||||
|
Date: Thu, 14 Aug 2014 11:49:20 +0200
|
||||||
|
Subject: [PATCH] TESTING -- override pthreads to fix gstreamer v4
|
||||||
|
|
||||||
|
I believe the code is ready and will work properly now in all cases.
|
||||||
|
but please test before cherry picking this patch, and report
|
||||||
|
success or failure to me please.
|
||||||
|
|
||||||
|
Changes since v1:
|
||||||
|
- Call pthread_yield to make sure that we link against libpthread.
|
||||||
|
This fixes the build on saucy.
|
||||||
|
Changes since v2:
|
||||||
|
- Set thread_data->detached before creating the thread to prevent
|
||||||
|
a race condition.
|
||||||
|
Changes since v3:
|
||||||
|
- Set thread_data->detached CORRECTLY. Fix a small race between
|
||||||
|
thread creation and pthread_detach.
|
||||||
|
---
|
||||||
|
dlls/ntdll/ntdll_misc.h | 3 +
|
||||||
|
dlls/ntdll/thread.c | 307 +++++++++++++++++++++++++++++++++++++--
|
||||||
|
dlls/winegstreamer/glibthread.c | 13 ++
|
||||||
|
libs/wine/loader.c | 7 +
|
||||||
|
libs/wine/wine.map | 6 +
|
||||||
|
loader/Makefile.in | 2 +-
|
||||||
|
loader/main.c | 41 +++++
|
||||||
|
7 files changed, 362 insertions(+), 17 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
|
||||||
|
index 4370084..1af819b 100644
|
||||||
|
--- a/dlls/ntdll/ntdll_misc.h
|
||||||
|
+++ b/dlls/ntdll/ntdll_misc.h
|
||||||
|
@@ -28,6 +28,7 @@
|
||||||
|
#include "winnt.h"
|
||||||
|
#include "winternl.h"
|
||||||
|
#include "wine/server.h"
|
||||||
|
+#include "wine/list.h"
|
||||||
|
|
||||||
|
#define MAX_NT_PATH_LENGTH 277
|
||||||
|
|
||||||
|
@@ -235,6 +236,8 @@ struct ntdll_thread_data
|
||||||
|
WINE_VM86_TEB_INFO vm86; /* 1fc vm86 private data */
|
||||||
|
void *exit_frame; /* 204 exit frame pointer */
|
||||||
|
#endif
|
||||||
|
+ struct list entry;
|
||||||
|
+ BOOL detached;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct ntdll_thread_data *ntdll_get_thread_data(void)
|
||||||
|
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
|
||||||
|
index c8461b0..8d5470e 100644
|
||||||
|
--- a/dlls/ntdll/thread.c
|
||||||
|
+++ b/dlls/ntdll/thread.c
|
||||||
|
@@ -33,6 +33,7 @@
|
||||||
|
#ifdef HAVE_SYS_SYSCALL_H
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#endif
|
||||||
|
+#include <errno.h>
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
#include "ntstatus.h"
|
||||||
|
@@ -58,6 +59,7 @@ struct startup_info
|
||||||
|
TEB *teb;
|
||||||
|
PRTL_THREAD_START_ROUTINE entry_point;
|
||||||
|
void *entry_arg;
|
||||||
|
+ BOOL native_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
static PEB *peb;
|
||||||
|
@@ -202,6 +204,78 @@ static ULONG get_dyld_image_info_addr(void)
|
||||||
|
}
|
||||||
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
|
+#ifdef __linux__
|
||||||
|
+extern typeof(pthread_create) *__glob_pthread_create, *call_pthread_create;
|
||||||
|
+extern typeof(pthread_join) *__glob_pthread_join, *call_pthread_join;
|
||||||
|
+extern typeof(pthread_detach) *__glob_pthread_detach, *call_pthread_detach;
|
||||||
|
+
|
||||||
|
+static typeof(pthread_create) __hook_pthread_create;
|
||||||
|
+static typeof(pthread_join) __hook_pthread_join;
|
||||||
|
+static typeof(pthread_detach) __hook_pthread_detach;
|
||||||
|
+
|
||||||
|
+static pthread_mutex_t thread_lock;
|
||||||
|
+
|
||||||
|
+static void thread_wrap_init(void)
|
||||||
|
+{
|
||||||
|
+ pthread_mutexattr_t attr;
|
||||||
|
+ pthread_mutexattr_init(&attr);
|
||||||
|
+ pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
|
||||||
|
+ pthread_mutex_init(&thread_lock, &attr);
|
||||||
|
+ pthread_mutexattr_destroy(&attr);
|
||||||
|
+
|
||||||
|
+ call_pthread_create = __hook_pthread_create;
|
||||||
|
+ call_pthread_join = __hook_pthread_join;
|
||||||
|
+ call_pthread_detach = __hook_pthread_detach;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static TEB *dead_teb;
|
||||||
|
+static struct list active_list = LIST_INIT(active_list);
|
||||||
|
+
|
||||||
|
+static void take_thread_lock(void)
|
||||||
|
+{
|
||||||
|
+ int ret = pthread_mutex_lock(&thread_lock);
|
||||||
|
+ if (ret == EOWNERDEAD)
|
||||||
|
+ pthread_mutex_consistent(&thread_lock);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void detach_thread_unlock(TEB *own_teb)
|
||||||
|
+{
|
||||||
|
+ struct ntdll_thread_data *thread_data;
|
||||||
|
+ TEB *teb = dead_teb;
|
||||||
|
+
|
||||||
|
+ dead_teb = own_teb;
|
||||||
|
+
|
||||||
|
+ pthread_mutex_unlock(&thread_lock);
|
||||||
|
+ if (!teb)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;
|
||||||
|
+ __glob_pthread_join(thread_data->pthread_id, NULL);
|
||||||
|
+ signal_free_thread(teb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void reap_thread(TEB *teb)
|
||||||
|
+{
|
||||||
|
+ struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;
|
||||||
|
+ take_thread_lock();
|
||||||
|
+ if (thread_data->detached)
|
||||||
|
+ detach_thread_unlock(teb);
|
||||||
|
+ else {
|
||||||
|
+ /*
|
||||||
|
+ * Do not unlock, wait until the thread is thoroughly dead.
|
||||||
|
+ * This prevents a race condition where detach is called
|
||||||
|
+ * after the thread has not finished dying yet.
|
||||||
|
+ */
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else
|
||||||
|
+#define __glob_pthread_create pthread_create
|
||||||
|
+#define __glob_pthread_join pthread_join
|
||||||
|
+#define __glob_pthread_detach pthread_detach
|
||||||
|
+#define thread_wrap_init()
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
/***********************************************************************
|
||||||
|
* thread_init
|
||||||
|
*
|
||||||
|
@@ -220,6 +294,7 @@ HANDLE thread_init(void)
|
||||||
|
struct ntdll_thread_data *thread_data;
|
||||||
|
static struct debug_info debug_info; /* debug info for initial thread */
|
||||||
|
|
||||||
|
+ thread_wrap_init();
|
||||||
|
virtual_init();
|
||||||
|
|
||||||
|
/* reserve space for shared user data */
|
||||||
|
@@ -349,14 +424,12 @@ void terminate_thread( int status )
|
||||||
|
pthread_exit( UIntToPtr(status) );
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
-/***********************************************************************
|
||||||
|
- * exit_thread
|
||||||
|
- */
|
||||||
|
-void exit_thread( int status )
|
||||||
|
+static void exit_thread_common( int status )
|
||||||
|
{
|
||||||
|
+#ifndef __linux__
|
||||||
|
static void *prev_teb;
|
||||||
|
TEB *teb;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
if (status) /* send the exit code to the server (0 is already the default) */
|
||||||
|
{
|
||||||
|
@@ -380,24 +453,177 @@ void exit_thread( int status )
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
|
||||||
|
|
||||||
|
+#ifndef __linux__
|
||||||
|
if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
|
||||||
|
{
|
||||||
|
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;
|
||||||
|
|
||||||
|
if (thread_data->pthread_id)
|
||||||
|
{
|
||||||
|
- pthread_join( thread_data->pthread_id, NULL );
|
||||||
|
+ __glob_pthread_join( thread_data->pthread_id, NULL );
|
||||||
|
signal_free_thread( teb );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+#else
|
||||||
|
+ reap_thread(NtCurrentTeb());
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
close( ntdll_get_thread_data()->wait_fd[0] );
|
||||||
|
close( ntdll_get_thread_data()->wait_fd[1] );
|
||||||
|
close( ntdll_get_thread_data()->reply_fd );
|
||||||
|
close( ntdll_get_thread_data()->request_fd );
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void exit_thread( int status )
|
||||||
|
+{
|
||||||
|
+ exit_thread_common(status);
|
||||||
|
pthread_exit( UIntToPtr(status) );
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef __linux__
|
||||||
|
+
|
||||||
|
+struct unix_arg {
|
||||||
|
+ void *(*start)(void *);
|
||||||
|
+ void *arg;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/* dummy used for comparison */
|
||||||
|
+static DWORD native_unix_start;
|
||||||
|
+
|
||||||
|
+static void call_native_cleanup(void *arg)
|
||||||
|
+{
|
||||||
|
+ exit_thread_common(0);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+__hook_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
+ void *(*start_routine) (void *), void *parm)
|
||||||
|
+{
|
||||||
|
+ NTSTATUS ret;
|
||||||
|
+ pthread_t tid;
|
||||||
|
+ size_t stack = 8 * 1024 * 1024;
|
||||||
|
+ struct unix_arg arg;
|
||||||
|
+ arg.start = start_routine;
|
||||||
|
+ arg.arg = parm;
|
||||||
|
+
|
||||||
|
+ if (!thread)
|
||||||
|
+ thread = &tid;
|
||||||
|
+
|
||||||
|
+ TRACE("Overriding thread creation!\n");
|
||||||
|
+ if (attr) {
|
||||||
|
+ static int once;
|
||||||
|
+ if (!once++)
|
||||||
|
+ FIXME("most thread attributes ignored!\n");
|
||||||
|
+ else
|
||||||
|
+ WARN("most thread attributes ignored!\n");
|
||||||
|
+
|
||||||
|
+ pthread_attr_getstacksize(attr, &stack);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE, NULL, stack, 0, (void*)&native_unix_start, &arg, NULL, (void*)thread );
|
||||||
|
+ if (ret != STATUS_SUCCESS)
|
||||||
|
+ FIXME("ret: %08x\n", ret);
|
||||||
|
+ switch (ret) {
|
||||||
|
+ case STATUS_SUCCESS:
|
||||||
|
+ TRACE("created thread %lx for %p/%p\n", *thread, start_routine, parm);
|
||||||
|
+ return 0;
|
||||||
|
+ case STATUS_NO_MEMORY:
|
||||||
|
+ return ENOMEM;
|
||||||
|
+ case STATUS_TOO_MANY_OPENED_FILES:
|
||||||
|
+ return EMFILE;
|
||||||
|
+ default:
|
||||||
|
+ ERR("Unhandled ntstatus %08x\n", ret);
|
||||||
|
+ return ENOMEM;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __hook_pthread_detach(pthread_t thread)
|
||||||
|
+{
|
||||||
|
+ struct ntdll_thread_data *thread_data;
|
||||||
|
+ TEB *teb = NULL;
|
||||||
|
+
|
||||||
|
+ if (pthread_equal(thread, pthread_self())) {
|
||||||
|
+ TRACE("Detached self: %lx\n", pthread_self());
|
||||||
|
+ ntdll_get_thread_data()->detached = 1;
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ take_thread_lock();
|
||||||
|
+ LIST_FOR_EACH_ENTRY(thread_data, &active_list, typeof(*thread_data), entry) {
|
||||||
|
+ if (pthread_equal(thread_data->pthread_id, thread)) {
|
||||||
|
+ teb = CONTAINING_RECORD(thread_data, typeof(*teb), SpareBytes1);
|
||||||
|
+
|
||||||
|
+ list_remove(&thread_data->entry);
|
||||||
|
+ if (!pthread_tryjoin_np(thread, NULL)) {
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+ TRACE("Thread %lx was dead, cleaning up\n", thread);
|
||||||
|
+ signal_free_thread(teb);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ thread_data->detached = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+ if (!teb)
|
||||||
|
+ TRACE("Could not find thread %lx to detach\n", thread);
|
||||||
|
+ else
|
||||||
|
+ TRACE("Changed thread %lx to detached\n", thread);
|
||||||
|
+ return teb ? 0 : ESRCH;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __hook_pthread_join(pthread_t thread, void **retval)
|
||||||
|
+{
|
||||||
|
+ struct ntdll_thread_data *thread_data, *t2;
|
||||||
|
+ int ret = ESRCH;
|
||||||
|
+
|
||||||
|
+ if (pthread_equal(thread, pthread_self()))
|
||||||
|
+ return EDEADLK;
|
||||||
|
+
|
||||||
|
+ take_thread_lock();
|
||||||
|
+ LIST_FOR_EACH_ENTRY(thread_data, &active_list, typeof(*thread_data), entry) {
|
||||||
|
+ TEB *teb = CONTAINING_RECORD(thread_data, typeof(*teb), SpareBytes1);
|
||||||
|
+
|
||||||
|
+ if (pthread_equal(thread, thread_data->pthread_id)) {
|
||||||
|
+
|
||||||
|
+ ret = pthread_tryjoin_np(thread, retval);
|
||||||
|
+ if (!ret) {
|
||||||
|
+ TRACE("Thread %lx was dead fastpath, cleaning up\n", thread);
|
||||||
|
+ goto free;
|
||||||
|
+ }
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+
|
||||||
|
+ ret = __glob_pthread_join(thread, retval);
|
||||||
|
+ if (ret) {
|
||||||
|
+ TRACE("Thread %lx join failed with %i, ignoring\n", thread, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ take_thread_lock();
|
||||||
|
+ /* Check if someone else freed the thread yet */
|
||||||
|
+ LIST_FOR_EACH_ENTRY(t2, &active_list, typeof(*thread_data), entry)
|
||||||
|
+ if (t2 == thread_data) {
|
||||||
|
+ TRACE("Cleaning up after successful join\n");
|
||||||
|
+ goto free;
|
||||||
|
+ }
|
||||||
|
+ TRACE("No clean up after successful join, multiple pthread_join's?\n");
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+free:
|
||||||
|
+ list_remove(&thread_data->entry);
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+ signal_free_thread(teb);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+ if (ret)
|
||||||
|
+ TRACE("failed with %i\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* start_thread
|
||||||
|
@@ -426,9 +652,19 @@ static void start_thread( struct startup_info *info )
|
||||||
|
if (TRACE_ON(relay))
|
||||||
|
DPRINTF( "%04x:Starting thread proc %p (arg=%p)\n", GetCurrentThreadId(), func, arg );
|
||||||
|
|
||||||
|
- call_thread_entry_point( (LPTHREAD_START_ROUTINE)func, arg );
|
||||||
|
-}
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ if (info->native_thread) {
|
||||||
|
+ void *(*start)(void*) = (void*)func;
|
||||||
|
|
||||||
|
+ FIXME("Started native thread %08x\n", GetCurrentThreadId());
|
||||||
|
+ pthread_cleanup_push(call_native_cleanup, NULL);
|
||||||
|
+ pthread_exit(start(arg));
|
||||||
|
+ pthread_cleanup_pop(1);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+ call_thread_entry_point( (LPTHREAD_START_ROUTINE)func, arg );
|
||||||
|
+}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* RtlCreateUserThread (NTDLL.@)
|
||||||
|
@@ -440,14 +676,13 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
|
HANDLE *handle_ptr, CLIENT_ID *id )
|
||||||
|
{
|
||||||
|
sigset_t sigset;
|
||||||
|
- pthread_t pthread_id;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
struct ntdll_thread_data *thread_data;
|
||||||
|
struct startup_info *info = NULL;
|
||||||
|
HANDLE handle = 0, actctx = 0;
|
||||||
|
TEB *teb = NULL;
|
||||||
|
DWORD tid = 0;
|
||||||
|
- int request_pipe[2];
|
||||||
|
+ int request_pipe[2], ret;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
if (process != NtCurrentProcess())
|
||||||
|
@@ -472,10 +707,14 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
|
if (handle_ptr) *handle_ptr = wine_server_ptr_handle( result.create_thread.handle );
|
||||||
|
else NtClose( wine_server_ptr_handle( result.create_thread.handle ));
|
||||||
|
}
|
||||||
|
+ TRACE("CreateThread for other process returns %08x\n", result.create_thread.status);
|
||||||
|
return result.create_thread.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (server_pipe( request_pipe ) == -1) return STATUS_TOO_MANY_OPENED_FILES;
|
||||||
|
+ if (server_pipe( request_pipe ) == -1) {
|
||||||
|
+ TRACE("CreateThread cannot create request pipe: %m\n");
|
||||||
|
+ return STATUS_TOO_MANY_OPENED_FILES;
|
||||||
|
+ }
|
||||||
|
wine_server_send_fd( request_pipe[0] );
|
||||||
|
|
||||||
|
SERVER_START_REQ( new_thread )
|
||||||
|
@@ -496,12 +735,16 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
close( request_pipe[1] );
|
||||||
|
+ TRACE("CreateThread server request failed with %08x\n", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset );
|
||||||
|
|
||||||
|
- if ((status = signal_alloc_thread( &teb ))) goto error;
|
||||||
|
+ if ((status = signal_alloc_thread( &teb ))) {
|
||||||
|
+ TRACE("CreateThread signal thread allocation failed with %08x\n", status);
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
teb->Peb = NtCurrentTeb()->Peb;
|
||||||
|
teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
|
||||||
|
@@ -524,32 +767,64 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
||||||
|
|
||||||
|
info = (struct startup_info *)(teb + 1);
|
||||||
|
info->teb = teb;
|
||||||
|
- info->entry_point = start;
|
||||||
|
- info->entry_arg = param;
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ info->native_thread = (void*)start == (void*)&native_unix_start;
|
||||||
|
+ if (info->native_thread) {
|
||||||
|
+ struct unix_arg *arg = param;
|
||||||
|
+ info->entry_point = (void*)arg->start;
|
||||||
|
+ info->entry_arg = arg->arg;
|
||||||
|
+ } else
|
||||||
|
+#endif
|
||||||
|
+ {
|
||||||
|
+ info->entry_point = start;
|
||||||
|
+ info->entry_arg = param;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
thread_data = (struct ntdll_thread_data *)teb->SpareBytes1;
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ thread_data->detached = !info->native_thread;
|
||||||
|
+#endif
|
||||||
|
thread_data->request_fd = request_pipe[1];
|
||||||
|
thread_data->reply_fd = -1;
|
||||||
|
thread_data->wait_fd[0] = -1;
|
||||||
|
thread_data->wait_fd[1] = -1;
|
||||||
|
+ thread_data->entry.next = NULL;
|
||||||
|
|
||||||
|
- if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error;
|
||||||
|
+ if ((status = virtual_alloc_thread_stack( teb, stack_reserve ?: (8 << 20), stack_commit ?: (1 << 20) ))) {
|
||||||
|
+ TRACE("Allocating virtual stack for %p (%li/%li) failed with %08x\n", start, stack_reserve, stack_commit, status);
|
||||||
|
+ goto error;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
pthread_attr_init( &attr );
|
||||||
|
pthread_attr_setstack( &attr, teb->DeallocationStack,
|
||||||
|
(char *)teb->Tib.StackBase - (char *)teb->DeallocationStack );
|
||||||
|
pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */
|
||||||
|
interlocked_xchg_add( &nb_threads, 1 );
|
||||||
|
- if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info ))
|
||||||
|
+
|
||||||
|
+ take_thread_lock();
|
||||||
|
+ ret = __glob_pthread_create( &thread_data->pthread_id, &attr, (void * (*)(void *))start_thread, info );
|
||||||
|
+ if (ret)
|
||||||
|
{
|
||||||
|
+ TRACE("pthread create failed with %i/%m\n", ret);
|
||||||
|
interlocked_xchg_add( &nb_threads, -1 );
|
||||||
|
pthread_attr_destroy( &attr );
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
+ if (!thread_data->detached)
|
||||||
|
+ list_add_tail(&active_list, &thread_data->entry);
|
||||||
|
+ detach_thread_unlock(NULL);
|
||||||
|
+
|
||||||
|
pthread_attr_destroy( &attr );
|
||||||
|
pthread_sigmask( SIG_SETMASK, &sigset, NULL );
|
||||||
|
|
||||||
|
+ TRACE("Created thread succesfully, win handle: %04x, pthread: %lx\n", tid, thread_data->pthread_id);
|
||||||
|
+
|
||||||
|
+#ifdef __linux__
|
||||||
|
+ if ((void*)start == (void*)&native_unix_start && id)
|
||||||
|
+ *(pthread_t*)id = thread_data->pthread_id;
|
||||||
|
+ else
|
||||||
|
+#endif
|
||||||
|
if (id) id->UniqueThread = ULongToHandle(tid);
|
||||||
|
if (handle_ptr) *handle_ptr = handle;
|
||||||
|
else NtClose( handle );
|
||||||
|
diff --git a/dlls/winegstreamer/glibthread.c b/dlls/winegstreamer/glibthread.c
|
||||||
|
index 0d829a0..46e22f4 100644
|
||||||
|
--- a/dlls/winegstreamer/glibthread.c
|
||||||
|
+++ b/dlls/winegstreamer/glibthread.c
|
||||||
|
@@ -43,6 +43,7 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
+#if 0
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "winnls.h"
|
||||||
|
@@ -388,3 +389,15 @@ void g_thread_impl_init (void)
|
||||||
|
g_thread_self_tls = TlsAlloc ();
|
||||||
|
g_thread_init(&g_thread_functions_for_glib_use_default);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+void g_thread_impl_init (void)
|
||||||
|
+{
|
||||||
|
+ static gboolean beenhere = FALSE;
|
||||||
|
+
|
||||||
|
+ if (!beenhere++)
|
||||||
|
+ g_thread_init(NULL);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/libs/wine/loader.c b/libs/wine/loader.c
|
||||||
|
index 7261522..a8c31b9 100644
|
||||||
|
--- a/libs/wine/loader.c
|
||||||
|
+++ b/libs/wine/loader.c
|
||||||
|
@@ -73,6 +73,13 @@ char **__wine_main_argv = NULL;
|
||||||
|
WCHAR **__wine_main_wargv = NULL;
|
||||||
|
char **__wine_main_environ = NULL;
|
||||||
|
|
||||||
|
+#ifdef __linux__
|
||||||
|
+#include <pthread.h>
|
||||||
|
+typeof(pthread_create) *call_pthread_create, *__glob_pthread_create;
|
||||||
|
+typeof(pthread_join) *call_pthread_join, *__glob_pthread_join;
|
||||||
|
+typeof(pthread_detach) *call_pthread_detach, *__glob_pthread_detach;
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
struct dll_path_context
|
||||||
|
{
|
||||||
|
unsigned int index; /* current index in the dll path list */
|
||||||
|
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
|
||||||
|
index 2159fac..fb3b951 100644
|
||||||
|
--- a/libs/wine/wine.map
|
||||||
|
+++ b/libs/wine/wine.map
|
||||||
|
@@ -117,6 +117,12 @@ WINE_1.0
|
||||||
|
wine_utf8_mbstowcs;
|
||||||
|
wine_utf8_wcstombs;
|
||||||
|
wine_wctype_table;
|
||||||
|
+ __glob_pthread_create;
|
||||||
|
+ call_pthread_create;
|
||||||
|
+ __glob_pthread_join;
|
||||||
|
+ call_pthread_join;
|
||||||
|
+ __glob_pthread_detach;
|
||||||
|
+ call_pthread_detach;
|
||||||
|
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
|
diff --git a/loader/Makefile.in b/loader/Makefile.in
|
||||||
|
index 95e4798..a18dd02 100644
|
||||||
|
--- a/loader/Makefile.in
|
||||||
|
+++ b/loader/Makefile.in
|
||||||
|
@@ -1,4 +1,4 @@
|
||||||
|
-EXTRALIBS = $(PTHREAD_LIBS)
|
||||||
|
+EXTRALIBS = $(PTHREAD_LIBS) $(DL_LIBS)
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
main.c \
|
||||||
|
diff --git a/loader/main.c b/loader/main.c
|
||||||
|
index ac67290..76609e1 100644
|
||||||
|
--- a/loader/main.c
|
||||||
|
+++ b/loader/main.c
|
||||||
|
@@ -202,6 +202,45 @@ static int pre_exec(void)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+#ifdef __linux__
|
||||||
|
+
|
||||||
|
+extern typeof(pthread_create) *call_pthread_create, *__glob_pthread_create;
|
||||||
|
+extern typeof(pthread_detach) *call_pthread_detach, *__glob_pthread_detach;
|
||||||
|
+extern typeof(pthread_join) *call_pthread_join, *__glob_pthread_join;
|
||||||
|
+
|
||||||
|
+int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
+ void *(*start_routine) (void *), void *arg)
|
||||||
|
+{
|
||||||
|
+ return call_pthread_create(thread, attr, start_routine, arg);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int pthread_detach(pthread_t thread)
|
||||||
|
+{
|
||||||
|
+ return call_pthread_detach(thread);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int pthread_join(pthread_t thread, void **retval)
|
||||||
|
+{
|
||||||
|
+ return call_pthread_join(thread, retval);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void init_thread_hook(void) {
|
||||||
|
+ call_pthread_create = __glob_pthread_create = dlvsym(RTLD_NEXT, "pthread_create", "GLIBC_2.2.5");
|
||||||
|
+ if (!__glob_pthread_create)
|
||||||
|
+ call_pthread_create = __glob_pthread_create = dlvsym(RTLD_NEXT, "pthread_create", "GLIBC_2.1");
|
||||||
|
+
|
||||||
|
+ call_pthread_detach = __glob_pthread_detach = dlsym(RTLD_NEXT, "pthread_detach");
|
||||||
|
+ call_pthread_join = __glob_pthread_join = dlsym(RTLD_NEXT, "pthread_join");
|
||||||
|
+
|
||||||
|
+ /* Call a function from libpthread to ensure being linked against it */
|
||||||
|
+ pthread_yield();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#else
|
||||||
|
+
|
||||||
|
+#define init_thread_hook()
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* main
|
||||||
|
@@ -211,6 +250,8 @@ int main( int argc, char *argv[] )
|
||||||
|
char error[1024];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
+ init_thread_hook();
|
||||||
|
+
|
||||||
|
if (!getenv( "WINELOADERNOEXEC" )) /* first time around */
|
||||||
|
{
|
||||||
|
static char noexec[] = "WINELOADERNOEXEC=1";
|
||||||
|
--
|
||||||
|
1.7.6.6.GIT
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright 1999-2014 Gentoo Foundation
|
# Copyright 1999-2014 Gentoo Foundation
|
||||||
# Distributed under the terms of the GNU General Public License v2
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
# $Header: /var/cvsroot/gentoo-x86/app-emulation/wine/wine-1.7.28.ebuild,v 1.1 2014/06/29 00:42:47 tetromino Exp $
|
# $Header: /var/cvsroot/gentoo-x86/app-emulation/wine/wine-1.7.28.ebuild,v 1.1 2014/10/05 13:17:36 ryao Exp $
|
||||||
|
|
||||||
EAPI="5"
|
EAPI="5"
|
||||||
|
|
||||||
|
@ -24,9 +24,7 @@ fi
|
||||||
|
|
||||||
GV="2.24"
|
GV="2.24"
|
||||||
MV="4.5.2"
|
MV="4.5.2"
|
||||||
PULSE_PATCHES="winepulse-patches-1.7.21"
|
COMPHOLIO_P="wine-compholio-${PV}"
|
||||||
COMPHOLIOV="1.7.25"
|
|
||||||
COMPHOLIO_PATCHES="wine-compholio-daily-${COMPHOLIOV}"
|
|
||||||
WINE_GENTOO="wine-gentoo-2013.06.24"
|
WINE_GENTOO="wine-gentoo-2013.06.24"
|
||||||
DESCRIPTION="Free implementation of Windows(tm) on Unix"
|
DESCRIPTION="Free implementation of Windows(tm) on Unix"
|
||||||
HOMEPAGE="http://www.winehq.org/"
|
HOMEPAGE="http://www.winehq.org/"
|
||||||
|
@ -36,8 +34,8 @@ SRC_URI="${SRC_URI}
|
||||||
abi_x86_64? ( mirror://sourceforge/${PN}/Wine%20Gecko/${GV}/wine_gecko-${GV}-x86_64.msi )
|
abi_x86_64? ( mirror://sourceforge/${PN}/Wine%20Gecko/${GV}/wine_gecko-${GV}-x86_64.msi )
|
||||||
)
|
)
|
||||||
mono? ( mirror://sourceforge/${PN}/Wine%20Mono/${MV}/wine-mono-${MV}.msi )
|
mono? ( mirror://sourceforge/${PN}/Wine%20Mono/${MV}/wine-mono-${MV}.msi )
|
||||||
pipelight? ( https://github.com/compholio/wine-compholio-daily/archive/v${COMPHOLIOV}.tar.gz -> ${COMPHOLIO_PATCHES}.tar.gz )
|
pipelight? ( https://github.com/compholio/wine-compholio-daily/archive/v${PV}.tar.gz -> ${COMPHOLIO_P}.tar.gz )
|
||||||
pulseaudio? ( http://dev.gentoo.org/~tetromino/distfiles/${PN}/${PULSE_PATCHES}.tar.bz2 )
|
pulseaudio? ( https://github.com/compholio/wine-compholio-daily/archive/v${PV}.tar.gz -> ${COMPHOLIO_P}.tar.gz )
|
||||||
http://dev.gentoo.org/~tetromino/distfiles/${PN}/${WINE_GENTOO}.tar.bz2"
|
http://dev.gentoo.org/~tetromino/distfiles/${PN}/${WINE_GENTOO}.tar.bz2"
|
||||||
|
|
||||||
LICENSE="LGPL-2.1"
|
LICENSE="LGPL-2.1"
|
||||||
|
@ -46,7 +44,6 @@ IUSE="+abi_x86_32 +abi_x86_64 +alsa capi cups custom-cflags dos elibc_glibc +fon
|
||||||
REQUIRED_USE="|| ( abi_x86_32 abi_x86_64 )
|
REQUIRED_USE="|| ( abi_x86_32 abi_x86_64 )
|
||||||
test? ( abi_x86_32 )
|
test? ( abi_x86_32 )
|
||||||
elibc_glibc? ( threads )
|
elibc_glibc? ( threads )
|
||||||
gstreamer? ( pulseaudio )
|
|
||||||
mono? ( abi_x86_32 )
|
mono? ( abi_x86_32 )
|
||||||
osmesa? ( opengl )" #286560
|
osmesa? ( opengl )" #286560
|
||||||
# winepulse patches needed for gstreamer due to http://bugs.winehq.org/show_bug.cgi?id=30557
|
# winepulse patches needed for gstreamer due to http://bugs.winehq.org/show_bug.cgi?id=30557
|
||||||
|
@ -295,14 +292,8 @@ src_unpack() {
|
||||||
unpack ${MY_P}.tar.bz2
|
unpack ${MY_P}.tar.bz2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
use pulseaudio && unpack "${PULSE_PATCHES}.tar.bz2"
|
use pipelight || use pulseaudio && unpack "${COMPHOLIO_P}.tar.gz"
|
||||||
if use pipelight; then
|
|
||||||
unpack "${COMPHOLIO_PATCHES}.tar.gz"
|
|
||||||
# we use a separate pulseaudio patchset
|
|
||||||
rm -r "${COMPHOLIO_PATCHES}/patches/06-winepulse" || die
|
|
||||||
# ... and need special tools for binary patches
|
|
||||||
mv "${COMPHOLIO_PATCHES}/patches/10-Missing_Fonts" "${T}" || die
|
|
||||||
fi
|
|
||||||
unpack "${WINE_GENTOO}.tar.bz2"
|
unpack "${WINE_GENTOO}.tar.bz2"
|
||||||
|
|
||||||
l10n_find_plocales_changes "${S}/po" "" ".po"
|
l10n_find_plocales_changes "${S}/po" "" ".po"
|
||||||
|
@ -317,31 +308,38 @@ src_prepare() {
|
||||||
"${FILESDIR}"/${PN}-1.7.12-osmesa-check.patch #429386
|
"${FILESDIR}"/${PN}-1.7.12-osmesa-check.patch #429386
|
||||||
"${FILESDIR}"/${PN}-1.6-memset-O3.patch #480508
|
"${FILESDIR}"/${PN}-1.6-memset-O3.patch #480508
|
||||||
)
|
)
|
||||||
use pulseaudio && PATCHES+=(
|
local COMPHOLIO_MAKE_ARGS="-W fonts-Missing_Fonts.ok"
|
||||||
"../${PULSE_PATCHES}"/*.patch #421365
|
|
||||||
)
|
use pulseaudio || COMPHOLIO_MAKE_ARGS="${COMPHOLIO_MAKE_ARGS} -W winepulse-PulseAudio_Support.ok"
|
||||||
if use gstreamer; then
|
if use gstreamer; then
|
||||||
# See http://bugs.winehq.org/show_bug.cgi?id=30557
|
# See http://bugs.winehq.org/show_bug.cgi?id=30557
|
||||||
ewarn "Applying experimental patch to fix GStreamer support. Note that"
|
ewarn "Applying experimental patch to fix GStreamer support. Note that"
|
||||||
ewarn "this patch has been reported to cause crashes in certain games."
|
ewarn "this patch has been reported to cause crashes in certain games."
|
||||||
|
|
||||||
PATCHES+=( "../${PULSE_PATCHES}"/gstreamer/*.patch )
|
PATCHES+=( "${FILESDIR}/${PN}-1.7.28-gstreamer-v4.patch" )
|
||||||
fi
|
fi
|
||||||
if use pipelight; then
|
if use pipelight; then
|
||||||
ewarn "Applying the unofficial Compholio patchset for Pipelight support,"
|
ewarn "Applying the unofficial Compholio patchset for Pipelight support,"
|
||||||
ewarn "which is unsupported by Wine developers. Please don't report bugs"
|
ewarn "which is unsupported by Wine developers. Please don't report bugs"
|
||||||
ewarn "to Wine bugzilla unless you can reproduce them with USE=-pipelight"
|
ewarn "to Wine bugzilla unless you can reproduce them with USE=-pipelight"
|
||||||
|
|
||||||
PATCHES+=(
|
# epatch doesn't support binary patches and we ship our own pulse patches
|
||||||
"../${COMPHOLIO_PATCHES}/patches"/*/*.patch #507950
|
emake -C "${WORKDIR}/${COMPHOLIO_P}/patches" \
|
||||||
"../${COMPHOLIO_PATCHES}/patches/patch-list.patch"
|
$(echo ${COMPHOLIO_MAKE_ARGS}) \
|
||||||
)
|
series
|
||||||
|
|
||||||
|
PATCHES+=( $(sed -e "s:^:${WORKDIR}/${COMPHOLIO_P}/patches/:" \
|
||||||
|
"${WORKDIR}/${COMPHOLIO_P}/patches/series") )
|
||||||
|
|
||||||
# epatch doesn't support binary patches
|
# epatch doesn't support binary patches
|
||||||
ebegin "Applying Compholio font patches"
|
ebegin "Applying Compholio font patches"
|
||||||
for f in "${T}/10-Missing_Fonts"/*.patch; do
|
for f in "${WORKDIR}/${COMPHOLIO_P}/patches/fonts-Missing_Fonts"/*.patch; do
|
||||||
"../${COMPHOLIO_PATCHES}/debian/tools/gitapply.sh" < "${f}" || die "Failed to apply Compholio font patches"
|
"../${COMPHOLIO_P}/debian/tools/gitapply.sh" < "${f}" \
|
||||||
|
|| die "Failed to apply ${f}"
|
||||||
done
|
done
|
||||||
eend
|
eend
|
||||||
|
elif use pulseaudio; then
|
||||||
|
PATCHES+=( "../${COMPHOLIO_P}/patches/winepulse-PulseAudio_Support"/*.patch )
|
||||||
fi
|
fi
|
||||||
autotools-utils_src_prepare
|
autotools-utils_src_prepare
|
||||||
|
|
||||||
|
@ -392,6 +390,7 @@ multilib_src_configure() {
|
||||||
$(use_with opengl)
|
$(use_with opengl)
|
||||||
$(use_with osmesa)
|
$(use_with osmesa)
|
||||||
$(use_with oss)
|
$(use_with oss)
|
||||||
|
--without-pcap
|
||||||
$(use_with png)
|
$(use_with png)
|
||||||
$(use_with threads pthread)
|
$(use_with threads pthread)
|
||||||
$(use_with scanner sane)
|
$(use_with scanner sane)
|
||||||
|
|
Loading…
Reference in New Issue