From 680527cbab9848acb04bfdb47c09ad7e4f3ded75 Mon Sep 17 00:00:00 2001 From: Patrick Mahoney Date: Wed, 1 Feb 2012 21:34:51 -0600 Subject: [PATCH] Add time and clock Mach functions; implement Mach::Semaphore#timedwait. --- lib/mach/clock.rb | 24 ++++++++++++++++++++++++ lib/mach/functions.rb | 33 +++++++++++++++++++++++++++------ lib/mach/host.rb | 28 ++++++++++++++++++++++++++++ lib/mach/semaphore.rb | 7 ++++++- lib/mach/time_spec.rb | 16 ++++++++++++++++ 5 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 lib/mach/clock.rb create mode 100644 lib/mach/host.rb create mode 100644 lib/mach/time_spec.rb diff --git a/lib/mach/clock.rb b/lib/mach/clock.rb new file mode 100644 index 0000000..b3d0c34 --- /dev/null +++ b/lib/mach/clock.rb @@ -0,0 +1,24 @@ +require 'mach/functions' +require 'mach/port' +require 'mach/time_spec' + +module Mach + class Clock + include Functions + + def initialize(clock_id) + @clock_id = clock_id + end + + def to_s + "#<#{self.class} #{@clock_id.to_i}>" + end + + def get_time + time = TimeSpec.new + clock_get_time(@clock_id.to_i, time) + time + end + end +end + diff --git a/lib/mach/functions.rb b/lib/mach/functions.rb index f4bd59b..e5fd8b8 100644 --- a/lib/mach/functions.rb +++ b/lib/mach/functions.rb @@ -1,5 +1,7 @@ require 'ffi' +require 'mach/time_spec' + module Mach # FFI wrapper around a subset of the Mach API (likely Mac OS X # specific). @@ -15,9 +17,12 @@ module Mach 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 @@ -128,11 +133,6 @@ module Mach :name, :bootstrap ) - class Timespec < FFI::ManagedStruct - layout(:tv_sec, :uint, - :tv_nsec, :int) - end - KERN_SUCCESS = 0 # Replace methods in +syms+ with error checking wrappers that @@ -253,6 +253,18 @@ module Mach MachMsgType], :kern_return_t) + ################## + # Host functions # + ################## + + attach_function :mach_host_self, [], :mach_port_t + + attach_mach_function(:host_get_clock_service, + [:host_t, + :clock_id_t, + :pointer], + :kern_return_t) + ################## # Task functions # ################## @@ -269,6 +281,15 @@ module Mach :mach_port_t], :kern_return_t) + ################### + # Clock functions # + ################### + + attach_mach_function(:clock_get_time, + [:clock_id_t, + TimeSpec], + :kern_return_t) + ##################### # Message functions # ##################### @@ -312,7 +333,7 @@ module Mach [:semaphore_t], :kern_return_t) attach_mach_function(:semaphore_timedwait, - [:semaphore_t, Timespec.val], + [:semaphore_t, TimeSpec.val], :kern_return_t) end diff --git a/lib/mach/host.rb b/lib/mach/host.rb new file mode 100644 index 0000000..d310039 --- /dev/null +++ b/lib/mach/host.rb @@ -0,0 +1,28 @@ +require 'mach/functions' +require 'mach/port' +require 'mach/clock' + +module Mach + class Host < Port + include Functions + + # @return [Task] + def self.self + new(Functions.mach_host_self) + end + + def initialize(host) + super(:port => host) + end + + alias_method :host, :port + + def get_clock_service + mem = new_memory_pointer(:clock_id_t) + host_get_clock_service(host, 0, mem) + clock_id = Port.new(:port => mem.read_int) + Clock.new clock_id + end + end +end + diff --git a/lib/mach/semaphore.rb b/lib/mach/semaphore.rb index 007eaaf..3033165 100644 --- a/lib/mach/semaphore.rb +++ b/lib/mach/semaphore.rb @@ -1,5 +1,7 @@ require 'mach/functions' require 'mach/port' +require 'mach/host' +require 'mach/clock' module Mach class Semaphore < Port @@ -61,8 +63,11 @@ module Mach semaphore_wait(port) end - # TODO: implement + # @see http://pkaudio.blogspot.com/2010/05/mac-os-x-no-timed-semaphore-waits.html def timedwait(secs) + timespec = TimeSpec.new + timespec.add_seconds!(secs) + semaphore_timedwait(port, timespec) end end diff --git a/lib/mach/time_spec.rb b/lib/mach/time_spec.rb new file mode 100644 index 0000000..96c9aeb --- /dev/null +++ b/lib/mach/time_spec.rb @@ -0,0 +1,16 @@ +require 'ffi' + +module Mach + class TimeSpec < FFI::Struct + layout(:tv_sec, :uint, + :tv_nsec, :int) # clock_res_t + + def to_s + "#<%s tv_sec=%d tv_nsec=%d>" % [self.class, + self[:tv_sec], + self[:tv_nsec]] + + end + end +end +