1 /*% clang -o # -Wall -Wextra -I/System/Library/Frameworks/System.framework/PrivateHeaders %
10 #include <sys/resource.h>
13 #include <mach/mach.h>
14 #include <mach/host_info.h>
15 #include <mach/mach_error.h>
16 #include <mach/mach_types.h>
17 #include <mach/message.h>
18 #include <mach/mach_syscalls.h>
19 #include <mach/policy.h>
20 #include <mach/task_policy.h>
23 (((i) == THREAD_QOS_UNSPECIFIED) ? QOS_CLASS_UNSPECIFIED : \
24 ((i) == THREAD_QOS_USER_INTERACTIVE) ? QOS_CLASS_USER_INTERACTIVE : \
25 ((i) == THREAD_QOS_USER_INITIATED) ? QOS_CLASS_USER_INITIATED : \
26 ((i) == THREAD_QOS_LEGACY) ? QOS_CLASS_DEFAULT : \
27 ((i) == THREAD_QOS_UTILITY) ? QOS_CLASS_UTILITY : \
28 ((i) == THREAD_QOS_BACKGROUND) ? QOS_CLASS_BACKGROUND : \
29 ((i) == THREAD_QOS_MAINTENANCE) ? QOS_CLASS_MAINTENANCE : \
37 void get_kern_qos(struct kern_qos
*kern_qos
){
39 boolean_t get_default
= false;
40 mach_msg_type_number_t count
;
42 struct thread_policy_state thread_policy
;
43 count
= THREAD_POLICY_STATE_COUNT
;
44 kr
= thread_policy_get(mach_thread_self(), THREAD_POLICY_STATE
, (thread_policy_t
)&thread_policy
, &count
, &get_default
);
45 if (kr
!= KERN_SUCCESS
) { mach_error("thread_policy_get(... THREAD_POLICY_STATE ...)", kr
); }
47 kern_qos
->requested
= QOS_TIER((thread_policy
.requested
& POLICY_REQ_TH_QOS_MASK
) >> POLICY_REQ_TH_QOS_SHIFT
);
48 kern_qos
->override
= QOS_TIER((thread_policy
.requested
& POLICY_REQ_TH_QOS_OVER_MASK
) >> POLICY_REQ_TH_QOS_OVER_SHIFT
);
51 void assert_fixedpri(bool fixedpri
){
53 boolean_t get_default
= false;
54 mach_msg_type_number_t count
;
56 thread_extended_policy_data_t extpol
;
57 count
= THREAD_EXTENDED_POLICY_COUNT
;
58 kr
= thread_policy_get(mach_thread_self(), THREAD_EXTENDED_POLICY
, (thread_policy_t
)&extpol
, &count
, &get_default
);
59 if (kr
!= KERN_SUCCESS
) { mach_error("thread_policy_get(... THREAD_EXTENDED_POLICY ...)", kr
); }
61 assert(extpol
.timeshare
== !fixedpri
);
64 void *assert_thread_qos(void *arg
){
65 struct kern_qos
*correct_kern_qos
= (struct kern_qos
*)arg
;
66 struct kern_qos actual_kern_qos
;
68 get_kern_qos(&actual_kern_qos
);
70 assert(actual_kern_qos
.requested
== qos_class_self());
71 assert(actual_kern_qos
.requested
== correct_kern_qos
->requested
);
72 assert(actual_kern_qos
.override
== correct_kern_qos
->override
);
77 void *fixedpri_test(void *arg
){
78 struct kern_qos
*correct_kern_qos
= (struct kern_qos
*)arg
;
80 assert_thread_qos(correct_kern_qos
);
81 assert_fixedpri(false);
83 pthread_set_fixedpriority_self();
85 assert_thread_qos(correct_kern_qos
);
86 assert_fixedpri(true);
88 pthread_set_timeshare_self();
90 assert_thread_qos(correct_kern_qos
);
91 assert_fixedpri(false);
98 printf("Must be run as root\n");
102 struct kern_qos kern_qos
;
106 pthread_attr_init(&attr
);
110 kern_qos
.requested
= qos_class_self();
111 kern_qos
.override
= QOS_CLASS_UNSPECIFIED
;
113 assert_thread_qos(&kern_qos
);
114 assert(qos_class_self() == qos_class_main());
118 kern_qos
.requested
= QOS_CLASS_UTILITY
;
119 kern_qos
.override
= QOS_CLASS_UNSPECIFIED
;
121 pthread_attr_set_qos_class_np(&attr
, QOS_CLASS_UTILITY
, 0);
122 pthread_create(&thread
, &attr
, assert_thread_qos
, &kern_qos
);
123 pthread_join(thread
, NULL
);
125 // pthread_set_fixedpriority_self()
127 kern_qos
.requested
= QOS_CLASS_USER_INITIATED
;
128 kern_qos
.override
= QOS_CLASS_UNSPECIFIED
;
130 pthread_attr_set_qos_class_np(&attr
, QOS_CLASS_USER_INITIATED
, 0);
131 pthread_create(&thread
, &attr
, fixedpri_test
, &kern_qos
);
132 pthread_join(thread
, NULL
);