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