From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/ntdll/Makefile.in | 1 + dlls/ntdll/unix/loader.c | 50 ---------------------------------- dlls/ntdll/unix/sched.c | 48 ++++++++++++++++++++++++++++++++ dlls/ntdll/unix/server.c | 14 ++++++++-- dlls/ntdll/unix/unix_private.h | 2 ++ server/process.c | 11 +++++++- server/protocol.def | 1 + 7 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 dlls/ntdll/unix/sched.c diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in index ad5c3bdc60f..5515e836129 100644 --- a/dlls/ntdll/Makefile.in +++ b/dlls/ntdll/Makefile.in @@ -56,6 +56,7 @@ SOURCES = \ unix/loadorder.c \ unix/process.c \ unix/registry.c \ + unix/sched.c \ unix/security.c \ unix/serial.c \ unix/server.c \ diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 28fc09cd354..6f0f3a23bbd 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1998,45 +1998,8 @@ jint JNI_OnLoad( JavaVM *vm, void *reserved ) #endif /* __ANDROID__ */ #ifdef __APPLE__ -static void *apple_wine_thread( void *arg ) -{ - start_main_thread(); - return NULL; -} - -/*********************************************************************** - * apple_create_wine_thread - * - * Spin off a secondary thread to complete Wine initialization, leaving - * the original thread for the Mac frameworks. - * - * Invoked as a CFRunLoopSource perform callback. - */ -static void apple_create_wine_thread( void *arg ) -{ - pthread_t thread; - pthread_attr_t attr; - - pthread_attr_init( &attr ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); - if (pthread_create( &thread, &attr, apple_wine_thread, NULL )) exit(1); - pthread_attr_destroy( &attr ); -} - - -/*********************************************************************** - * apple_main_thread - * - * Park the process's original thread in a Core Foundation run loop for - * use by the Mac frameworks, especially receiving and handling - * distributed notifications. Spin off a new thread for the rest of the - * Wine initialization. - */ static void apple_main_thread(void) { - CFRunLoopSourceContext source_context = { 0 }; - CFRunLoopSourceRef source; - if (!pthread_main_np()) return; #pragma clang diagnostic push @@ -2051,19 +2014,6 @@ static void apple_main_thread(void) * center scheduled on this thread's run loop. In theory, it's scheduled * in the first thread to ask for it. */ CFNotificationCenterGetDistributedCenter(); - - /* We use this run loop source for two purposes. First, a run loop exits - * if it has no more sources scheduled. So, we need at least one source - * to keep the run loop running. Second, although it's not critical, it's - * preferable for the Wine initialization to not proceed until we know - * the run loop is running. So, we signal our source immediately after - * adding it and have its callback spin off the Wine thread. */ - source_context.perform = apple_create_wine_thread; - source = CFRunLoopSourceCreate( NULL, 0, &source_context ); - CFRunLoopAddSource( CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes ); - CFRunLoopSourceSignal( source ); - CFRelease( source ); - CFRunLoopRun(); /* Should never return, except on error. */ } #endif /* __APPLE__ */ diff --git a/dlls/ntdll/unix/sched.c b/dlls/ntdll/unix/sched.c new file mode 100644 index 00000000000..250ecff44af --- /dev/null +++ b/dlls/ntdll/unix/sched.c @@ -0,0 +1,48 @@ +/* + * Copyright 2026 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include <stddef.h> +#include <stdarg.h> + +#include <poll.h> + +#include "unix_private.h" + +#ifdef __APPLE__ + +#include <CoreFoundation/CoreFoundation.h> + +void sched_run(void) +{ + CFRunLoopRun(); +} + +#else + +void sched_run(void) +{ + for (;;) poll( NULL, 0, -1 ); +} + +#endif diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 10167d24215..2084a8127c6 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -1736,6 +1736,8 @@ void server_init_process_done(void) int suspend; FILE_FS_DEVICE_INFORMATION info; struct ntdll_thread_data *thread_data = ntdll_get_thread_data(); + HANDLE handle; + DWORD flags; if (!get_device_info( initial_cwd, &info ) && (info.Characteristics & FILE_REMOVABLE_MEDIA)) chdir( "/" ); @@ -1755,18 +1757,26 @@ void server_init_process_done(void) /* always send the native TEB */ if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb(); + flags = THREAD_CREATE_FLAGS_CREATE_SUSPENDED; + status = NtCreateThreadEx( &handle, THREAD_ALL_ACCESS, NULL, NtCurrentProcess(), + main_image_info.TransferAddress, peb, flags, 0, 0, 0, NULL ); + assert( !status ); + /* Signal the parent process to continue */ SERVER_START_REQ( init_process_done ) { + req->main = wine_server_obj_handle( handle ); req->teb = wine_server_client_ptr( teb ); req->peb = NtCurrentTeb64() ? NtCurrentTeb64()->Peb : wine_server_client_ptr( peb ); status = wine_server_call( req ); suspend = reply->suspend; } SERVER_END_REQ; - assert( !status ); - signal_start_thread( main_image_info.TransferAddress, peb, suspend, NtCurrentTeb() ); + if (!suspend) NtResumeThread( handle, NULL ); + NtClose( handle ); + + sched_run(); } diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 10f6bb2c63c..1ea6ab56d18 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -388,6 +388,8 @@ extern NTSTATUS wow64_wine_server_handle_to_fd( void *args ); extern NTSTATUS wow64_wine_spawnvp( void *args ); #endif +extern void sched_run(void); + extern void dbg_init(void); extern void close_inproc_sync( HANDLE handle ); diff --git a/server/process.c b/server/process.c index 91c4a76326c..60e8ae18188 100644 --- a/server/process.c +++ b/server/process.c @@ -1481,12 +1481,21 @@ DECL_HANDLER(get_startup_info) DECL_HANDLER(init_process_done) { struct process *process = current->process; + struct thread *thread; if (is_process_init_done(process)) { set_error( STATUS_INVALID_PARAMETER ); return; } + if (!(thread = get_thread_from_handle( req->main, THREAD_ALL_ACCESS ))) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + list_remove( &thread->proc_entry ); + list_add_head( &process->thread_list, &thread->proc_entry ); + release_object( thread ); current->teb = req->teb; process->peb = req->peb; @@ -1500,7 +1509,7 @@ DECL_HANDLER(init_process_done) if (process->image_info.subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI) process->idle_event = create_event( NULL, NULL, 0, 1, 0, NULL ); if (process->debug_obj) set_process_debug_flag( process, 1 ); - reply->suspend = (current->suspend || process->suspend); + reply->suspend = process->suspend; } /* open a handle to a process */ diff --git a/server/protocol.def b/server/protocol.def index f7cecc336f0..bd54db30a0a 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1144,6 +1144,7 @@ typedef volatile struct /* Signal the end of the process initialization */ @REQ(init_process_done) + obj_handle_t main; /* main thread handle */ client_ptr_t teb; /* TEB of new thread (in process address space) */ client_ptr_t peb; /* PEB of new process (in process address space) */ @REPLY -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10058