]> git.saurik.com Git - apple/libpthread.git/blob - tests/qos.c
libpthread-301.1.6.tar.gz
[apple/libpthread.git] / tests / qos.c
1 /*% clang -o # -Wall -Wextra -I/System/Library/Frameworks/System.framework/PrivateHeaders %
2 */
3
4 #include <assert.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <stdbool.h>
8
9 #include <sys/qos.h>
10 #include <sys/resource.h>
11 #include <pthread.h>
12
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>
21
22 #define QOS_TIER(i) \
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 : \
30 -1)
31
32 struct kern_qos {
33 long requested;
34 long override;
35 };
36
37 void get_kern_qos(struct kern_qos *kern_qos){
38 kern_return_t kr;
39 boolean_t get_default = false;
40 mach_msg_type_number_t count;
41
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); }
46
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);
49 }
50
51 void assert_fixedpri(bool fixedpri){
52 kern_return_t kr;
53 boolean_t get_default = false;
54 mach_msg_type_number_t count;
55
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); }
60
61 assert(extpol.timeshare == !fixedpri);
62 }
63
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;
67
68 get_kern_qos(&actual_kern_qos);
69
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);
73
74 return NULL;
75 }
76
77 void *fixedpri_test(void *arg){
78 struct kern_qos *correct_kern_qos = (struct kern_qos *)arg;
79
80 assert_thread_qos(correct_kern_qos);
81 assert_fixedpri(false);
82
83 pthread_set_fixedpriority_self();
84
85 assert_thread_qos(correct_kern_qos);
86 assert_fixedpri(true);
87
88 pthread_set_timeshare_self();
89
90 assert_thread_qos(correct_kern_qos);
91 assert_fixedpri(false);
92
93 return NULL;
94 }
95
96 int main(){
97 if (geteuid() != 0){
98 printf("Must be run as root\n");
99 return 1;
100 }
101
102 struct kern_qos kern_qos;
103
104 pthread_t thread;
105 pthread_attr_t attr;
106 pthread_attr_init(&attr);
107
108 // Main thread QoS
109
110 kern_qos.requested = qos_class_self();
111 kern_qos.override = QOS_CLASS_UNSPECIFIED;
112
113 assert_thread_qos(&kern_qos);
114 assert(qos_class_self() == qos_class_main());
115
116 // Created pthread
117
118 kern_qos.requested = QOS_CLASS_UTILITY;
119 kern_qos.override = QOS_CLASS_UNSPECIFIED;
120
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);
124
125 // pthread_set_fixedpriority_self()
126
127 kern_qos.requested = QOS_CLASS_USER_INITIATED;
128 kern_qos.override = QOS_CLASS_UNSPECIFIED;
129
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);
133
134 return 0;
135 }