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 'ffi'
|
||||||
require 'mach/semaphore'
|
|
||||||
require 'mach/task'
|
require 'mach/types'
|
||||||
require 'mach/functions'
|
|
||||||
|
|
||||||
module Mach
|
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
|
# @return [Port] the original bootstrap port; different from that
|
||||||
# affected by {get,set}_special_port
|
# affected by {get,set}_special_port
|
||||||
def self.bootstrap_port
|
def self.bootstrap_port
|
||||||
@bootstrap_port ||= Mach::Port.new(:port => Mach::Functions::bootstrap_port)
|
@bootstrap_port ||= Mach::Port.new(:port => Mach::Functions::bootstrap_port)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require 'mach/port'
|
||||||
|
require 'mach/semaphore'
|
||||||
|
require 'mach/task'
|
||||||
|
require 'mach/functions'
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require 'ffi'
|
require 'ffi'
|
||||||
|
|
||||||
|
require 'mach/types'
|
||||||
require 'mach/time_spec'
|
require 'mach/time_spec'
|
||||||
|
|
||||||
module Mach
|
module Mach
|
||||||
|
@ -7,134 +8,10 @@ module Mach
|
||||||
# specific).
|
# specific).
|
||||||
module Functions
|
module Functions
|
||||||
extend FFI::Library
|
extend FFI::Library
|
||||||
|
extend Types
|
||||||
|
|
||||||
ffi_lib 'c'
|
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
|
# Replace methods in +syms+ with error checking wrappers that
|
||||||
# invoke the original method and raise a {SystemCallError}.
|
# invoke the original method and raise a {SystemCallError}.
|
||||||
#
|
#
|
||||||
|
@ -232,7 +109,7 @@ module Mach
|
||||||
|
|
||||||
attach_mach_function(:mach_port_allocate,
|
attach_mach_function(:mach_port_allocate,
|
||||||
[:ipc_space_t,
|
[:ipc_space_t,
|
||||||
MachPortRight,
|
PortRight,
|
||||||
:mach_port_name_pointer_t],
|
:mach_port_name_pointer_t],
|
||||||
:kern_return_t)
|
:kern_return_t)
|
||||||
|
|
||||||
|
@ -250,7 +127,7 @@ module Mach
|
||||||
[:ipc_space_t,
|
[:ipc_space_t,
|
||||||
:mach_port_name_t,
|
:mach_port_name_t,
|
||||||
:mach_port_t,
|
:mach_port_t,
|
||||||
MachMsgType],
|
MsgType],
|
||||||
:kern_return_t)
|
:kern_return_t)
|
||||||
|
|
||||||
##################
|
##################
|
||||||
|
@ -271,13 +148,13 @@ module Mach
|
||||||
|
|
||||||
attach_mach_function(:task_get_special_port,
|
attach_mach_function(:task_get_special_port,
|
||||||
[:task_t,
|
[:task_t,
|
||||||
MachSpecialPort,
|
SpecialPort,
|
||||||
:mach_port_pointer_t],
|
:mach_port_pointer_t],
|
||||||
:kern_return_t)
|
:kern_return_t)
|
||||||
|
|
||||||
attach_mach_function(:task_set_special_port,
|
attach_mach_function(:task_set_special_port,
|
||||||
[:task_t,
|
[:task_t,
|
||||||
MachSpecialPort,
|
SpecialPort,
|
||||||
:mach_port_t],
|
:mach_port_t],
|
||||||
:kern_return_t)
|
:kern_return_t)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ module Mach
|
||||||
# Insert +right+ into another ipc space. The current task must
|
# Insert +right+ into another ipc space. The current task must
|
||||||
# have sufficient rights to insert the requested right.
|
# have sufficient rights to insert the requested right.
|
||||||
#
|
#
|
||||||
# @param [MachMsgType] right
|
# @param [MsgType] right
|
||||||
#
|
#
|
||||||
# @param [Hash] opts
|
# @param [Hash] opts
|
||||||
#
|
#
|
||||||
|
@ -100,9 +100,9 @@ module Mach
|
||||||
|
|
||||||
msg[:header].tap do |h|
|
msg[:header].tap do |h|
|
||||||
h[:remote_port] = remote_port.to_i
|
h[:remote_port] = remote_port.to_i
|
||||||
h[:local_port] = MACH_PORT_NULL
|
h[:local_port] = PORT_NULL
|
||||||
h[:bits] =
|
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
|
h[:size] = 40 # msg.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,8 +110,8 @@ module Mach
|
||||||
|
|
||||||
msg[:port].tap do |p|
|
msg[:port].tap do |p|
|
||||||
p[:name] = port
|
p[:name] = port
|
||||||
p[:disposition] = MachMsgType[right]
|
p[:disposition] = MsgType[right]
|
||||||
p[:type] = 0 # MACH_MSG_PORT_DESCRIPTOR;
|
p[:type] = 0 # MSG_PORT_DESCRIPTOR;
|
||||||
end
|
end
|
||||||
|
|
||||||
mach_msg_send msg
|
mach_msg_send msg
|
||||||
|
@ -130,12 +130,12 @@ module Mach
|
||||||
msg = ReceiveRightMsg.new
|
msg = ReceiveRightMsg.new
|
||||||
|
|
||||||
mach_msg(msg,
|
mach_msg(msg,
|
||||||
2, # MACH_RCV_MSG,
|
2, # RCV_MSG,
|
||||||
0,
|
0,
|
||||||
msg.size,
|
msg.size,
|
||||||
port,
|
port,
|
||||||
MACH_MSG_TIMEOUT_NONE,
|
MSG_TIMEOUT_NONE,
|
||||||
MACH_PORT_NULL)
|
PORT_NULL)
|
||||||
|
|
||||||
self.class.new :port => msg[:port][:name]
|
self.class.new :port => msg[:port][:name]
|
||||||
end
|
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
|
module Kernel
|
||||||
# Override to call Process::fork.
|
# Override to call Process::fork.
|
||||||
|
def self.fork(*args, &block)
|
||||||
|
Process.fork(*args, &block)
|
||||||
|
end
|
||||||
|
|
||||||
def fork(*args, &block)
|
def fork(*args, &block)
|
||||||
Process.fork(*args, &block)
|
Process.fork(*args, &block)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue