1/* 2 * Copyright (c) 2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.0 (the 'License'). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License." 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <unistd.h> 28#include <string.h> 29#include <sys/resource.h> 30#include <err.h> 31#include <sys/errno.h> 32#include <stdbool.h> 33#include <sysexits.h> 34#include <mach/mach.h> 35#include <mach/task_policy.h> 36 37#define QOS_PARAMETER_LATENCY 0 38#define QOS_PARAMETER_THROUGHPUT 1 39 40static void usage(void); 41static int parse_disk_policy(const char *strpolicy); 42static int parse_qos_tier(const char *strpolicy, int parameter); 43 44int main(int argc, char * argv[]) 45{ 46 int ch, ret; 47 bool flagx = false, flagX = false, flagb = false; 48 int flagd = -1, flagg = -1; 49 struct task_qos_policy qosinfo = { LATENCY_QOS_TIER_UNSPECIFIED, THROUGHPUT_QOS_TIER_UNSPECIFIED }; 50 51 while ((ch = getopt(argc, argv, "xXbd:g:t:l:")) != -1) { 52 switch (ch) { 53 case 'x': 54 flagx = true; 55 break; 56 case 'X': 57 flagX = true; 58 break; 59 case 'b': 60 flagb = true; 61 break; 62 case 'd': 63 flagd = parse_disk_policy(optarg); 64 if (flagd == -1) { 65 warnx("Could not parse '%s' as a disk policy", optarg); 66 usage(); 67 } 68 break; 69 case 'g': 70 flagg = parse_disk_policy(optarg); 71 if (flagg == -1) { 72 warnx("Could not parse '%s' as a disk policy", optarg); 73 usage(); 74 } 75 break; 76 case 't': 77 qosinfo.task_throughput_qos_tier = parse_qos_tier(optarg, QOS_PARAMETER_THROUGHPUT); 78 if (qosinfo.task_throughput_qos_tier == -1) { 79 warnx("Could not parse '%s' as a qos tier", optarg); 80 usage(); 81 } 82 break; 83 case 'l': 84 qosinfo.task_latency_qos_tier = parse_qos_tier(optarg, QOS_PARAMETER_LATENCY); 85 if (qosinfo.task_latency_qos_tier == -1) { 86 warnx("Could not parse '%s' as a qos tier", optarg); 87 usage(); 88 } 89 break; 90 case '?': 91 default: 92 usage(); 93 } 94 } 95 argc -= optind; 96 argv += optind; 97 98 if (argc == 0) { 99 usage(); 100 } 101 102 if (flagx && flagX){ 103 warnx("Incompatible options -x, -X"); 104 usage(); 105 } 106 107 if (flagx) { 108 ret = setiopolicy_np(IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY, IOPOL_SCOPE_PROCESS, IOPOL_VFS_HFS_CASE_SENSITIVITY_FORCE_CASE_SENSITIVE); 109 if (ret == -1) { 110 err(EX_SOFTWARE, "setiopolicy_np(IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY...)"); 111 } 112 } 113 114 if (flagX) { 115 ret = setiopolicy_np(IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY, IOPOL_SCOPE_PROCESS, IOPOL_VFS_HFS_CASE_SENSITIVITY_DEFAULT); 116 if (ret == -1) { 117 err(EX_SOFTWARE, "setiopolicy_np(IOPOL_TYPE_VFS_HFS_CASE_SENSITIVITY...)"); 118 } 119 } 120 121 if (flagb) { 122 ret = setpriority(PRIO_DARWIN_PROCESS, 0, PRIO_DARWIN_BG); 123 if (ret == -1) { 124 err(EX_SOFTWARE, "setpriority()"); 125 } 126 } 127 128 if (flagd >= 0) { 129 ret = setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, flagd); 130 if (ret == -1) { 131 err(EX_SOFTWARE, "setiopolicy_np(...IOPOL_SCOPE_PROCESS...)"); 132 } 133 } 134 135 if (flagg >= 0){ 136 ret = setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_DARWIN_BG, flagg); 137 if (ret == -1) { 138 err(EX_SOFTWARE, "setiopolicy_np(...IOPOL_SCOPE_DARWIN_BG...)"); 139 } 140 } 141 142 if (qosinfo.task_latency_qos_tier != LATENCY_QOS_TIER_UNSPECIFIED || 143 qosinfo.task_throughput_qos_tier != THROUGHPUT_QOS_TIER_UNSPECIFIED){ 144 ret = task_policy_set(mach_task_self(), TASK_OVERRIDE_QOS_POLICY, (task_policy_t)&qosinfo, TASK_QOS_POLICY_COUNT); 145 if (ret != KERN_SUCCESS){ 146 err(EX_SOFTWARE, "task_policy_set(...TASK_OVERRIDE_QOS_POLICY...)"); 147 } 148 } 149 150 ret = execvp(argv[0], argv); 151 if (ret == -1) { 152 err(EX_NOINPUT, "Could not execute %s", argv[0]); 153 } 154 155 return EX_OSERR; 156} 157 158static void usage(void) 159{ 160 fprintf(stderr, "Usage: %s [-x|-X] [-d <policy>] [-g policy] [-b] [-t <tier>] [-l <tier>] <program> [<pargs> [...]]\n", getprogname()); 161 exit(EX_USAGE); 162} 163 164static int parse_disk_policy(const char *strpolicy) 165{ 166 long policy; 167 char *endptr = NULL; 168 169 /* first try as an integer */ 170 policy = strtol(strpolicy, &endptr, 0); 171 if (endptr && (endptr[0] == '\0') && (strpolicy[0] != '\0')) { 172 /* parsed complete string as a number */ 173 return (int)policy; 174 } 175 176 if (0 == strcasecmp(strpolicy, "DEFAULT") ) { 177 return IOPOL_DEFAULT; 178 } else if (0 == strcasecmp(strpolicy, "IMPORTANT")) { 179 return IOPOL_IMPORTANT; 180 } else if (0 == strcasecmp(strpolicy, "PASSIVE")) { 181 return IOPOL_PASSIVE; 182 } else if (0 == strcasecmp(strpolicy, "THROTTLE")) { 183 return IOPOL_THROTTLE; 184 } else if (0 == strcasecmp(strpolicy, "UTILITY")) { 185 return IOPOL_UTILITY; 186 } else if (0 == strcasecmp(strpolicy, "STANDARD")) { 187 return IOPOL_STANDARD; 188 } else { 189 return -1; 190 } 191} 192 193static int parse_qos_tier(const char *strtier, int parameter){ 194 long policy; 195 char *endptr = NULL; 196 197 /* first try as an integer */ 198 policy = strtol(strtier, &endptr, 0); 199 if (endptr && (endptr[0] == '\0') && (strtier[0] != '\0')) { 200 switch (policy) { 201 case 0: 202 return parameter ? THROUGHPUT_QOS_TIER_0 : LATENCY_QOS_TIER_0; 203 break; 204 case 1: 205 return parameter ? THROUGHPUT_QOS_TIER_1 : LATENCY_QOS_TIER_1; 206 break; 207 case 2: 208 return parameter ? THROUGHPUT_QOS_TIER_2 : LATENCY_QOS_TIER_2; 209 break; 210 case 3: 211 return parameter ? THROUGHPUT_QOS_TIER_3 : LATENCY_QOS_TIER_3; 212 break; 213 case 4: 214 return parameter ? THROUGHPUT_QOS_TIER_4 : LATENCY_QOS_TIER_4; 215 break; 216 case 5: 217 return parameter ? THROUGHPUT_QOS_TIER_5 : LATENCY_QOS_TIER_5; 218 break; 219 default: 220 return -1; 221 break; 222 } 223 } 224 225 return -1; 226} 227