1/* 2 * Copyright (c) 2000-2007 Apple 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 * @OSF_COPYRIGHT@ 30 * 31 */ 32 33/* The routines in this module are all obsolete */ 34 35#include <mach/boolean.h> 36#include <mach/thread_switch.h> 37#include <ipc/ipc_port.h> 38#include <ipc/ipc_space.h> 39#include <kern/ipc_kobject.h> 40#include <kern/processor.h> 41#include <kern/sched.h> 42#include <kern/sched_prim.h> 43#include <kern/spl.h> 44#include <kern/task.h> 45#include <kern/thread.h> 46#include <mach/policy.h> 47 48#include <kern/syscall_subr.h> 49#include <mach/mach_host_server.h> 50#include <mach/mach_syscalls.h> 51 52#include <kern/misc_protos.h> 53#include <kern/spl.h> 54#include <kern/sched.h> 55#include <kern/sched_prim.h> 56#include <kern/assert.h> 57#include <kern/thread.h> 58#include <mach/mach_host_server.h> 59#include <mach/thread_act_server.h> 60#include <mach/host_priv_server.h> 61 62 63/* 64 * thread_set_policy 65 * 66 * Set scheduling policy and parameters, both base and limit, for 67 * the given thread. Policy can be any policy implemented by the 68 * processor set, whether enabled or not. 69 */ 70kern_return_t 71thread_set_policy( 72 thread_t thread, 73 processor_set_t pset, 74 policy_t policy, 75 policy_base_t base, 76 mach_msg_type_number_t base_count, 77 policy_limit_t limit, 78 mach_msg_type_number_t limit_count) 79{ 80 int max, bas; 81 kern_return_t result = KERN_SUCCESS; 82 83 if ( thread == THREAD_NULL || 84 pset == PROCESSOR_SET_NULL || pset != &pset0) 85 return (KERN_INVALID_ARGUMENT); 86 87 if (invalid_policy(policy)) 88 return(KERN_INVALID_ARGUMENT); 89 90 thread_mtx_lock(thread); 91 92 switch (policy) { 93 94 case POLICY_RR: 95 { 96 policy_rr_base_t rr_base = (policy_rr_base_t) base; 97 policy_rr_limit_t rr_limit = (policy_rr_limit_t) limit; 98 99 if ( base_count != POLICY_RR_BASE_COUNT || 100 limit_count != POLICY_RR_LIMIT_COUNT ) { 101 result = KERN_INVALID_ARGUMENT; 102 break; 103 } 104 105 bas = rr_base->base_priority; 106 max = rr_limit->max_priority; 107 if (invalid_pri(bas) || invalid_pri(max)) { 108 result = KERN_INVALID_ARGUMENT; 109 break; 110 } 111 112 break; 113 } 114 115 case POLICY_FIFO: 116 { 117 policy_fifo_base_t fifo_base = (policy_fifo_base_t) base; 118 policy_fifo_limit_t fifo_limit = (policy_fifo_limit_t) limit; 119 120 if ( base_count != POLICY_FIFO_BASE_COUNT || 121 limit_count != POLICY_FIFO_LIMIT_COUNT) { 122 result = KERN_INVALID_ARGUMENT; 123 break; 124 } 125 126 bas = fifo_base->base_priority; 127 max = fifo_limit->max_priority; 128 if (invalid_pri(bas) || invalid_pri(max)) { 129 result = KERN_INVALID_ARGUMENT; 130 break; 131 } 132 133 break; 134 } 135 136 case POLICY_TIMESHARE: 137 { 138 policy_timeshare_base_t ts_base = (policy_timeshare_base_t) base; 139 policy_timeshare_limit_t ts_limit = 140 (policy_timeshare_limit_t) limit; 141 142 if ( base_count != POLICY_TIMESHARE_BASE_COUNT || 143 limit_count != POLICY_TIMESHARE_LIMIT_COUNT ) { 144 result = KERN_INVALID_ARGUMENT; 145 break; 146 } 147 148 bas = ts_base->base_priority; 149 max = ts_limit->max_priority; 150 if (invalid_pri(bas) || invalid_pri(max)) { 151 result = KERN_INVALID_ARGUMENT; 152 break; 153 } 154 155 break; 156 } 157 158 default: 159 result = KERN_INVALID_POLICY; 160 } 161 162 if (result != KERN_SUCCESS) { 163 thread_mtx_unlock(thread); 164 165 return (result); 166 } 167 168 /* Note that we do not pass on max priority. */ 169 if (result == KERN_SUCCESS) { 170 result = thread_set_mode_and_absolute_pri(thread, policy, bas); 171 } 172 173 thread_mtx_unlock(thread); 174 175 return (result); 176} 177 178 179/* 180 * thread_policy 181 * 182 * Set scheduling policy and parameters, both base and limit, for 183 * the given thread. Policy must be a policy which is enabled for the 184 * processor set. Change contained threads if requested. 185 */ 186kern_return_t 187thread_policy( 188 thread_t thread, 189 policy_t policy, 190 policy_base_t base, 191 mach_msg_type_number_t count, 192 boolean_t set_limit) 193{ 194 kern_return_t result = KERN_SUCCESS; 195 processor_set_t pset = &pset0; 196 policy_limit_t limit = NULL; 197 int limcount = 0; 198 policy_rr_limit_data_t rr_limit; 199 policy_fifo_limit_data_t fifo_limit; 200 policy_timeshare_limit_data_t ts_limit; 201 202 if (thread == THREAD_NULL) 203 return (KERN_INVALID_ARGUMENT); 204 205 thread_mtx_lock(thread); 206 207 if ( invalid_policy(policy) || 208 ((POLICY_TIMESHARE | POLICY_RR | POLICY_FIFO) & policy) == 0 ) { 209 thread_mtx_unlock(thread); 210 211 return (KERN_INVALID_POLICY); 212 } 213 214 if (set_limit) { 215 /* 216 * Set scheduling limits to base priority. 217 */ 218 switch (policy) { 219 220 case POLICY_RR: 221 { 222 policy_rr_base_t rr_base; 223 224 if (count != POLICY_RR_BASE_COUNT) { 225 result = KERN_INVALID_ARGUMENT; 226 break; 227 } 228 229 limcount = POLICY_RR_LIMIT_COUNT; 230 rr_base = (policy_rr_base_t) base; 231 rr_limit.max_priority = rr_base->base_priority; 232 limit = (policy_limit_t) &rr_limit; 233 234 break; 235 } 236 237 case POLICY_FIFO: 238 { 239 policy_fifo_base_t fifo_base; 240 241 if (count != POLICY_FIFO_BASE_COUNT) { 242 result = KERN_INVALID_ARGUMENT; 243 break; 244 } 245 246 limcount = POLICY_FIFO_LIMIT_COUNT; 247 fifo_base = (policy_fifo_base_t) base; 248 fifo_limit.max_priority = fifo_base->base_priority; 249 limit = (policy_limit_t) &fifo_limit; 250 251 break; 252 } 253 254 case POLICY_TIMESHARE: 255 { 256 policy_timeshare_base_t ts_base; 257 258 if (count != POLICY_TIMESHARE_BASE_COUNT) { 259 result = KERN_INVALID_ARGUMENT; 260 break; 261 } 262 263 limcount = POLICY_TIMESHARE_LIMIT_COUNT; 264 ts_base = (policy_timeshare_base_t) base; 265 ts_limit.max_priority = ts_base->base_priority; 266 limit = (policy_limit_t) &ts_limit; 267 268 break; 269 } 270 271 default: 272 result = KERN_INVALID_POLICY; 273 break; 274 } 275 276 } 277 else { 278 /* 279 * Use current scheduling limits. Ensure that the 280 * new base priority will not exceed current limits. 281 */ 282 switch (policy) { 283 284 case POLICY_RR: 285 { 286 policy_rr_base_t rr_base; 287 288 if (count != POLICY_RR_BASE_COUNT) { 289 result = KERN_INVALID_ARGUMENT; 290 break; 291 } 292 293 limcount = POLICY_RR_LIMIT_COUNT; 294 rr_base = (policy_rr_base_t) base; 295 if (rr_base->base_priority > thread->max_priority) { 296 result = KERN_POLICY_LIMIT; 297 break; 298 } 299 300 rr_limit.max_priority = thread->max_priority; 301 limit = (policy_limit_t) &rr_limit; 302 303 break; 304 } 305 306 case POLICY_FIFO: 307 { 308 policy_fifo_base_t fifo_base; 309 310 if (count != POLICY_FIFO_BASE_COUNT) { 311 result = KERN_INVALID_ARGUMENT; 312 break; 313 } 314 315 limcount = POLICY_FIFO_LIMIT_COUNT; 316 fifo_base = (policy_fifo_base_t) base; 317 if (fifo_base->base_priority > thread->max_priority) { 318 result = KERN_POLICY_LIMIT; 319 break; 320 } 321 322 fifo_limit.max_priority = thread->max_priority; 323 limit = (policy_limit_t) &fifo_limit; 324 325 break; 326 } 327 328 case POLICY_TIMESHARE: 329 { 330 policy_timeshare_base_t ts_base; 331 332 if (count != POLICY_TIMESHARE_BASE_COUNT) { 333 result = KERN_INVALID_ARGUMENT; 334 break; 335 } 336 337 limcount = POLICY_TIMESHARE_LIMIT_COUNT; 338 ts_base = (policy_timeshare_base_t) base; 339 if (ts_base->base_priority > thread->max_priority) { 340 result = KERN_POLICY_LIMIT; 341 break; 342 } 343 344 ts_limit.max_priority = thread->max_priority; 345 limit = (policy_limit_t) &ts_limit; 346 347 break; 348 } 349 350 default: 351 result = KERN_INVALID_POLICY; 352 break; 353 } 354 355 } 356 357 thread_mtx_unlock(thread); 358 359 if (result == KERN_SUCCESS) 360 result = thread_set_policy(thread, pset, 361 policy, base, count, limit, limcount); 362 363 return(result); 364} 365