Skip to content

Commit

Permalink
NSThread: Fix threadPriority and setThreadPriority: on Android by…
Browse files Browse the repository at this point in the history
… using `setpriority` instead of pthread (#436)

* Update Changelog

* Use {get, set}priority for -[NSThread setThreadPriority] on Android
  • Loading branch information
hmelder authored Aug 13, 2024
1 parent 7cc7fc5 commit 162708f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2024-12-08 Hugo Melder <[email protected]>
* Source/NSThread.m:
Fix threadPriority and setThreadPriority: on Android.

2024-08-08 Richard Frith-Macdonald <[email protected]>

* Tools/AGSHtml.m:
Expand Down
47 changes: 45 additions & 2 deletions Source/NSThread.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ int pthread_spin_destroy(pthread_spinlock_t *lock)
# include <sys/file.h>
#endif

#if defined(__ANDROID__)
# include <string.h> // For strerror
# include <sys/resource.h> // For getpriority and setpriority
#endif

#if defined(HAVE_SYS_FCNTL_H)
# include <sys/fcntl.h>
#elif defined(HAVE_FCNTL_H)
Expand Down Expand Up @@ -1004,6 +1009,34 @@ + (BOOL) setThreadPriority: (double)pri
return NO;
}
return YES;
#elif defined(__ANDROID__)
/* Android's pthread_setschedparam is currently broken, as it checks
* if the priority is in the range of the system's min and max
* priorities. The interval bounds are queried with `sched_get_priority_min`,
* and `sched_get_priority_max` which just return 0, regardless of the
* specified scheduling policy.
*
* The solution is to use `setpriority` to set the thread
* priority. This is possible because on Linux, it is not a per-process setting
* as specified by POSIX but a per-thread setting (See the `Bugs` section in `setpriority`).
*
* Android's internal implementation also relies on this behavior, so it
* is safe to use it here.
*/

// Clamp pri into the required range.
if (pri > 1) { pri = 1; }
if (pri < 0) { pri = 0; }

// Convert [0.0, 1.0] to [-20, 19] range where -20 is the highest
// and 19 the lowest priority.
int priority = (int)(-20 + (1-pri) * 39);
if (setpriority(PRIO_PROCESS, 0, priority) == -1)
{
NSLog(@"Failed to set thread priority %d: %s", priority, strerror(errno));
return NO;
}
return YES;
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
int res;
int policy;
Expand Down Expand Up @@ -1097,6 +1130,18 @@ + (double) threadPriority
NSLog(@"Unknown thread priority: %d", winPri);
break;
}
#elif defined(__ANDROID__)
/* See notes in setThreadPriority
*/
int priority = getpriority(PRIO_PROCESS, 0);
if (priority == -1)
{
NSLog(@"Failed to get thread priority: %s", strerror(errno));
return pri;
}

// Convert [-20, 19] to [0.0, 1.0] range
pri = 1 - (priority + 20) / 39.0;
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
int res;
int policy;
Expand Down Expand Up @@ -1126,8 +1171,6 @@ + (double) threadPriority
return pri;
}



/*
* Thread instance methods.
*/
Expand Down

0 comments on commit 162708f

Please sign in to comment.