ragweed 0.1.7.3 → 0.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,18 +1,5 @@
1
1
  module Ragweed; end
2
2
  module Ragweed::Wraposx::ThreadInfo
3
- class << self
4
- #factory method to get a ThreadInfo variant
5
- def get(flavor,tid)
6
- found = false
7
- klass = self.constants.detect{|c| con = self.const_get(c); con.kind_of?(Class) && (flavor == con.const_get(:FLAVOR))}
8
- if klass.nil?
9
- raise Ragwed::Wraposx::KErrno::INVALID_ARGUMENT
10
- else
11
- klass.get(tid)
12
- end
13
- end
14
- end
15
-
16
3
  # info interfaces
17
4
  BASIC_INFO = 3 #basic information
18
5
 
@@ -22,17 +9,6 @@ module Ragweed::Wraposx::ThreadInfo
22
9
  SCHED_RR_INFO = 11
23
10
  # SCHED_FIFO_INFO = 12
24
11
 
25
- FLAVORS = {
26
- # define THREAD_BASIC_INFO_COUNT ((mach_msg_type_number_t)(sizeof(thread_basic_info_data_t) / sizeof(natural_t)))
27
- BASIC_INFO => {:size => 30, :count => 10},
28
- # define POLICY_TIMESHARE_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_timeshare_info)/sizeof(integer_t)))
29
- SCHED_TIMESHARE_INFO => {:size => 20, :count => 5},
30
- # define POLICY_RR_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_rr_info)/sizeof(integer_t)))
31
- SCHED_RR_INFO => {:size => 20,:count => 5},
32
- # define POLICY_FIFO_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_fifo_info)/sizeof(integer_t)))
33
- # SCHED_FIFO_INFO => {:size => 16,:count => 4} # immediately returns KERNEL_INVALID_POLICY on osx
34
- }
35
-
36
12
  module State
37
13
  #Thread run states
38
14
  RUNNING = 1 #/* thread is running normally */
@@ -42,46 +18,6 @@ module Ragweed::Wraposx::ThreadInfo
42
18
  HALTED = 5 #/* thread is halted at a clean point */
43
19
  end
44
20
 
45
- module ThreadInfoMixins
46
- def initialize(str=nil)
47
- refresh(str) if (str && !str.empty?)
48
- end
49
-
50
- # (re)loads the data from str
51
- def refresh(str)
52
- fields = self.class.const_get :FIELDS
53
- pp self.class
54
- if str and not str.empty?
55
- str.unpack(fields.map {|x| x[1]}.join("")).each_with_index do |val, i|
56
- raise "i is nil" if i.nil?
57
- instance_variable_set "@#{ fields[i][0] }".intern, val
58
- end
59
- end
60
- end
61
-
62
- def to_s
63
- fields = self.class.const_get :FIELDS
64
- fields.map {|f| send(f[0])}.pack(fields.map {|x| x[1]}.join(""))
65
- end
66
-
67
- def inspect
68
- body = lambda do
69
- self.class.const_get(:FIELDS).map do |f|
70
- "#{f[0]}=#{send(f[0]).to_s}"
71
- end.join(", ")
72
- end
73
- "#<#{self.class.name.split('::').last(2).join('::')} #{body.call}>"
74
- end
75
-
76
- def self.get(t)
77
- self.new(Ragweed::Wraposx::thread_info_raw(t, self.class.const_get(:FLAVOR)))
78
- end
79
-
80
- def get(t)
81
- refresh(Ragweed::Wraposx::vm_region_raw(t, self.class.const_get(:FLAVOR)))
82
- end
83
- end
84
-
85
21
  # struct thread_basic_info
86
22
  # {
87
23
  # time_value_t user_time;
@@ -93,35 +29,23 @@ module Ragweed::Wraposx::ThreadInfo
93
29
  # integer_t suspend_count;
94
30
  # integer_t sleep_time;
95
31
  # };
96
- class Basic
97
- include Ragweed::Wraposx::ThreadInfo::ThreadInfoMixins
32
+ class Basic < FFI::Struct
33
+ include Ragweed::FFIStructInclude
98
34
  module Flags
