]> git.saurik.com Git - apple/system_cmds.git/blob - taskpolicy.tproj/taskpolicy.c
f1cbe5e254932bdcb7e5afac4ae31a3d3a2441bd
[apple/system_cmds.git] / taskpolicy.tproj / taskpolicy.c
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
40 static void usage(void);
41 static int parse_disk_policy(const char *strpolicy);
42 static int parse_qos_tier(const char *strpolicy, int parameter);
43
44 int 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
158 static 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
164 static 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
193 static 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 }