Split from https://gitlab.winehq.org/wine/wine/-/merge_requests/7516, with some minor tweaks and putting the tests first. I'll send more adjustments for the rest after.
From: Marc-Aurel Zent mzent@codeweavers.com
--- include/ddk/wdm.h | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/include/ddk/wdm.h b/include/ddk/wdm.h index 2ea6a81d432..6e63727dfdc 100644 --- a/include/ddk/wdm.h +++ b/include/ddk/wdm.h @@ -40,6 +40,11 @@ #define ADDRESS_AND_SIZE_TO_SPAN_PAGES(va, length) \ ((BYTE_OFFSET(va) + ((SIZE_T)(length)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)
+#define LOW_PRIORITY 0 +#define LOW_REALTIME_PRIORITY 16 +#define HIGH_PRIORITY 31 +#define MAXIMUM_PRIORITY 32 + typedef LONG KPRIORITY;
typedef ULONG_PTR KSPIN_LOCK, *PKSPIN_LOCK;
From: Marc-Aurel Zent mzent@codeweavers.com
--- dlls/ntdll/tests/info.c | 135 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index d24639b6b68..b92d421891f 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -31,7 +31,18 @@ #include "psapi.h" #include "wine/test.h"
+struct PROCESS_BASIC_INFORMATION_PRIVATE +{ + NTSTATUS ExitStatus; + PPEB PebBaseAddress; + DWORD_PTR AffinityMask; + DWORD_PTR BasePriority; + ULONG_PTR UniqueProcessId; + ULONG_PTR InheritedFromUniqueProcessId; +}; + static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); +static NTSTATUS (WINAPI * pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG); static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*); @@ -90,6 +101,7 @@ static void InitFunctionPtrs(void) HMODULE hkernel32 = GetModuleHandleA("kernel32");
NTDLL_GET_PROC(NtQuerySystemInformation); + NTDLL_GET_PROC(NtQueryInformationProcess); NTDLL_GET_PROC(NtQuerySystemInformationEx); NTDLL_GET_PROC(NtSetSystemInformation); NTDLL_GET_PROC(RtlGetNativeSystemInformation); @@ -3263,6 +3275,128 @@ static void test_affinity(void) "Unexpected thread affinity\n" ); }
+static void test_priority(void) +{ + NTSTATUS status; + DWORD proc_priority; + int thread_base_priority, expected_nt_priority; + ULONG nt_thread_priority; + THREAD_BASIC_INFORMATION tbi; + DECLSPEC_ALIGN(8) PROCESS_PRIORITY_CLASS ppc; /* needs align, or STATUS_DATATYPE_MISALIGNMENT is returned */ + struct PROCESS_BASIC_INFORMATION_PRIVATE pbi; + BOOL ret; + + /* Change process priority class to HIGH_PRIORITY_CLASS and test */ + ret = SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ); + ok( ret, "SetPriorityClass to HIGH_PRIORITY_CLASS failed: %lu\n", GetLastError() ); + proc_priority = GetPriorityClass( GetCurrentProcess() ); + ok( proc_priority == HIGH_PRIORITY_CLASS, "Expected HIGH_PRIORITY_CLASS, got %lu\n", proc_priority ); + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessPriorityClass, &ppc, sizeof(ppc), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationProcess failed: %08lx\n", status ); + ok( ppc.PriorityClass == PROCESS_PRIOCLASS_HIGH, "Expected PROCESS_PRIOCLASS_HIGH, got %lu\n", proc_priority ); + + /* Restore process priority back to normal */ + ret = SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS ); + ok( ret, "Restore SetPriorityClass failed: %lu\n", GetLastError() ); + proc_priority = GetPriorityClass( GetCurrentProcess() ); + ok( proc_priority == NORMAL_PRIORITY_CLASS, "Expected NORMAL_PRIORITY_CLASS after restore, got %lu\n", proc_priority ); + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessPriorityClass, &ppc, sizeof(ppc), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationProcess failed: %08lx\n", status ); + ok( ppc.PriorityClass == PROCESS_PRIOCLASS_NORMAL, "Expected PROCESS_PRIOCLASS_NORMAL, got %lu\n", proc_priority ); + + /* Before checking any thread priorities, disable priority boosting + * in order to make the tests reliable. */ + SetThreadPriorityBoost( GetCurrentThread(), TRUE ); + + /* Test thread priority: + * Compare the value from GetThreadPriority (thread priority level) + * with the BasePriority from NtQueryInformationThread. */ + thread_base_priority = GetThreadPriority( GetCurrentThread() ); + ok( thread_base_priority != THREAD_PRIORITY_ERROR_RETURN, "GetThreadPriority returned error\n" ); + + status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationThread failed: %08lx\n", status ); + ok( thread_base_priority == tbi.BasePriority, "Thread priority mismatch: Win32 API returned %d, NT BasePriority is %ld\n", + thread_base_priority, tbi.BasePriority ); + + /* Change the thread priority to THREAD_PRIORITY_HIGHEST and compare with + * underlying NT priority, which should be now the NORMAL_PRIORITY_CLASS + * base value (8) + THREAD_PRIORITY_HIGHEST (+2) = 10 (without boost). */ + ret = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST ); + ok( ret, "SetThreadPriority(THREAD_PRIORITY_HIGHEST) failed: %lu\n", GetLastError() ); + thread_base_priority = GetThreadPriority( GetCurrentThread() ); + ok( thread_base_priority == THREAD_PRIORITY_HIGHEST, "Expected THREAD_PRIORITY_HIGHEST (%d), got %d\n", + THREAD_PRIORITY_HIGHEST, thread_base_priority ); + + status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationThread failed after setting priority: %08lx\n", status ); + ok( thread_base_priority == tbi.BasePriority, "After setting, API priority (%d) does not match NT BasePriority (%ld)\n", + thread_base_priority, tbi.BasePriority ); + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL ); + expected_nt_priority = pbi.BasePriority + THREAD_PRIORITY_HIGHEST; + todo_wine ok( expected_nt_priority == tbi.Priority, "After setting, effective NT priority (%ld) does not match expected priority %d.\n", + tbi.Priority, expected_nt_priority ); + + /* Test setting the thread priority to THREAD_PRIORITY_LOWEST now, but using + * pNtSetInformationThread, also testing NT priority directly afterwards. */ + nt_thread_priority = THREAD_PRIORITY_LOWEST; + status = pNtSetInformationThread( GetCurrentThread(), ThreadBasePriority, &nt_thread_priority, sizeof(ULONG) ); + ok( status == STATUS_SUCCESS, "NtSetInformationThread(ThreadBasePriority) failed: %08lx\n", status ); + /* Effective thread priority should be now NORMAL_PRIORITY_CLASS base + * value (8) + THREAD_PRIORITY_LOWEST (-2) = 6. */ + status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationThread failed after setting priority: %08lx\n", status ); + ok( nt_thread_priority == tbi.BasePriority, "After setting, BasePriority (%ld) does not match set BasePriority (%ld)\n", + nt_thread_priority, tbi.BasePriority ); + expected_nt_priority = pbi.BasePriority + THREAD_PRIORITY_LOWEST; + todo_wine ok( expected_nt_priority == tbi.Priority, "After setting, effective NT priority (%ld) does not match expected priority %d.\n", + tbi.Priority, expected_nt_priority ); + /* Now set NT thread priority directly to 12, a value normally impossible to + * reach in NORMAL_PRIORITY_CLASS without boost. */ + nt_thread_priority = 12; + status = pNtSetInformationThread( GetCurrentThread(), ThreadPriority, &nt_thread_priority, sizeof(ULONG) ); + todo_wine ok( status == STATUS_SUCCESS, "NtSetInformationThread(ThreadPriority) failed: %08lx\n", status ); + /* Effective thread priority should be now 12, BasePriority should be + * unchanged. */ + status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationThread failed after setting priority: %08lx\n", status ); + ok( THREAD_PRIORITY_LOWEST == tbi.BasePriority, "After setting, BasePriority (%ld) does not match set BasePriority THREAD_PRIORITY_LOWEST.\n", + tbi.BasePriority ); + todo_wine ok( nt_thread_priority == tbi.Priority, "After setting, effective NT priority (%ld) does not match expected priority %lu.\n", + tbi.Priority, nt_thread_priority ); + /* Changing process priority recalculates all priorities again and + * overwrites our custom priority of 12. */ + ret = SetPriorityClass( GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS ); + ok( ret, "SetPriorityClass to BELOW_NORMAL_PRIORITY_CLASS failed: %lu\n", GetLastError() ); + /* Effective thread priority should be now BELOW_NORMAL_PRIORITY_CLASS base + * value (6) + THREAD_PRIORITY_LOWEST (-2) = 4. */ + status = pNtQueryInformationThread( GetCurrentThread(), ThreadBasicInformation, &tbi, sizeof(tbi), NULL ); + ok( status == STATUS_SUCCESS, "NtQueryInformationThread failed after setting priority: %08lx\n", status ); + status = pNtQueryInformationProcess( GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL ); + expected_nt_priority = pbi.BasePriority + THREAD_PRIORITY_LOWEST; + todo_wine ok( expected_nt_priority == tbi.Priority, "After setting, effective NT priority (%ld) does not match expected priority %d.\n", + tbi.Priority, expected_nt_priority ); + /* Setting an out of range priority above HIGH_PRIORITY (31) or LOW_PRIORITY (0) + * and lower fails. */ + nt_thread_priority = 42; + status = pNtSetInformationThread( GetCurrentThread(), ThreadPriority, &nt_thread_priority, sizeof(ULONG) ); + todo_wine ok( status == STATUS_INVALID_PARAMETER, "got %08lx, expected STATUS_INVALID_PARAMETER.\n", status ); + nt_thread_priority = 0; /* 0 also fails in addition to negative values. */ + status = pNtSetInformationThread( GetCurrentThread(), ThreadPriority, &nt_thread_priority, sizeof(ULONG) ); + todo_wine ok( status == STATUS_INVALID_PARAMETER, "got %08lx, expected STATUS_INVALID_PARAMETER.\n", status ); + /* Moving a thread into the realtime band is normally not possible in a non-realtime process. */ + nt_thread_priority = 24; + status = pNtSetInformationThread( GetCurrentThread(), ThreadPriority, &nt_thread_priority, sizeof(ULONG) ); + todo_wine ok( status == STATUS_PRIVILEGE_NOT_HELD, "got %08lx, expected STATUS_PRIVILEGE_NOT_HELD.\n", status ); + + /* Restore thread priority and boosting behaviour back to normal */ + SetThreadPriorityBoost( GetCurrentThread(), FALSE ); + ret = SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_NORMAL ); + ok( ret, "Restore SetThreadPriority(THREAD_PRIORITY_NORMAL) failed: %lu\n", GetLastError() ); + ret = SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS ); + ok( ret, "SetPriorityClass to NORMAL_PRIORITY_CLASS failed: %lu\n", GetLastError() ); +} + static DWORD WINAPI hide_from_debugger_thread(void *arg) { HANDLE stop_event = arg; @@ -4197,6 +4331,7 @@ START_TEST(info) test_ThreadIsTerminated();
test_affinity(); + test_priority(); test_debug_object();
/* belongs to its own file */
From: Marc-Aurel Zent mzent@codeweavers.com
--- server/process.c | 2 +- server/thread.c | 9 +++++---- server/thread.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/server/process.c b/server/process.c index c877bb6f7ae..6af58cc2cc6 100644 --- a/server/process.c +++ b/server/process.c @@ -1641,7 +1641,7 @@ void set_process_priority( struct process *process, int priority )
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { - set_thread_priority( thread, priority, thread->priority ); + set_thread_priority( thread, thread->priority ); } }
diff --git a/server/thread.c b/server/thread.c index 9f6f5f57a52..b0573b609fd 100644 --- a/server/thread.c +++ b/server/thread.c @@ -784,8 +784,9 @@ static int get_base_priority( int priority_class, int priority ) #define THREAD_PRIORITY_REALTIME_HIGHEST 6 #define THREAD_PRIORITY_REALTIME_LOWEST -7
-unsigned int set_thread_priority( struct thread *thread, int priority_class, int priority ) +unsigned int set_thread_priority( struct thread *thread, int priority ) { + int priority_class = thread->process->priority; int max = THREAD_PRIORITY_HIGHEST; int min = THREAD_PRIORITY_LOWEST;
@@ -814,7 +815,7 @@ static void set_thread_info( struct thread *thread, { if (req->mask & SET_THREAD_INFO_PRIORITY) { - unsigned int status = set_thread_priority( thread, thread->process->priority, req->priority ); + unsigned int status = set_thread_priority( thread, req->priority ); if (status) set_error( status ); } if (req->mask & SET_THREAD_INFO_AFFINITY) @@ -1617,7 +1618,7 @@ DECL_HANDLER(init_first_thread) else set_thread_affinity( current, current->affinity );
- set_thread_priority( current, process->priority, current->priority ); + set_thread_priority( current, current->priority );
debug_level = max( debug_level, req->debug_level );
@@ -1648,7 +1649,7 @@ DECL_HANDLER(init_thread)
init_thread_context( current ); generate_debug_event( current, DbgCreateThreadStateChange, &req->entry ); - set_thread_priority( current, current->process->priority, current->priority ); + set_thread_priority( current, current->priority ); set_thread_affinity( current, current->affinity );
reply->suspend = (current->suspend || current->process->suspend || current->context != NULL); diff --git a/server/thread.h b/server/thread.h index 2b256be322f..7549243e88b 100644 --- a/server/thread.h +++ b/server/thread.h @@ -122,7 +122,7 @@ extern void thread_cancel_apc( struct thread *thread, struct object *owner, enum extern int thread_add_inflight_fd( struct thread *thread, int client, int server ); extern int thread_get_inflight_fd( struct thread *thread, int client ); extern struct token *thread_get_impersonation_token( struct thread *thread ); -extern unsigned int set_thread_priority( struct thread *thread, int priority_class, int priority ); +extern unsigned int set_thread_priority( struct thread *thread, int priority ); extern int set_thread_affinity( struct thread *thread, affinity_t affinity ); extern int suspend_thread( struct thread *thread ); extern int resume_thread( struct thread *thread );
This merge request was approved by Rémi Bernon.
From: Marc-Aurel Zent mzent@codeweavers.com
This also uses the correct NT thread priority constants where possible. --- server/thread.c | 52 +++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 21 deletions(-)
diff --git a/server/thread.c b/server/thread.c index b0573b609fd..79452be00e8 100644 --- a/server/thread.c +++ b/server/thread.c @@ -51,6 +51,7 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h" +#include "ddk/wdm.h"
#include "file.h" #include "handle.h" @@ -247,14 +248,14 @@ void init_threading(void) if (nice_limit < 0 && debug_level) fprintf(stderr, "wine: Using setpriority to control niceness in the [%d,%d] range\n", nice_limit, -nice_limit ); }
-static void apply_thread_priority( struct thread *thread, int base_priority ) +static void apply_thread_priority( struct thread *thread, int effective_priority ) { int min = -nice_limit, max = nice_limit, range = max - min, niceness;
/* FIXME: handle realtime priorities using SCHED_RR if possible */ - if (base_priority > THREAD_BASE_PRIORITY_LOWRT) base_priority = THREAD_BASE_PRIORITY_LOWRT; - /* map an NT application band [1,15] base priority to [-nice_limit, nice_limit] */ - niceness = (min + (base_priority - 1) * range / 14); + if (effective_priority >= LOW_REALTIME_PRIORITY) effective_priority = LOW_REALTIME_PRIORITY - 1; + /* map an NT application band [1,15] priority to [-nice_limit, nice_limit] */ + niceness = (min + (effective_priority - 1) * range / 14); setpriority( PRIO_PROCESS, thread->unix_tid, niceness ); }
@@ -275,13 +276,13 @@ void init_threading(void) } }
-static int get_mach_importance( int base_priority ) +static int get_mach_importance( int effective_priority ) { int min = -31, max = 32, range = max - min; - return min + (base_priority - 1) * range / 14; + return min + (effective_priority - 1) * range / 14; }
-static void apply_thread_priority( struct thread *thread, int base_priority ) +static void apply_thread_priority( struct thread *thread, int effective_priority ) { kern_return_t kr; mach_msg_type_name_t type; @@ -294,9 +295,9 @@ static void apply_thread_priority( struct thread *thread, int base_priority ) kr = mach_port_extract_right( process_port, thread->unix_tid, MACH_MSG_TYPE_COPY_SEND, &thread_port, &type ); if (kr != KERN_SUCCESS) return; - /* base priority 15 is for time-critical threads, so not compute-bound */ - thread_extended_policy.timeshare = base_priority > 14 ? 0 : 1; - thread_precedence_policy.importance = get_mach_importance( base_priority ); + /* effective priority 15 is for time-critical threads, so not compute-bound */ + thread_extended_policy.timeshare = effective_priority > 14 ? 0 : 1; + thread_precedence_policy.importance = get_mach_importance( effective_priority ); /* adapted from the QoS table at xnu/osfmk/kern/thread_policy.c */ switch (thread->priority) { @@ -325,7 +326,7 @@ static void apply_thread_priority( struct thread *thread, int base_priority ) break; } /* QOS_UNSPECIFIED is assigned the highest tier available, so it does not provide a limit */ - if (base_priority > THREAD_BASE_PRIORITY_LOWRT) + if (effective_priority >= LOW_REALTIME_PRIORITY) { throughput_qos = THROUGHPUT_QOS_TIER_UNSPECIFIED; latency_qos = LATENCY_QOS_TIER_UNSPECIFIED; @@ -339,7 +340,7 @@ static void apply_thread_priority( struct thread *thread, int base_priority ) THREAD_EXTENDED_POLICY_COUNT ); thread_policy_set( thread_port, THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thread_precedence_policy, THREAD_PRECEDENCE_POLICY_COUNT ); - if (base_priority > THREAD_BASE_PRIORITY_LOWRT) + if (effective_priority >= LOW_REALTIME_PRIORITY) { /* For realtime threads we are requesting from the scheduler to be moved * into the Mach realtime band (96-127) above the kernel. @@ -354,14 +355,14 @@ static void apply_thread_priority( struct thread *thread, int base_priority ) * importance), which is on XNU equivalent to setting SCHED_RR with the * pthread API. */ struct thread_time_constraint_policy thread_time_constraint_policy; - int realtime_priority = base_priority - THREAD_BASE_PRIORITY_LOWRT; + int realtime_priority = effective_priority - LOW_REALTIME_PRIORITY + 1; unsigned int max_constraint = mach_ticks_per_second / 2; unsigned int max_computation = max_constraint / 10; /* unfortunately we can't give a hint for the periodicity of calculations */ thread_time_constraint_policy.period = 0; thread_time_constraint_policy.constraint = max_constraint; thread_time_constraint_policy.computation = realtime_priority * max_computation / 16; - thread_time_constraint_policy.preemptible = thread->priority == THREAD_PRIORITY_TIME_CRITICAL ? 0 : 1; + thread_time_constraint_policy.preemptible = effective_priority == HIGH_PRIORITY ? 0 : 1; thread_policy_set( thread_port, THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t)&thread_time_constraint_policy, THREAD_TIME_CONSTRAINT_POLICY_COUNT ); @@ -375,7 +376,7 @@ void init_threading(void) { }
-static void apply_thread_priority( struct thread *thread, int base_priority ) +static void apply_thread_priority( struct thread *thread, int effective_priority ) { }
@@ -770,15 +771,24 @@ affinity_t get_thread_affinity( struct thread *thread ) return mask; }
-static int get_base_priority( int priority_class, int priority ) +static int priority_from_class_and_level( int priority_class, int priority_level ) { /* offsets taken from https://learn.microsoft.com/en-us/windows/win32/procthread/scheduling-priori... */ static const int class_offsets[] = { 4, 8, 13, 24, 6, 10 };
- if (priority == THREAD_PRIORITY_IDLE) return (priority_class == PROCESS_PRIOCLASS_REALTIME ? 16 : 1); - if (priority == THREAD_PRIORITY_TIME_CRITICAL) return (priority_class == PROCESS_PRIOCLASS_REALTIME ? 31 : 15); - if (priority_class >= ARRAY_SIZE(class_offsets)) return 8; - return class_offsets[priority_class - 1] + priority; + if (priority_class == PROCESS_PRIOCLASS_REALTIME) + { + if (priority_level == THREAD_PRIORITY_IDLE) return LOW_REALTIME_PRIORITY; + if (priority_level == THREAD_PRIORITY_TIME_CRITICAL) return HIGH_PRIORITY; + } + else + { + if (priority_level == THREAD_PRIORITY_IDLE) return LOW_PRIORITY + 1; + if (priority_level == THREAD_PRIORITY_TIME_CRITICAL) return LOW_REALTIME_PRIORITY - 1; + } + + if (priority_class >= ARRAY_SIZE(class_offsets)) return LOW_REALTIME_PRIORITY / 2; + return class_offsets[priority_class - 1] + priority_level; }
#define THREAD_PRIORITY_REALTIME_HIGHEST 6 @@ -804,7 +814,7 @@ unsigned int set_thread_priority( struct thread *thread, int priority )
/* if thread is gone or hasn't started yet, this will be called again from init_thread with a unix_tid */ if (thread->state == RUNNING && thread->unix_tid != -1) - apply_thread_priority( thread, get_base_priority( priority_class, priority )); + apply_thread_priority( thread, priority_from_class_and_level( priority_class, priority ) );
return STATUS_SUCCESS; }
From: Marc-Aurel Zent mzent@codeweavers.com
--- dlls/ntdll/unix/thread.c | 8 ++++---- server/process.c | 6 +++--- server/protocol.def | 14 +++++++------- server/thread.c | 27 ++++++++++++++------------- server/thread.h | 4 ++-- 5 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index d3ddcf13963..b31f8969c21 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -2373,13 +2373,13 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
case ThreadBasePriority: { - const DWORD *pprio = data; + const DWORD *base_priority = data; if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER; SERVER_START_REQ( set_thread_info ) { - req->handle = wine_server_obj_handle( handle ); - req->priority = *pprio; - req->mask = SET_THREAD_INFO_PRIORITY; + req->handle = wine_server_obj_handle( handle ); + req->base_priority = *base_priority; + req->mask = SET_THREAD_INFO_BASE_PRIORITY; status = wine_server_call( req ); } SERVER_END_REQ; diff --git a/server/process.c b/server/process.c index 6af58cc2cc6..1980e2ca777 100644 --- a/server/process.c +++ b/server/process.c @@ -1641,7 +1641,7 @@ void set_process_priority( struct process *process, int priority )
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry ) { - set_thread_priority( thread, thread->priority ); + set_thread_base_priority( thread, thread->base_priority ); } }
@@ -2013,8 +2013,8 @@ DECL_HANDLER(list_processes)
thread_info->start_time = thread->creation_time; thread_info->tid = thread->id; - thread_info->base_priority = thread->priority; - thread_info->current_priority = thread->priority; /* FIXME */ + thread_info->base_priority = thread->base_priority; + thread_info->current_priority = thread->base_priority; /* FIXME */ thread_info->unix_tid = thread->unix_tid; thread_info->entry_point = thread->entry_point; thread_info->teb = thread->teb; diff --git a/server/protocol.def b/server/protocol.def index 871c3909e8c..ee98e10ec4c 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1247,18 +1247,18 @@ struct obj_locator @REQ(set_thread_info) obj_handle_t handle; /* thread handle */ int mask; /* setting mask (see below) */ - int priority; /* priority class */ + int base_priority;/* base priority level (relative to process base priority class) */ affinity_t affinity; /* affinity mask */ client_ptr_t entry_point; /* thread entry point */ obj_handle_t token; /* impersonation token */ VARARG(desc,unicode_str); /* description string */ @END -#define SET_THREAD_INFO_PRIORITY 0x01 -#define SET_THREAD_INFO_AFFINITY 0x02 -#define SET_THREAD_INFO_TOKEN 0x04 -#define SET_THREAD_INFO_ENTRYPOINT 0x08 -#define SET_THREAD_INFO_DESCRIPTION 0x10 -#define SET_THREAD_INFO_DBG_HIDDEN 0x20 +#define SET_THREAD_INFO_BASE_PRIORITY 0x01 +#define SET_THREAD_INFO_AFFINITY 0x02 +#define SET_THREAD_INFO_TOKEN 0x04 +#define SET_THREAD_INFO_ENTRYPOINT 0x08 +#define SET_THREAD_INFO_DESCRIPTION 0x10 +#define SET_THREAD_INFO_DBG_HIDDEN 0x20
/* Suspend a thread */ diff --git a/server/thread.c b/server/thread.c index 79452be00e8..8797af32648 100644 --- a/server/thread.c +++ b/server/thread.c @@ -299,7 +299,7 @@ static void apply_thread_priority( struct thread *thread, int effective_priority thread_extended_policy.timeshare = effective_priority > 14 ? 0 : 1; thread_precedence_policy.importance = get_mach_importance( effective_priority ); /* adapted from the QoS table at xnu/osfmk/kern/thread_policy.c */ - switch (thread->priority) + switch (thread->base_priority) { case THREAD_PRIORITY_IDLE: /* THREAD_QOS_MAINTENANCE */ case THREAD_PRIORITY_LOWEST: /* THREAD_QOS_BACKGROUND */ @@ -405,7 +405,7 @@ static inline void init_thread_structure( struct thread *thread ) thread->wait_fd = NULL; thread->state = RUNNING; thread->exit_code = 0; - thread->priority = 0; + thread->base_priority = 0; thread->suspend = 0; thread->dbg_hidden = 0; thread->desktop_users = 0; @@ -794,7 +794,8 @@ static int priority_from_class_and_level( int priority_class, int priority_level #define THREAD_PRIORITY_REALTIME_HIGHEST 6 #define THREAD_PRIORITY_REALTIME_LOWEST -7
-unsigned int set_thread_priority( struct thread *thread, int priority ) +/* sets the thread base priority level, relative to its process base priority class */ +unsigned int set_thread_base_priority( struct thread *thread, int base_priority ) { int priority_class = thread->process->priority; int max = THREAD_PRIORITY_HIGHEST; @@ -805,16 +806,16 @@ unsigned int set_thread_priority( struct thread *thread, int priority ) max = THREAD_PRIORITY_REALTIME_HIGHEST; min = THREAD_PRIORITY_REALTIME_LOWEST; } - if ((priority < min || priority > max) && - priority != THREAD_PRIORITY_IDLE && - priority != THREAD_PRIORITY_TIME_CRITICAL) + if ((base_priority < min || base_priority > max) && + base_priority != THREAD_PRIORITY_IDLE && + base_priority != THREAD_PRIORITY_TIME_CRITICAL) return STATUS_INVALID_PARAMETER;
- thread->priority = priority; + thread->base_priority = base_priority;
/* if thread is gone or hasn't started yet, this will be called again from init_thread with a unix_tid */ if (thread->state == RUNNING && thread->unix_tid != -1) - apply_thread_priority( thread, priority_from_class_and_level( priority_class, priority ) ); + apply_thread_priority( thread, priority_from_class_and_level( priority_class, base_priority ) );
return STATUS_SUCCESS; } @@ -823,9 +824,9 @@ unsigned int set_thread_priority( struct thread *thread, int priority ) static void set_thread_info( struct thread *thread, const struct set_thread_info_request *req ) { - if (req->mask & SET_THREAD_INFO_PRIORITY) + if (req->mask & SET_THREAD_INFO_BASE_PRIORITY) { - unsigned int status = set_thread_priority( thread, req->priority ); + unsigned int status = set_thread_base_priority( thread, req->base_priority ); if (status) set_error( status ); } if (req->mask & SET_THREAD_INFO_AFFINITY) @@ -1628,7 +1629,7 @@ DECL_HANDLER(init_first_thread) else set_thread_affinity( current, current->affinity );
- set_thread_priority( current, current->priority ); + set_thread_base_priority( current, current->base_priority );
debug_level = max( debug_level, req->debug_level );
@@ -1659,7 +1660,7 @@ DECL_HANDLER(init_thread)
init_thread_context( current ); generate_debug_event( current, DbgCreateThreadStateChange, &req->entry ); - set_thread_priority( current, current->priority ); + set_thread_base_priority( current, current->base_priority ); set_thread_affinity( current, current->affinity );
reply->suspend = (current->suspend || current->process->suspend || current->context != NULL); @@ -1708,7 +1709,7 @@ DECL_HANDLER(get_thread_info) reply->teb = thread->teb; reply->entry_point = thread->entry_point; reply->exit_code = (thread->state == TERMINATED) ? thread->exit_code : STATUS_PENDING; - reply->priority = thread->priority; + reply->priority = thread->base_priority; reply->affinity = thread->affinity; reply->last = thread->process->running_threads == 1; reply->suspend_count = thread->suspend; diff --git a/server/thread.h b/server/thread.h index 7549243e88b..33d150df9cb 100644 --- a/server/thread.h +++ b/server/thread.h @@ -81,7 +81,7 @@ struct thread client_ptr_t teb; /* TEB address (in client address space) */ client_ptr_t entry_point; /* entry point (in client address space) */ affinity_t affinity; /* affinity mask */ - int priority; /* priority level */ + int base_priority; /* base priority level (relative to process base priority class) */ int suspend; /* suspend count */ int dbg_hidden; /* hidden from debugger */ obj_handle_t desktop; /* desktop handle */ @@ -122,7 +122,7 @@ extern void thread_cancel_apc( struct thread *thread, struct object *owner, enum extern int thread_add_inflight_fd( struct thread *thread, int client, int server ); extern int thread_get_inflight_fd( struct thread *thread, int client ); extern struct token *thread_get_impersonation_token( struct thread *thread ); -extern unsigned int set_thread_priority( struct thread *thread, int priority ); +extern unsigned int set_thread_base_priority( struct thread *thread, int base_priority ); extern int set_thread_affinity( struct thread *thread, affinity_t affinity ); extern int suspend_thread( struct thread *thread ); extern int resume_thread( struct thread *thread );