99
35
  #Thread flags (flags field).
100
36
  SWAPPED = 0x1 #/* thread is swapped out */
101
37
  IDLE = 0x2 #/* thread is an idle thread */
102
38
  end
103
-
104
- attr_accessor :user_time
105
- attr_accessor :system_time
106
- alias_method :__refresh, :refresh
107
- (FIELDS = [ [:user_time_s, "I"],
108
- [:user_time_us, "I"],
109
- [:system_time_s, "I"],
110
- [:system_time_us, "I"],
111
- [:cpu_usage, "I"],
112
- [:policy, "I"],
113
- [:run_state, "I"],
114
- [:flags, "I"],
115
- [:suspend_count, "I"],
116
- [:sleep_time, "I"]]).each {|x| attr_accessor x[0]}
117
39
 
118
40
  FLAVOR = Ragweed::Wraposx::ThreadInfo::BASIC_INFO
119
- #(re)loads the data from str
120
- def refresh(str)
121
- __refresh str
122
- @user_time = @user_time_s + (@user_time_us/1000000.0)
123
- @system_time = @system_time_s + (@system_time_us/1000000.0)
124
- end
41
+ layout :user_time, Ragweed::Wraposx::TimeValue,
42
+ :system_time, Ragweed::Wraposx::TimeValue,
43
+ :cpu_usage, :int,
44
+ :policy, Ragweed::Wraposx::Libc.find_type(:policy_t),
45
+ :run_state, :int,
46
+ :flags, :int,
47
+ :suspend_count, :int,
48
+ :sleep_time, :int
125
49
 
126
50
  def dump(&block)
127
51
  maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
@@ -150,13 +74,12 @@ EOM
150
74
  # boolean_t depressed;
151
75
  # int depress_priority;
152
76
  # };
153
- class SchedTimeshare
154
- include Ragweed::Wraposx::ThreadInfo::ThreadInfoMixins
155
- (FIELDS = [ [:max_priority, "I"],
156
- [:base_priority, "I"],
157
- [:cur_priority, "I"],
158
- [:depressed, "I"],
159
- [:depress_priority, "I"]]).each {|x| attr_accessor x[0]}
77
+ class SchedTimeshare < FFI::Struct
78
+ include Ragweed::FFIStructInclude
79
+ layout :max_priority, :int,
80
+ :base_priority, :int,
81
+ :cur_priority, :int,
82
+ :depress_priority, :int
160
83
 
161
84
  def dump(&block)
162
85
  maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
@@ -181,13 +104,13 @@ EOM
181
104
  # boolean_t depressed;
182
105
  # int depress_priority;
183
106
  # };
184
- class SchedRr
185
- include Ragweed::Wraposx::ThreadInfo::ThreadInfoMixins
186
- (FIELDS = [ [:max_priority, "I"],
187
- [:base_priority, "I"],
188
- [:quantum, "I"],
189
- [:depressed, "I"],
190
- [:depress_priority, "I"]]).each {|x| attr_accessor x[0]}
107
+ class SchedRr < FFI::Struct
108
+ include Ragweed::FFIStructInclude
109
+ layout :max_priority, :int,
110
+ :base_priority, :int,
111
+ :quantum, :int,
112
+ :depressed, Ragweed::Wraposx::Libc.find_type(:boolean_t),
113
+ :depress_priority, :int
191
114
 
192
115
  def dump(&block)
193
116
  maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
@@ -201,8 +124,19 @@ EOM
201
124
  depressed: #{(!self.depressed.zero?).to_s.rjust(8, " ")} #{maybe_hex.call(self.depressed)}
202
125
  depress_priority: #{self.depress_priority.to_s.rjust(8, "0")} #{maybe_hex.call(self.depressed_priority)}
203
126
  EOM
127
+ end
204
128
  end
