]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/task_policy.c
xnu-1504.9.26.tar.gz
[apple/xnu.git] / osfmk / kern / task_policy.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <mach/mach_types.h>
30 #include <mach/task_server.h>
31
32 #include <kern/sched.h>
33 #include <kern/task.h>
34
35 static void
36 task_priority(
37 task_t task,
38 integer_t priority,
39 integer_t max_priority);
40
41 kern_return_t
42 task_policy_set(
43 task_t task,
44 task_policy_flavor_t flavor,
45 task_policy_t policy_info,
46 mach_msg_type_number_t count)
47 {
48 kern_return_t result = KERN_SUCCESS;
49
50 if (task == TASK_NULL || task == kernel_task)
51 return (KERN_INVALID_ARGUMENT);
52
53 switch (flavor) {
54
55 case TASK_CATEGORY_POLICY:
56 {
57 task_category_policy_t info = (task_category_policy_t)policy_info;
58
59 if (count < TASK_CATEGORY_POLICY_COUNT)
60 return (KERN_INVALID_ARGUMENT);
61
62 task_lock(task);
63
64 if ( info->role == TASK_FOREGROUND_APPLICATION ||
65 info->role == TASK_BACKGROUND_APPLICATION ) {
66 switch (task->role) {
67
68 case TASK_FOREGROUND_APPLICATION:
69 case TASK_BACKGROUND_APPLICATION:
70 case TASK_UNSPECIFIED:
71 task_priority(task,
72 ((info->role == TASK_FOREGROUND_APPLICATION)?
73 BASEPRI_FOREGROUND: BASEPRI_BACKGROUND),
74 task->max_priority);
75 task->role = info->role;
76 break;
77
78 case TASK_CONTROL_APPLICATION:
79 case TASK_RENICED:
80 /* fail silently */
81 break;
82
83 default:
84 result = KERN_INVALID_ARGUMENT;
85 break;
86 }
87 }
88 else
89 if (info->role == TASK_CONTROL_APPLICATION) {
90 if ( task != current_task() ||
91 task->sec_token.val[0] != 0 )
92 result = KERN_INVALID_ARGUMENT;
93 else {
94 task_priority(task, BASEPRI_CONTROL, task->max_priority);
95 task->role = info->role;
96 }
97 }
98 else
99 if (info->role == TASK_GRAPHICS_SERVER) {
100 if ( task != current_task() ||
101 task->sec_token.val[0] != 0 )
102 result = KERN_INVALID_ARGUMENT;
103 else {
104 task_priority(task, MAXPRI_RESERVED - 3, MAXPRI_RESERVED);
105 task->role = info->role;
106 }
107 }
108 else
109 if (info->role == TASK_THROTTLE_APPLICATION) {
110 task_priority(task, MAXPRI_THROTTLE, MAXPRI_THROTTLE);
111 task->role = info->role;
112 }
113 else
114 if (info->role == TASK_DEFAULT_APPLICATION) {
115 task_priority(task, BASEPRI_DEFAULT, MAXPRI_USER);
116 task->role = info->role;
117 }
118 else
119 result = KERN_INVALID_ARGUMENT;
120
121 task_unlock(task);
122
123 break;
124 }
125
126 default:
127 result = KERN_INVALID_ARGUMENT;
128 break;
129 }
130
131 return (result);
132 }
133
134 static void
135 task_priority(
136 task_t task,
137 integer_t priority,
138 integer_t max_priority)
139 {
140 thread_t thread;
141
142 task->max_priority = max_priority;
143
144 if (priority > task->max_priority)
145 priority = task->max_priority;
146 else
147 if (priority < MINPRI)
148 priority = MINPRI;
149
150 task->priority = priority;
151
152 queue_iterate(&task->threads, thread, thread_t, task_threads) {
153 thread_mtx_lock(thread);
154
155 if (thread->active)
156 thread_task_priority(thread, priority, max_priority);
157
158 thread_mtx_unlock(thread);
159 }
160 }
161
162 kern_return_t
163 task_importance(
164 task_t task,
165 integer_t importance)
166 {
167 if (task == TASK_NULL || task == kernel_task)
168 return (KERN_INVALID_ARGUMENT);
169
170 task_lock(task);
171
172 if (!task->active) {
173 task_unlock(task);
174
175 return (KERN_TERMINATED);
176 }
177
178 if (task->role >= TASK_CONTROL_APPLICATION) {
179 task_unlock(task);
180
181 return (KERN_INVALID_ARGUMENT);
182 }
183
184 task_priority(task, importance + BASEPRI_DEFAULT, task->max_priority);
185 task->role = TASK_RENICED;
186
187 task_unlock(task);
188
189 return (KERN_SUCCESS);
190 }
191
192 kern_return_t
193 task_policy_get(
194 task_t task,
195 task_policy_flavor_t flavor,
196 task_policy_t policy_info,
197 mach_msg_type_number_t *count,
198 boolean_t *get_default)
199 {
200 if (task == TASK_NULL || task == kernel_task)
201 return (KERN_INVALID_ARGUMENT);
202
203 switch (flavor) {
204
205 case TASK_CATEGORY_POLICY:
206 {
207 task_category_policy_t info = (task_category_policy_t)policy_info;
208
209 if (*count < TASK_CATEGORY_POLICY_COUNT)
210 return (KERN_INVALID_ARGUMENT);
211
212 if (*get_default)
213 info->role = TASK_UNSPECIFIED;
214 else {
215 task_lock(task);
216 info->role = task->role;
217 task_unlock(task);
218 }
219 break;
220 }
221
222 default:
223 return (KERN_INVALID_ARGUMENT);
224 }
225
226 return (KERN_SUCCESS);
227 }