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 35static void 36task_priority( 37 task_t task, 38 integer_t priority, 39 integer_t max_priority); 40 41kern_return_t 42task_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 124static void 125task_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 152kern_return_t 153task_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 182kern_return_t 183task_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} 218