@@ -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,