1 : /*
2 : * Copyright 2009 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can
4 : * be found in the LICENSE file.
5 : */
6 : /*
7 : * Mac OSX thread priority support.
8 : */
9 :
10 : #include <mach/mach_init.h>
11 : #include <mach/mach_time.h>
12 : #include <mach/thread_policy.h>
13 : #include <mach/thread_act.h>
14 :
15 : #include "native_client/src/shared/platform/nacl_log.h"
16 : #include "native_client/src/trusted/service_runtime/include/sys/nacl_nice.h"
17 :
18 : /* MyConvertToHostTime converts nanoseconds to the time base used by MacOS.
19 : * Typically the time base is nanoseconds, and the conversion is trivial.
20 : * To avoid having to drag in the entire CoreAudio framework just for this
21 : * subroutine, it is reimplemented here in terms of mach_timebase_info which
22 : * is in the MacOS core.
23 : * To understand that this implementation is correct, have a look at
24 : * CAHostTimeBase::ConvertFromNanos(uint64 inNanos) in CAHostTimeBase.h
25 : */
26 : static struct mach_timebase_info gTimeBase;
27 14 : void NaClThreadNiceInit() {
28 14 : if (mach_timebase_info(&gTimeBase) != KERN_SUCCESS) {
29 0 : NaClLog(LOG_WARNING, "mach_timebase_info failed\n");
30 0 : gTimeBase.numer = 1;
31 0 : gTimeBase.denom = 1;
32 : }
33 14 : if (gTimeBase.denom == 0) {
34 0 : NaClLog(LOG_WARNING, "mach_timebase_info returned bogus result\n");
35 0 : gTimeBase.numer = 1;
36 0 : gTimeBase.denom = 1;
37 : }
38 14 : }
39 :
40 0 : static uint64_t MyConvertToHostTime(uint64_t nanos) {
41 0 : double math_tmp = 0.0;
42 :
43 0 : math_tmp = gTimeBase.numer;
44 0 : math_tmp *= nanos;
45 0 : math_tmp /= gTimeBase.denom;
46 0 : return (uint64_t)math_tmp;
47 : }
48 :
49 0 : int nacl_thread_nice(int nacl_nice) {
50 : kern_return_t kr;
51 0 : thread_act_t mthread = mach_thread_self();
52 :
53 0 : switch (nacl_nice) {
54 : case NICE_REALTIME: {
55 : struct thread_time_constraint_policy tcpolicy;
56 0 : const int kPeriodInNanoseconds = 2902490;
57 0 : const float kDutyCycle = 0.5;
58 0 : const float kDutyMax = 0.85;
59 0 : tcpolicy.period = MyConvertToHostTime(kPeriodInNanoseconds);
60 0 : tcpolicy.computation = kDutyCycle * tcpolicy.period;
61 0 : tcpolicy.constraint = kDutyMax * tcpolicy.period;
62 0 : tcpolicy.preemptible = 1;
63 : /* Sadly it appears that a MacOS system can be locked up by too
64 : * many real-time threads. So use normal priority until we figure
65 : * out a way to control things globally.
66 : */
67 : /* kr = thread_policy_set(mthread, THREAD_TIME_CONSTRAINT_POLICY,
68 : * (thread_policy_t)&tcpolicy,
69 : * THREAD_TIME_CONSTRAINT_POLICY_COUNT);
70 : */
71 0 : kr = thread_policy_set(mthread, THREAD_PRECEDENCE_POLICY,
72 : (thread_policy_t)&tcpolicy,
73 : THREAD_PRECEDENCE_POLICY_COUNT);
74 : }
75 0 : break;
76 : case NICE_BACKGROUND: {
77 : struct thread_precedence_policy tppolicy;
78 0 : tppolicy.importance = 0; /* IDLE_PRI */
79 0 : kr = thread_policy_set(mthread, THREAD_PRECEDENCE_POLICY,
80 : (thread_policy_t)&tppolicy,
81 : THREAD_PRECEDENCE_POLICY_COUNT);
82 : }
83 0 : break;
84 : case NICE_NORMAL: {
85 : struct thread_standard_policy tspolicy;
86 0 : kr = thread_policy_set(mthread, THREAD_STANDARD_POLICY,
87 : (thread_policy_t)&tspolicy,
88 : THREAD_STANDARD_POLICY_COUNT);
89 : }
90 0 : break;
91 : default:
92 0 : NaClLog(LOG_WARNING, "nacl_thread_nice() failed (bad nice value).\n");
93 0 : return -1;
94 : break;
95 : }
96 0 : if (kr != KERN_SUCCESS) {
97 0 : NaClLog(LOG_WARNING, "nacl_thread_nice() failed.\n");
98 0 : return -1;
99 : } else {
100 0 : return 0;
101 : }
102 : }
|