      -- * Point-to-point operations
      -- ** Tags.
      Tag, toTag, fromTag, anyTag, unitTag, tagUpperBound,
+
      -- ** Blocking operations
      BufferPtr, Count, -- XXX: what will break if we don't export those?
      send, bsend, ssend, rsend, recv,

{# fun unsafe init_wrapper_thread as initThread
                {cFromEnum `ThreadSupport', alloca- `ThreadSupport' peekEnum* } -> `()' checkError*- #}

{# fun unsafe Query_thread as ^ {alloca- `Bool' peekBool* } -> `()' checkError*- #}

{# fun unsafe Is_thread_main as ^
                 {alloca- `Bool' peekBool* } -> `()' checkError*- #}


{# fun unsafe Op_create as ^
              {castFunPtr `FunPtr (Ptr t -> Ptr t -> Ptr CInt -> Ptr Datatype -> IO ())', cFromEnum `Bool', alloca- `Operation' peekOperation*} -> `()' checkError*- #}
{# fun Op_free as ^ {withOperation* `Operation'} -> `()' checkError*- #}

{- | Returns a 
floating-point number of seconds, representing elapsed wallclock
time since some time in the past.

The \"time in the past\" is guaranteed not to change during the life of the process.
The user is responsible for converting large numbers of seconds to other units if they are
preferred. The time is local to the node that calls @wtime@, but see 'wtimeIsGlobal'.
-}
{# fun unsafe Wtime as ^ {} -> `Double' realToFrac #}

{- | Returns the resolution of 'wtime' in seconds. That is, it returns,
as a double precision value, the number of seconds between successive clock ticks. For
example, if the clock is implemented by the hardware as a counter that is incremented
every millisecond, the value returned by @wtick@ should be 10^(-3).
-}
{# fun unsafe Wtick as ^ {} -> `Double' realToFrac #}

-- | Return the process group from a communicator. With
--   intercommunicator, returns the local group.
{# fun unsafe Comm_group as ^
               {fromComm `Comm', alloca- `Group' peekGroup*} -> `()' checkError*- #}