205
- end
129
+
130
+ FLAVORS = {
131
+ # define THREAD_BASIC_INFO_COUNT ((mach_msg_type_number_t)(sizeof(thread_basic_info_data_t) / sizeof(natural_t)))
132
+ BASIC_INFO => {:size => 30, :count => 10, :class => Basic},
133
+ # define POLICY_TIMESHARE_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_timeshare_info)/sizeof(integer_t)))
134
+ SCHED_TIMESHARE_INFO => {:size => 20, :count => 5, :class => SchedTimeshare},
135
+ # define POLICY_RR_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_rr_info)/sizeof(integer_t)))
136
+ SCHED_RR_INFO => {:size => 20,:count => 5, :class => SchedRr},
137
+ # define POLICY_FIFO_INFO_COUNT ((mach_msg_type_number_t)(sizeof(struct policy_fifo_info)/sizeof(integer_t)))
138
+ # SCHED_FIFO_INFO => {:size => 16,:count => 4} # immediately returns KERNEL_INVALID_POLICY on osx
139
+ }
206
140
  end
207
141
 
208
142
  module Ragweed::Wraposx
@@ -215,13 +149,12 @@ module Ragweed::Wraposx
215
149
  # thread_flavor_t flavor,
216
150
  # thread_info_t thread_info,
217
151
  # mach_msg_type_number_t thread_info_count);
218
- def thread_info_raw(thread, flavor)
219
- raise KErrno::INVALID_ARGUMENT if ThreadInfo::FLAVORS[flavor].nil?
220
- info = ("\x00"*ThreadInfo::FLAVORS[flavor][:size]).to_ptr
221
- count = ([Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]].pack("I_")).to_ptr
222
- r = CALLS["libc!thread_info:IIPP=I"].call(thread,flavor,info,Ragweed::Wraposx::ThreadInfo::FLAVORS[flavor][:count]).first
152
+ def thread_info(thread, flavor)
153
+ info = FFI::MemoryPointer.new(ThreadInfo::FLAVORS[flavor][:class], 1)
154
+ count = FFI::MemoryPointer.new(:int, 1).write_int(ThreadInfo::FLAVORS[flavor][:count])
155
+ r = Libc.thread_info(thread, flavor, info, count)
223
156
  raise KernelCallError.new(r) if r != 0
224
- return "#{info.to_s(ThreadInfo::FLAVORS[flavor][:size])}#{count.to_s(SizeOf::INT)}"
157
+ ThreadInfo::FLAVORS[flavor][:class].new info
225
158
  end
226
159
  end
227
160
  end
