ragweed 0.1.7.3 → 0.2.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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