Added support for showing the I/O priority
[iotop.git] / iotop / ioprio.py
blob4e961d9a9e5f734ce5b177818d083648efc47db5
1 import ctypes
2 import fnmatch
3 import os
4 import time
6 # From http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git;a=blob;
7 # f=configure.ac;h=770eb45ae85d32757fc3cff1d70a7808a627f9f7;hb=HEAD#l363
8 IOPRIO_GET_ARCH_SYSCALL = [
9 ('alpha', 443),
10 ('i*86', 290),
11 ('ia64*', 1275),
12 ('powerpc*', 274),
13 ('s390*', 283),
14 ('sparc*', 218),
15 ('sh*', 289),
16 ('x86_64*', 252),
19 def find_ioprio_get_syscall_number():
20 arch = os.uname()[4]
22 for candidate_arch, syscall_nr in IOPRIO_GET_ARCH_SYSCALL:
23 if fnmatch.fnmatch(arch, candidate_arch):
24 return syscall_nr
27 __NR_ioprio_get = find_ioprio_get_syscall_number()
28 ctypes_handle = ctypes.CDLL(None)
29 syscall = ctypes_handle.syscall
31 PRIORITY_CLASSES = (None, 'rt', 'be', 'idle')
33 WHO_PROCESS = 1
34 IOPRIO_CLASS_SHIFT = 13
35 IOPRIO_PRIO_MASK = (1 << IOPRIO_CLASS_SHIFT) - 1
37 def ioprio_class(ioprio):
38 return PRIORITY_CLASSES[ioprio >> IOPRIO_CLASS_SHIFT]
40 def ioprio_data(ioprio):
41 return ioprio & IOPRIO_PRIO_MASK
43 sched_getscheduler = ctypes_handle.sched_getscheduler
44 SCHED_OTHER, SCHED_FIFO, SCHED_RR, SCHED_BATCH, SCHED_ISO, SCHED_IDLE = range(6)
46 def get_ioprio_from_sched(pid):
47 scheduler = sched_getscheduler(pid)
48 nice = int(open('/proc/%d/stat' % pid).read().split()[18])
49 ioprio_nice = (nice + 20) / 5
51 if scheduler in (SCHED_FIFO, SCHED_RR):
52 return 'rt/%d' % ioprio_nice
53 elif scheduler == SCHED_IDLE:
54 return 'idle'
55 else:
56 return 'be/%d' % ioprio_nice
58 def get(pid):
59 if __NR_ioprio_get is None:
60 return '?sys'
62 ioprio = syscall(__NR_ioprio_get, WHO_PROCESS, pid)
63 if ioprio < 0:
64 return '?err'
66 prio_class = ioprio_class(ioprio)
67 if not prio_class:
68 return get_ioprio_from_sched(pid)
69 if prio_class == 'idle':
70 return prio_class
71 return '%s/%d' % (prio_class, ioprio_data(ioprio))
73 def sort_key(key):
74 if key[0] == '?':
75 return -ord(key[1])
77 if '/' in key:
78 if key.startswith('rt/'):
79 shift = 0
80 elif key.startswith('be/'):
81 shift = 1
82 prio = int(key.split('/')[1])
83 elif key == 'idle':
84 shift = 2
85 prio = 0
87 return (1 << (shift * IOPRIO_CLASS_SHIFT)) + prio
89 if __name__ == '__main__':
90 import sys
91 if len(sys.argv) == 2:
92 pid = int(sys.argv[1])
93 else:
94 pid = os.getpid()
95 print 'pid:', pid
96 print 'ioprio:', get(pid)