]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/task_policy.c
xnu-792.21.3.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 result = KERN_INVALID_ARGUMENT;
110
111 task_unlock(task);
112
113 break;
114 }
115
116 default:
117 result = KERN_INVALID_ARGUMENT;
118 break;
119 }
120
121 return (result);
122 }
123
124 static void
125 task_priority(
126 task_t task,
127 integer_t priority,
128 integer_t max_priority)
129 {
130 thread_t thread;
131
132 task->max_priority = max_priority;
133
134 if (priority > task->max_priority)
135 priority = task->max_priority;
136 else
137 if (priority < MINPRI)
138 priority = MINPRI;
139
140 task->priority = priority;
141
142 queue_iterate(&task->threads, thread, thread_t, task_threads) {
143 thread_mtx_lock(thread);
144
145 if (thread->active)
146 thread_task_priority(thread, priority, max_priority);
147
148 thread_mtx_unlock(thread);
149 }
150 }
151
152 kern_return_t
153 task_importance(
154 task_t task,
155 integer_t importance)
156 {
157 if (task == TASK_NULL || task == kernel_task)
158 return (KERN_INVALID_ARGUMENT);
159
160 task_lock(task);
161
162 if (!task->active) {
163 task_unlock(task);
164
165 return (KERN_TERMINATED);
166 }
167
168 if (task->role >= TASK_CONTROL_APPLICATION) {
169 task_unlock(task);
170
171 return (KERN_INVALID_ARGUMENT);
172 }
173
174 task_priority(task, importance + BASEPRI_DEFAULT, task->max_priority);
175 task->role = TASK_RENICED;
176
177 task_unlock(task);
178
179 return (KERN_SUCCESS);
180 }
181
182 kern_return_t
183 task_policy_get(
184 task_t task,
185 task_policy_flavor_t flavor,
186 task_policy_t policy_info,
187 mach_msg_type_number_t *count,
188 boolean_t *get_default)
189 {
190 if (task == TASK_NULL || task == kernel_task)
191 return (KERN_INVALID_ARGUMENT);
192
193 switch (flavor) {
194
195 case TASK_CATEGORY_POLICY:
196 {
197 task_category_policy_t info = (task_category_policy_t)policy_info;
198
199 if (*count < TASK_CATEGORY_POLICY_COUNT)
200 return (KERN_INVALID_ARGUMENT);
201
202 if (*get_default)
203 info->role = TASK_UNSPECIFIED;
204 else {
205 task_lock(task);
206 info->role = task->role;
207 task_unlock(task);
208 }
209 break;
210 }
211
212 default:
213 return (KERN_INVALID_ARGUMENT);
214 }
215
216 return (KERN_SUCCESS);
217 }