From da42ac4875895923178eff317f0d20b74a018335 Mon Sep 17 00:00:00 2001 From: Patrick Mahoney Date: Wed, 8 Feb 2012 21:30:18 -0600 Subject: [PATCH] Refactor Mach FFI wrapper; get unit tests working again. --- lib/mach.rb | 105 +++++++++++++++++++++++++++-- lib/mach/functions.rb | 135 ++----------------------------------- lib/mach/port.rb | 16 ++--- lib/mach/types.rb | 54 +++++++++++++++ lib/process_shared/mach.rb | 4 ++ 5 files changed, 173 insertions(+), 141 deletions(-) create mode 100644 lib/mach/types.rb diff --git a/lib/mach.rb b/lib/mach.rb index f2d08a5..4c894c2 100644 --- a/lib/mach.rb +++ b/lib/mach.rb @@ -1,12 +1,109 @@ -require 'mach/port' -require 'mach/semaphore' -require 'mach/task' -require 'mach/functions' +require 'ffi' + +require 'mach/types' module Mach + extend Mach::Types + + class MsgHeader < FFI::Struct + layout(:bits, :mach_msg_bits_t, + :size, :mach_msg_size_t, + :remote_port, :mach_port_t, + :local_port, :mach_port_t, + :reserved, :mach_msg_size_t, + :id, :mach_msg_id_t) + end + + class MsgBody < FFI::Struct + layout(:descriptor_count, :mach_msg_size_t) + end + + class MsgBase < FFI::Struct + layout(:header, MsgHeader, + :body, MsgBody) + end + + class MsgTrailer < FFI::Struct + layout(:type, :mach_msg_trailer_type_t, + :size, :mach_msg_trailer_size_t) + end + + class MsgPortDescriptor < FFI::Struct + layout(:name, :mach_port_t, + :pad1, :mach_msg_size_t, # FIXME: leave oout on __LP64__ + :pad2, :uint16, # :uint + :disposition, :uint8, # :mach_msg_type_name_t + :type, :uint8) # :mach_msg_descriptor_type_t + end + + SyncPolicy = enum( :fifo, 0x0, + :fixed_priority, 0x1, + :reversed, 0x2, + :order_mask, 0x3, + :lifo, 0x0 | 0x2, # um... + :max, 0x7 ) + + PortRight = enum( :send, 0, + :receive, + :send_once, + :port_set, + :dead_name, + :labelh, + :number ) + + # port type macro + def self.pt(*syms) + acc = 0 + syms.each do |sym| + acc |= (1 << (PortRight[sym] + 16)) + end + acc + end + + PORT_NULL = 0 + MSG_TIMEOUT_NONE = 0 + + PortType = + enum(:none, 0, + :send, pt(:send), + :receive, pt(:receive), + :send_once, pt(:send_once), + :port_set, pt(:port_set), + :dead_name, pt(:dead_name), + :labelh, pt(:labelh), + + :send_receive, pt(:send, :receive), + :send_rights, pt(:send, :send_once), + :port_rights, pt(:send, :send_once, :receive), + :port_or_dead, pt(:send, :send_once, :receive, :dead_name), + :all_rights, pt(:send, :send_once, :receive, :dead_name, :port_set)) + + MsgType = + enum( :move_receive, 16, # must hold receive rights + :move_send, # must hold send rights + :move_send_once, # must hold sendonce rights + :copy_send, # must hold send rights + :make_send, # must hold receive rights + :make_send_once, # must hold receive rights + :copy_receive ) # must hold receive rights + + SpecialPort = + enum( :kernel, 1, + :host, + :name, + :bootstrap ) + + KERN_SUCCESS = 0 + + # @return [Port] the original bootstrap port; different from that # affected by {get,set}_special_port def self.bootstrap_port @bootstrap_port ||= Mach::Port.new(:port => Mach::Functions::bootstrap_port) end end + +require 'mach/port' +require 'mach/semaphore' +require 'mach/task' +require 'mach/functions' diff --git a/lib/mach/functions.rb b/lib/mach/functions.rb index e5fd8b8..d5cd8e7 100644 --- a/lib/mach/functions.rb +++ b/lib/mach/functions.rb @@ -1,5 +1,6 @@ require 'ffi' +require 'mach/types' require 'mach/time_spec' module Mach @@ -7,134 +8,10 @@ module Mach # specific). module Functions extend FFI::Library + extend Types ffi_lib 'c' - typedef :__darwin_mach_port_t, :mach_port_t - typedef :__darwin_natural_t, :natural_t - - typedef :int, :integer_t - typedef :int, :kern_return_t # true for 64 bit?? - typedef :int, :mach_error_t - typedef :int, :sync_policy_t # SyncPolicy - typedef :int, :clock_id_t - typedef :int, :clock_res_t - - typedef :string, :name_t - - typedef :mach_port_t, :host_t - typedef :mach_port_t, :task_t - typedef :mach_port_t, :ipc_space_t - typedef :mach_port_t, :semaphore_t - typedef :pointer, :mach_port_pointer_t - - typedef :natural_t, :mach_port_name_t - typedef :natural_t, :mach_port_right_t # MachPortRight - typedef :pointer, :mach_port_name_array_t - typedef :pointer, :mach_port_name_pointer_t - - typedef :uint, :mach_msg_type_name_t - typedef :uint, :mach_msg_bits_t - typedef :uint, :mach_msg_trailer_type_t - typedef :uint, :mach_msg_trailer_size_t - typedef :uint, :mach_msg_descriptor_type_t - typedef :natural_t, :mach_msg_timeout_t - - typedef :natural_t, :mach_msg_size_t - typedef :integer_t, :mach_msg_id_t - typedef :integer_t, :mach_msg_options_t - typedef :integer_t, :mach_msg_option_t - - class MsgHeader < FFI::Struct - layout(:bits, :mach_msg_bits_t, - :size, :mach_msg_size_t, - :remote_port, :mach_port_t, - :local_port, :mach_port_t, - :reserved, :mach_msg_size_t, - :id, :mach_msg_id_t) - end - - class MsgBody < FFI::Struct - layout(:descriptor_count, :mach_msg_size_t) - end - - class MsgBase < FFI::Struct - layout(:header, MsgHeader, - :body, MsgBody) - end - - class MsgTrailer < FFI::Struct - layout(:type, :mach_msg_trailer_type_t, - :size, :mach_msg_trailer_size_t) - end - - class MsgPortDescriptor < FFI::Struct - layout(:name, :mach_port_t, - :pad1, :mach_msg_size_t, # FIXME: leave oout on __LP64__ - :pad2, :uint16, # :uint - :disposition, :uint8, # :mach_msg_type_name_t - :type, :uint8) # :mach_msg_descriptor_type_t - end - - SyncPolicy = enum( :fifo, 0x0, - :fixed_priority, 0x1, - :reversed, 0x2, - :order_mask, 0x3, - :lifo, 0x0 | 0x2, # um... - :max, 0x7 ) - - MachPortRight = enum( :send, 0, - :receive, - :send_once, - :port_set, - :dead_name, - :labelh, - :number ) - - # port type - def self.pt(*syms) - acc = 0 - syms.each do |sym| - acc |= (1 << (MachPortRight[sym] + 16)) - end - acc - end - - MACH_PORT_NULL = 0 - MACH_MSG_TIMEOUT_NONE = 0 - - MachPortType = - enum(:none, 0, - :send, pt(:send), - :receive, pt(:receive), - :send_once, pt(:send_once), - :port_set, pt(:port_set), - :dead_name, pt(:dead_name), - :labelh, pt(:labelh), - - :send_receive, pt(:send, :receive), - :send_rights, pt(:send, :send_once), - :port_rights, pt(:send, :send_once, :receive), - :port_or_dead, pt(:send, :send_once, :receive, :dead_name), - :all_rights, pt(:send, :send_once, :receive, :dead_name, :port_set)) - - MachMsgType = - enum( :move_receive, 16, # must hold receive rights - :move_send, # must hold send rights - :move_send_once, # must hold sendonce rights - :copy_send, # must hold send rights - :make_send, # must hold receive rights - :make_send_once, # must hold receive rights - :copy_receive ) # must hold receive rights - - MachSpecialPort = - enum( :kernel, 1, - :host, - :name, - :bootstrap ) - - KERN_SUCCESS = 0 - # Replace methods in +syms+ with error checking wrappers that # invoke the original method and raise a {SystemCallError}. # @@ -232,7 +109,7 @@ module Mach attach_mach_function(:mach_port_allocate, [:ipc_space_t, - MachPortRight, + PortRight, :mach_port_name_pointer_t], :kern_return_t) @@ -250,7 +127,7 @@ module Mach [:ipc_space_t, :mach_port_name_t, :mach_port_t, - MachMsgType], + MsgType], :kern_return_t) ################## @@ -271,13 +148,13 @@ module Mach attach_mach_function(:task_get_special_port, [:task_t, - MachSpecialPort, + SpecialPort, :mach_port_pointer_t], :kern_return_t) attach_mach_function(:task_set_special_port, [:task_t, - MachSpecialPort, + SpecialPort, :mach_port_t], :kern_return_t) diff --git a/lib/mach/port.rb b/lib/mach/port.rb index f947e0d..84d0635 100644 --- a/lib/mach/port.rb +++ b/lib/mach/port.rb @@ -76,7 +76,7 @@ module Mach # Insert +right+ into another ipc space. The current task must # have sufficient rights to insert the requested right. # - # @param [MachMsgType] right + # @param [MsgType] right # # @param [Hash] opts # @@ -100,9 +100,9 @@ module Mach msg[:header].tap do |h| h[:remote_port] = remote_port.to_i - h[:local_port] = MACH_PORT_NULL + h[:local_port] = PORT_NULL h[:bits] = - (MachMsgType[right] | (0 << 8)) | 0x80000000 # MACH_MSGH_BITS_COMPLEX + (MsgType[right] | (0 << 8)) | 0x80000000 # MACH_MSGH_BITS_COMPLEX h[:size] = 40 # msg.size end @@ -110,8 +110,8 @@ module Mach msg[:port].tap do |p| p[:name] = port - p[:disposition] = MachMsgType[right] - p[:type] = 0 # MACH_MSG_PORT_DESCRIPTOR; + p[:disposition] = MsgType[right] + p[:type] = 0 # MSG_PORT_DESCRIPTOR; end mach_msg_send msg @@ -130,12 +130,12 @@ module Mach msg = ReceiveRightMsg.new mach_msg(msg, - 2, # MACH_RCV_MSG, + 2, # RCV_MSG, 0, msg.size, port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL) + MSG_TIMEOUT_NONE, + PORT_NULL) self.class.new :port => msg[:port][:name] end diff --git a/lib/mach/types.rb b/lib/mach/types.rb new file mode 100644 index 0000000..ddf2051 --- /dev/null +++ b/lib/mach/types.rb @@ -0,0 +1,54 @@ +require 'ffi' + +module Mach + module Types + extend FFI::Library + + typedef :__darwin_mach_port_t, :mach_port_t + typedef :__darwin_natural_t, :natural_t + + typedef :int, :integer_t + typedef :int, :kern_return_t # true for 64 bit?? + typedef :int, :mach_error_t + typedef :int, :sync_policy_t # SyncPolicy + typedef :int, :clock_id_t + typedef :int, :clock_res_t + + typedef :string, :name_t + + typedef :mach_port_t, :host_t + typedef :mach_port_t, :task_t + typedef :mach_port_t, :ipc_space_t + typedef :mach_port_t, :semaphore_t + typedef :pointer, :mach_port_pointer_t + + typedef :natural_t, :mach_port_name_t + typedef :natural_t, :mach_port_right_t # MachPortRight + typedef :pointer, :mach_port_name_array_t + typedef :pointer, :mach_port_name_pointer_t + + typedef :uint, :mach_msg_type_name_t + typedef :uint, :mach_msg_bits_t + typedef :uint, :mach_msg_trailer_type_t + typedef :uint, :mach_msg_trailer_size_t + typedef :uint, :mach_msg_descriptor_type_t + typedef :natural_t, :mach_msg_timeout_t + + typedef :natural_t, :mach_msg_size_t + typedef :integer_t, :mach_msg_id_t + typedef :integer_t, :mach_msg_options_t + typedef :integer_t, :mach_msg_option_t + + def self.typedefs + @ffi_typedefs + end + + def find_type(t) + Mach::Types.find_type(t) || super + end + + def enum(*args) + Mach::Types.enum(*args) + end + end +end diff --git a/lib/process_shared/mach.rb b/lib/process_shared/mach.rb index 6ef87fc..bb937a7 100644 --- a/lib/process_shared/mach.rb +++ b/lib/process_shared/mach.rb @@ -46,6 +46,10 @@ end module Kernel # Override to call Process::fork. + def self.fork(*args, &block) + Process.fork(*args, &block) + end + def fork(*args, &block) Process.fork(*args, &block) end