@@ -0,0 +1,121 @@
1
+ module Ragweed; end
2
+ module Ragweed::Wraposx::ThreadState
3
+ #Thread run states
4
+ RUNNING = 1 #/* thread is running normally */
5
+ STOPPED = 2 #/* thread is stopped */
6
+ WAITING = 3 #/* thread is waiting normally */
7
+ UNINTERRUPTIBLE = 4 #/* thread is in an uninterruptible wait */
8
+ HALTED = 5 #/* thread is halted at a clean point */
9
+ end
10
+
11
+ module Ragweed::Wraposx::TFlags
12
+ #Thread flags (flags field).
13
+ SWAPPED = 0x1 #/* thread is swapped out */
14
+ IDLE = 0x2 #/* thread is an idle thread */
15
+ end
16
+
17
+ class Ragweed::Wraposx::ThreadInfo
18
+ include Ragweed
19
+ attr_accessor :user_time
20
+ attr_accessor :system_time
21
+ (FIELDS = [ [:user_time_s, "I"],
22
+ [:user_time_us, "I"],
23
+ [:system_time_s, "I"],
24
+ [:system_time_us, "I"],
25
+ [:cpu_usage, "I"],
26
+ [:policy, "I"],
27
+ [:run_state, "I"],
28
+ [:flags, "I"],
29
+ [:suspend_count, "I"],
30
+ [:sleep_time, "I"]]).each {|x| attr_accessor x[0]}
31
+
32
+ def initialize(str=nil)
33
+ refresh(str) if str
34
+ end
35
+
36
+ #(re)loads the data from str
37
+ def refresh(str)
38
+ if str and not str.empty?
39
+ str.unpack(FIELDS.map {|x| x[1]}.join("")).each_with_index do |val, i|
40
+ raise "i is nil" if i.nil?
41
+ instance_variable_set "@#{ FIELDS[i][0] }".intern, val
42
+ end
43
+ end
44
+ @user_time = @user_time_s + (@user_time_us/1000000.0)
45
+ @system_time = @system_time_s + (@system_time_us/1000000.0)
46
+ end
47
+
48
+ def to_s
49
+ FIELDS.map {|f| send(f[0])}.pack(FIELDS.map {|x| x[1]}.join(""))
50
+ end
51
+
52
+ def self.get(t)
53
+ self.new(Wraposx::thread_info_raw(t))
54
+ end
55
+
56
+ def get(t)
57
+ refresh(Wraposx::thread_info_raw(t))
58
+ end
59
+
60
+ def inspect
61
+ body = lambda do
62
+ FIELDS.map do |f|
63
+ "#{f[0]}=#{send(f[0]).to_s}"
64
+ end.join(", ")
65
+ end
66
+ "#<ThreadInfo #{body.call}>"
67
+ end
68
+
69
+ def dump(&block)
70
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
71
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
72
+
73
+ string =<<EOM
74
+ -----------------------------------------------------------------------
75
+ INFO:
76
+ user_time: #{self.user_time.to_s.rjust(8, "0")} #{maybe_hex.call(self.user_time)}
77
+ system_time: #{self.system_time.to_s.rjust(8, "0")} #{maybe_hex.call(self.system_time)}
78
+ cpu_usage: #{self.cpu_usage.to_s.rjust(8, "0")} #{maybe_hex.call(self.cpu_usage)}
79
+ policy: #{self.policy.to_s.rjust(8, "0")} #{maybe_hex.call(self.policy)}
80
+ run_state: #{self.run_state.to_s.rjust(8, "0")} #{maybe_hex.call(self.run_state)}
81
+ suspend_count: #{self.suspend_count.to_s.rjust(8, "0")} #{maybe_hex.call(self.suspend_count)}
82
+ sleep_time: #{self.sleep_time.to_s.rjust(8, "0")} #{maybe_hex.call(self.sleep_time)}
83
+ flags: #{self.flags.to_s(2).rjust(32, "0")} #{Wraposx::TFlags.flag_dump(self.flags)}
84
+ EOM
85
+ end
86
+ end
87
+
88
+ module Ragweed::Wraposx
89
+
90
+ # FIXME - constants should be under separate sub-modules
91
+ # XXX - implement more thread info flavors (if possible)
92
+ # XXX - move to class based implementation a la region_info
93
+ # info interfaces
94
+ THREAD_BASIC_INFO = 3 #basic information
95
+
96
+ # following are obsolete interfaces
97
+ THREAD_SCHED_TIMESHARE_INFO = 10
98
+ THREAD_SCHED_RR_INFO = 11
99
+ THREAD_SCHED_FIFO_INFO = 12
100
+
101
+ # define THREAD_BASIC_INFO_COUNT ((mach_msg_type_number_t)(sizeof(thread_basic_info_data_t) / sizeof(natural_t)))
102
+ # the two time fields are each two ints
103
+ THREAD_BASIC_INFO_COUNT = 10
104
+
105
+ class << self
106
+
107
+ # Returns the packed string representation of the thread_info_t struct for later parsing.
108
+ # kern_return_t thread_info
109
+ # (thread_act_t target_thread,
110
+ # thread_flavor_t flavor,
111
+ # thread_info_t thread_info,
112
+ # mach_msg_type_number_t thread_info_count);
113
+ def thread_info_raw(thread)
114
+ info = ("\x00"*1024).to_ptr
115
+ count = ([THREAD_BASIC_INFO_COUNT].pack("I_")).to_ptr
116
+ r = CALLS["libc!thread_info:IIPP=I"].call(thread,THREAD_BASIC_INFO,info,count).first
117
+ raise KernelCallError.new(:thread_info, r) if r != 0
118
+ return info.to_s(SIZEOFINT*THREAD_BASIC_INFO_COUNT)
119
+ end
120
+ end
121
+ end