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