From: Marc-Aurel Zent mzent@codeweavers.com
--- dlls/ntdll/unix/thread.c | 91 ++++++++++++++++++++++++++++++---------- 1 file changed, 70 insertions(+), 21 deletions(-)
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 9e84ec3cc96..37341416a9e 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1911,39 +1911,88 @@ static void set_native_thread_name( HANDLE handle, const UNICODE_STRING *name ) close( fd ); } #elif defined(__APPLE__) - /* pthread_setname_np() silently fails if the name is longer than 63 characters + null terminator */ - char nameA[64]; - NTSTATUS status; - int unix_pid, unix_tid, len, current_tid; + extern int __proc_info( int callnum, int pid, int flavor, uint64_t arg, void *buffer, int buffersize ); + static int pthread_name_offset = -1; + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + char nameA[MAXTHREADNAMESIZE]; + char *pthread_name; + int len; + THREAD_BASIC_INFORMATION info; + struct ntdll_thread_data *thread_data; + pthread_t pthread_id;
- SERVER_START_REQ( get_thread_times ) + if (NtQueryInformationThread( handle, ThreadBasicInformation, &info, sizeof(info), NULL )) + return; + + if (HandleToULong( info.ClientId.UniqueProcess ) != GetCurrentProcessId()) { - req->handle = wine_server_obj_handle( handle ); - status = wine_server_call( req ); - if (status == STATUS_SUCCESS) + static int once; + if (!once++) FIXME("cross-process native thread naming not supported\n"); + return; + } + + pthread_mutex_lock( &lock ); + + if (pthread_name_offset == -1) + { + char current_thread_name[MAXTHREADNAMESIZE]; + const char *test_name = "__WINE_THREAD_NAME_OFFSET_TEST__"; + const int max_search_offset = 256; + int test_name_len, search_offset = 0; + + pthread_getname_np( pthread_self(), current_thread_name, sizeof(current_thread_name) ); + test_name_len = strlen( test_name ); + pthread_setname_np( test_name ); + + for (; search_offset < max_search_offset; search_offset++) { - unix_pid = reply->unix_pid; - unix_tid = reply->unix_tid; + char *candidate = (char *)pthread_self() + search_offset; + if (!strncmp( candidate, test_name, test_name_len )) + { + pthread_name_offset = search_offset; + break; + } + } + + pthread_setname_np( current_thread_name ); + + if (pthread_name_offset == -1) + { + static int once; + if (!once++) ERR("could not determine pthread_name struct offset\n"); + goto out; } } - SERVER_END_REQ;
- if (status != STATUS_SUCCESS || unix_pid == -1 || unix_tid == -1) - return; + thread_data = (struct ntdll_thread_data *)&((PTEB)(info.TebBaseAddress))->GdiTebBatch; + pthread_id = thread_data->pthread_id; + pthread_name = (char *)pthread_id + pthread_name_offset;
- current_tid = mach_thread_self(); - mach_port_deallocate(mach_task_self(), current_tid); + len = ntdll_wcstoumbs( name->Buffer, name->Length / sizeof(WCHAR), nameA, sizeof(nameA) - 1, FALSE );
- if (unix_tid != current_tid) + if (len >= 0) + { + nameA[len] = '\0'; + strcpy( pthread_name, nameA ); + } + else + { + bzero( pthread_name, MAXTHREADNAMESIZE ); + goto out; + } + + if (!pthread_equal( pthread_self(), pthread_id )) { static int once; - if (!once++) FIXME("setting other thread name not supported\n"); - return; + if (!once++) FIXME("cross-thread native thread naming not visible cross-process\n"); + goto out; }
- len = ntdll_wcstoumbs( name->Buffer, name->Length / sizeof(WCHAR), nameA, sizeof(nameA) - 1, FALSE ); - nameA[len] = '\0'; - pthread_setname_np(nameA); + if (__proc_info( 5, getpid(), 2, (uint64_t)0, (void *)nameA, len )) + ERR("could not set native thread name kernel-side\n"); + +out: + pthread_mutex_unlock( &lock ); #else static int once; if (!once++) FIXME("not implemented on this platform\n");