Index: src/OFThread.h ================================================================== --- src/OFThread.h +++ src/OFThread.h @@ -220,21 +220,28 @@ - (void)setName: (nullable OFString*)name; /*! * @brief Returns the priority of the thread. * + * This is a value between -1.0 (meaning lowest priority that still schedules) + * and +1.0 (meaning highest priority that still allows getting preemptted) + * with normal priority being 0.0 (meaning being the same as the main thread). + * * @return The priority of the thread */ - (float)priority; /*! * @brief Sets the priority of the thread. * * @note This has to be set before the thread is started! * - * @param priority The priority for the thread, with 0.0 being the lowest and - * 1.0 the highest + * @param priority The priority of the thread. This is a value between -1.0 + * (meaning lowest priority that still schedules) and +1.0 + * (meaning highest priority that still allows getting + * preemptted) with normal priority being 0.0 (meaning being + * the same as the main thread). */ - (void)setPriority: (float)priority; /*! * @brief Returns the stack size of the thread. Index: src/threading_pthread.m ================================================================== --- src/threading_pthread.m +++ src/threading_pthread.m @@ -24,14 +24,38 @@ #ifdef OF_HAIKU # include #endif +static int minPrio, maxPrio, normalPrio; + struct thread_ctx { void (*function)(id object); id object; }; + +/* + * This is done here to make sure this is done as early as possible in the main + * thread. + */ +static void __attribute__((constructor)) +init(void) +{ + pthread_attr_t pattr; + int policy; + struct sched_param param; + + OF_ENSURE(pthread_attr_init(&pattr) == 0); + OF_ENSURE(pthread_attr_getschedpolicy(&pattr, &policy) == 0); + OF_ENSURE((minPrio = sched_get_priority_min(policy)) != -1); + OF_ENSURE((maxPrio = sched_get_priority_max(policy)) != -1); + OF_ENSURE(pthread_attr_getschedparam(&pattr, ¶m) == 0); + + normalPrio = param.sched_priority; + + pthread_attr_destroy(&pattr); +} static void* function_wrapper(void *data) { struct thread_ctx *ctx = data; @@ -51,28 +75,11 @@ if (pthread_attr_init(&pattr) != 0) return false; @try { - int policy, minPrio, maxPrio; - struct sched_param param; - - if (pthread_attr_getschedpolicy(&pattr, &policy) != 0) - return false; - - minPrio = sched_get_priority_min(policy); - maxPrio = sched_get_priority_max(policy); - - if (pthread_attr_getschedparam(&pattr, ¶m) != 0) - return false; - - /* Prevent possible division by zero */ - if (minPrio != maxPrio) - attr->priority = (float)(param.sched_priority - - minPrio) / (maxPrio - minPrio); - else - attr->priority = 0; + attr->priority = 0; if (pthread_attr_getstacksize(&pattr, &attr->stackSize) != 0) return false; } @finally { pthread_attr_destroy(&pattr); @@ -93,31 +100,29 @@ @try { struct thread_ctx *ctx; if (attr != NULL) { - int policy, minPrio, maxPrio; struct sched_param param; - if (attr->priority < 0 || attr->priority > 1) - return false; - - if (pthread_attr_getschedpolicy(&pattr, &policy) != 0) - return false; - - minPrio = sched_get_priority_min(policy); - maxPrio = sched_get_priority_max(policy); - - param.sched_priority = (float)minPrio + - attr->priority * (maxPrio - minPrio); + if (attr->priority < -1 || attr->priority > 1) + return false; #ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED if (pthread_attr_setinheritsched(&pattr, PTHREAD_EXPLICIT_SCHED) != 0) return false; #endif + if (attr->priority < 0) { + param.sched_priority = minPrio + + (1.0 + attr->priority) * + (normalPrio - minPrio); + } else + param.sched_priority = normalPrio + + attr->priority * (maxPrio - normalPrio); + if (pthread_attr_setschedparam(&pattr, ¶m) != 0) return false; if (attr->stackSize > 0) { if (pthread_attr_setstacksize(&pattr, Index: src/threading_winapi.m ================================================================== --- src/threading_winapi.m +++ src/threading_winapi.m @@ -19,13 +19,11 @@ #import "macros.h" bool of_thread_attr_init(of_thread_attr_t *attr) { - attr->priority = - (float)(THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST) / - (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_LOWEST); + attr->priority = 0; attr->stackSize = 0; return true; } @@ -35,15 +33,22 @@ { size_t stackSize = 0; int priority = 0; if (attr != NULL) { - if (attr->priority < 0 || attr->priority > 1) + if (attr->priority < -1 || attr->priority > 1) return false; - priority = THREAD_PRIORITY_LOWEST + attr->priority * - (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_LOWEST); + if (attr->priority < 0) + priority = THREAD_PRIORITY_LOWEST + + (1.0 + attr->priority) * + (THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST); + else + priority = THREAD_PRIORITY_NORMAL + + attr->priority * + (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_NORMAL); + stackSize = attr->stackSize; } *thread = CreateThread(NULL, stackSize, (LPTHREAD_START_ROUTINE)function, (__bridge void*)object, 0, NULL);