unix: Implement `-X realtime` command-line option on macOS.
This adds a new command line option to the unix port `-X realtime` to enable realtime priority on threads. This enables high precision timers for applications that need more accurate timers. Related docs: https://developer.apple.com/library/archive/technotes/tn2169/_index.html Fixes issue #8621. Signed-off-by: David Lechner <david@pybricks.com>
This commit is contained in:
parent
be5657b64f
commit
c012318d74
|
@ -73,6 +73,8 @@ General options:
|
|||
- ``-X heapsize=<n>[w][K|M]`` sets the heap size for the garbage collector.
|
||||
The suffix ``w`` means words instead of bytes. ``K`` means x1024 and ``M``
|
||||
means x1024x1024.
|
||||
- ``-X realtime`` sets thread priority to realtime. This can be used to
|
||||
improve timer precision. Only available on macOS.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -328,6 +328,10 @@ STATIC void print_help(char **argv) {
|
|||
, heap_size);
|
||||
impl_opts_cnt++;
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
printf(" realtime -- set thread priority to realtime\n");
|
||||
impl_opts_cnt++;
|
||||
#endif
|
||||
|
||||
if (impl_opts_cnt == 0) {
|
||||
printf(" (none)\n");
|
||||
|
@ -399,6 +403,15 @@ STATIC void pre_process_options(int argc, char **argv) {
|
|||
goto invalid_arg;
|
||||
}
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
} else if (strcmp(argv[a + 1], "realtime") == 0) {
|
||||
#if MICROPY_PY_THREAD
|
||||
mp_thread_is_realtime_enabled = true;
|
||||
#endif
|
||||
// main thread was already intialized before the option
|
||||
// was parsed, so we have to enable realtime here.
|
||||
mp_thread_set_realtime();
|
||||
#endif
|
||||
} else {
|
||||
invalid_arg:
|
||||
exit(invalid_args());
|
||||
|
|
|
@ -192,6 +192,13 @@ void mp_thread_set_state(mp_state_thread_t *state) {
|
|||
}
|
||||
|
||||
void mp_thread_start(void) {
|
||||
// enable realtime priority if `-X realtime` command line parameter was set
|
||||
#if defined(__APPLE__)
|
||||
if (mp_thread_is_realtime_enabled) {
|
||||
mp_thread_set_realtime();
|
||||
}
|
||||
#endif
|
||||
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
mp_thread_unix_begin_atomic_section();
|
||||
for (mp_thread_t *th = thread; th != NULL; th = th->next) {
|
||||
|
@ -310,3 +317,39 @@ void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
|
|||
}
|
||||
|
||||
#endif // MICROPY_PY_THREAD
|
||||
|
||||
// this is used even when MICROPY_PY_THREAD is disabled
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach_error.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/thread_policy.h>
|
||||
|
||||
bool mp_thread_is_realtime_enabled;
|
||||
|
||||
// based on https://developer.apple.com/library/archive/technotes/tn2169/_index.html
|
||||
void mp_thread_set_realtime(void) {
|
||||
mach_timebase_info_data_t timebase_info;
|
||||
|
||||
mach_timebase_info(&timebase_info);
|
||||
|
||||
const uint64_t NANOS_PER_MSEC = 1000000ULL;
|
||||
double clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
|
||||
|
||||
thread_time_constraint_policy_data_t policy;
|
||||
policy.period = 0;
|
||||
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
|
||||
policy.constraint = (uint32_t)(10 * clock2abs);
|
||||
policy.preemptible = FALSE;
|
||||
|
||||
int kr = thread_policy_set(pthread_mach_thread_np(pthread_self()),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(thread_policy_t)&policy,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
|
||||
|
||||
if (kr != KERN_SUCCESS) {
|
||||
mach_error("thread_policy_set:", kr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef pthread_mutex_t mp_thread_mutex_t;
|
||||
|
||||
|
@ -36,3 +37,9 @@ void mp_thread_gc_others(void);
|
|||
// Functions as a port-global lock for any code that must be serialised.
|
||||
void mp_thread_unix_begin_atomic_section(void);
|
||||
void mp_thread_unix_end_atomic_section(void);
|
||||
|
||||
// for `-X realtime` command line option
|
||||
#if defined(__APPLE__)
|
||||
extern bool mp_thread_is_realtime_enabled;
|
||||
void mp_thread_set_realtime(void);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue