Refactor Mach FFI wrapper; get unit tests working again.
This commit is contained in:
parent
d373ed5996
commit
da42ac4875
105
lib/mach.rb
105
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'
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue