| 1216 | /** \brief Allows setting the I/O priority of the current process/thread. |
| 1217 | * |
| 1218 | * As of November 14th, 2010 this only works on Linux when using the CFQ |
| 1219 | * I/O Scheduler. The range is -1 to 8, with -1 being real-time priority |
| 1220 | * 0 through 7 being standard best-time priorities and 8 being the idle |
| 1221 | * priority. The deadline and noop I/O Schedulers will ignore this but |
| 1222 | * are much less likely to starve video playback to feed the transcoder |
| 1223 | * or flagger. (noop is only recommended for SSDs.) |
| 1224 | * |
| 1225 | * Since a process needs to have elevated priviledges to use either the |
| 1226 | * real-time or idle priority this will try priorities 0 or 7 respectively |
| 1227 | * if -1 or 8 do not work. It will not report an error on these conditions |
| 1228 | * as they will be the common case. |
| 1229 | * |
| 1230 | * Only Linux on i386, ppc, x86_64 and ia64 are currently supported. |
| 1231 | * This is a no-op on all other architectures and platforms. |
| 1232 | */ |
| 1233 | #if defined(__linux__) && ( defined(__i386__) || defined(__ppc__) || \ |
| 1234 | defined(__x86_64__) || defined(__ia64__) ) |
| 1235 | |
| 1236 | #include <stdio.h> |
| 1237 | #include <stdlib.h> |
| 1238 | #include <errno.h> |
| 1239 | #include <getopt.h> |
| 1240 | #include <unistd.h> |
| 1241 | #include <sys/ptrace.h> |
| 1242 | #include <asm/unistd.h> |
| 1243 | |
| 1244 | #if defined(__i386__) |
| 1245 | # define __NR_ioprio_set 289 |
| 1246 | # define __NR_ioprio_get 290 |
| 1247 | #elif defined(__ppc__) |
| 1248 | # define __NR_ioprio_set 273 |
| 1249 | # define __NR_ioprio_get 274 |
| 1250 | #elif defined(__x86_64__) |
| 1251 | # define __NR_ioprio_set 251 |
| 1252 | # define __NR_ioprio_get 252 |
| 1253 | #elif defined(__ia64__) |
| 1254 | # define __NR_ioprio_set 1274 |
| 1255 | # define __NR_ioprio_get 1275 |
| 1256 | #endif |
| 1257 | |
| 1258 | #define IOPRIO_BITS (16) |
| 1259 | #define IOPRIO_CLASS_SHIFT (13) |
| 1260 | #define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) |
| 1261 | #define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) |
| 1262 | #define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) |
| 1263 | #define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) |
| 1264 | |
| 1265 | enum { IOPRIO_CLASS_NONE,IOPRIO_CLASS_RT,IOPRIO_CLASS_BE,IOPRIO_CLASS_IDLE, }; |
| 1266 | enum { IOPRIO_WHO_PROCESS = 1, IOPRIO_WHO_PGRP, IOPRIO_WHO_USER, }; |
| 1267 | |
| 1268 | bool myth_ioprio(int val) |
| 1269 | { |
| 1270 | int new_ioclass = (val < 0) ? IOPRIO_CLASS_RT : |
| 1271 | (val > 7) ? IOPRIO_CLASS_IDLE : IOPRIO_CLASS_BE; |
| 1272 | int new_iodata = (new_ioclass == IOPRIO_CLASS_BE) ? val : 0; |
| 1273 | int new_ioprio = IOPRIO_PRIO_VALUE(new_ioclass, new_iodata); |
| 1274 | |
| 1275 | int pid = getpid(); |
| 1276 | int old_ioprio = syscall(__NR_ioprio_get, IOPRIO_WHO_PROCESS, pid); |
| 1277 | if (old_ioprio == new_ioprio) |
| 1278 | return true; |
| 1279 | |
| 1280 | int ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS, pid, new_ioprio); |
| 1281 | |
| 1282 | if (-1 == ret && EPERM == errno && IOPRIO_CLASS_BE != new_ioclass) |
| 1283 | { |
| 1284 | new_iodata = (new_ioclass == IOPRIO_CLASS_RT) ? 0 : 7; |
| 1285 | new_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, new_iodata); |
| 1286 | ret = syscall(__NR_ioprio_set, IOPRIO_WHO_PROCESS, pid, new_ioprio); |
| 1287 | } |
| 1288 | |
| 1289 | return 0 == ret; |
| 1290 | } |
| 1291 | |
| 1292 | #else |
| 1293 | |
| 1294 | bool myth_ioprio(int) { return true; } |
| 1295 | |
| 1296 | #endif |
| 1297 | |