Home | History | Annotate | Download | only in system
      1 // Copyright 2017 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MOJO_PUBLIC_C_SYSTEM_TRAP_H_
      6 #define MOJO_PUBLIC_C_SYSTEM_TRAP_H_
      7 
      8 #include <stdint.h>
      9 
     10 #include "mojo/public/c/system/macros.h"
     11 #include "mojo/public/c/system/system_export.h"
     12 #include "mojo/public/c/system/types.h"
     13 
     14 // Flags passed to trap event handlers within |MojoTrapEvent|.
     15 typedef uint32_t MojoTrapEventFlags;
     16 
     17 #ifdef __cplusplus
     18 const MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_NONE = 0;
     19 const MojoTrapEventFlags MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL = 1 << 0;
     20 #else
     21 #define MOJO_TRAP_EVENT_FLAG_NONE ((MojoTrapEventFlags)0)
     22 #define MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL ((MojoTrapEventFlags)1 << 0)
     23 #endif
     24 
     25 // Structure passed to trap event handlers when invoked by a tripped trap.
     26 struct MOJO_ALIGNAS(8) MojoTrapEvent {
     27   // The size of this structure, used for versioning.
     28   uint32_t struct_size;
     29 
     30   // May take on some combination of the following values:
     31   //
     32   //   |MOJO_TRAP_EVENT_FLAG_NONE|: No flags.
     33   //
     34   //   |MOJO_TRAP_EVENT_FLAG_WITHIN_API_CALL|: The trap was tripped within the
     35   //       extent of a user call to some Mojo API. This means that the event
     36   //       handler itself is re-entering user code. May happen, for example, if
     37   //       user code writes to an intra-process pipe and the receiving end trips
     38   //       a trap as a result. In that case the event handler executes within
     39   //       the extent of the |MojoWriteMessage()| call.
     40   MojoTrapEventFlags flags;
     41 
     42   // The context for the trigger which tripped the trap.
     43   MOJO_POINTER_FIELD(uintptr_t, trigger_context);
     44 
     45   // A result code indicating the cause of the event. May take on any of the
     46   // following values:
     47   //
     48   //   |MOJO_RESULT_OK|: The trigger's conditions were met.
     49   //   |MOJO_RESULT_FAILED_PRECONDITION|: The trigger's observed handle has
     50   //       changed state in such a way that the trigger's conditions can never
     51   //       be met again.
     52   //   |MOJO_RESULT_CANCELLED|: The trigger has been removed and will never
     53   //       cause another event to fire. This is always the last event fired by
     54   //       a trigger and it will fire when: the trigger is explicitly removed
     55   //       with |MojoRemoteTrigger()|, the trigger's owning trap handle is
     56   //       closed, or the handle observed by the trigger is closed.
     57   //
     58   //       Unlike the other result types above |MOJO_RESULT_CANCELLED| can
     59   //       fire even when the trap is disarmed.
     60   MojoResult result;
     61 
     62   // The last known signalling state of the trigger's observed handle at the
     63   // time the trap was tripped.
     64   struct MojoHandleSignalsState signals_state;
     65 };
     66 MOJO_STATIC_ASSERT(sizeof(MojoTrapEvent) == 32,
     67                    "MojoTrapEvent has wrong size.");
     68 
     69 // Value given to |MojoAddTrigger| to configure what condition should cause it
     70 // to trip its trap. May be one of the following values:
     71 //
     72 //   |MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED| - A trigger added with this
     73 //       condition will trip its trap when any of its observed signals
     74 //       transition from being satisfied to being unsatisfied.
     75 //   |MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED| - A triger added with this
     76 //       condition will trip its trap  when any of its observed signals
     77 //       transition from being unsatisfied to being satisfied, or when none of
     78 //       the observed signals can ever be satisfied again.
     79 typedef uint32_t MojoTriggerCondition;
     80 
     81 #ifdef __cplusplus
     82 const MojoTriggerCondition MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED = 0;
     83 const MojoTriggerCondition MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED = 1;
     84 #else
     85 #define MOJO_TRIGGER_CONDITION_SIGNALS_UNSATISFIED ((MojoTriggerCondition)0)
     86 #define MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED ((MojoTriggerCondition)1)
     87 #endif
     88 
     89 // Flags passed to |MojoCreateTrap()| via |MojoCreateTrapOptions|.
     90 typedef uint32_t MojoCreateTrapFlags;
     91 
     92 #ifdef __cplusplus
     93 const MojoCreateTrapFlags MOJO_CREATE_TRAP_FLAG_NONE = 0;
     94 #else
     95 #define MOJO_CREATE_TRAP_FLAG_NONE ((MojoCreateTrapFlags)0)
     96 #endif
     97 
     98 // Options passed to |MojoCreateTrap()|.
     99 struct MOJO_ALIGNAS(8) MojoCreateTrapOptions {
    100   // The size of this structure, used for versioning.
    101   uint32_t struct_size;
    102 
    103   // Flags. Currently unused.
    104   MojoCreateTrapFlags flags;
    105 };
    106 MOJO_STATIC_ASSERT(sizeof(MojoCreateTrapOptions) == 8,
    107                    "MojoCreateTrapOptions has wrong size.");
    108 
    109 // Flags passed to |MojoAddTrigger()| via |MojoAddTriggerOptions|.
    110 typedef uint32_t MojoAddTriggerFlags;
    111 
    112 #ifdef __cplusplus
    113 const MojoAddTriggerFlags MOJO_ADD_TRIGGER_FLAG_NONE = 0;
    114 #else
    115 #define MOJO_ADD_TRIGGER_FLAG_NONE ((MojoAddTriggerFlags)0)
    116 #endif
    117 
    118 // Options passed to |MojoAddTrigger()|.
    119 struct MOJO_ALIGNAS(8) MojoAddTriggerOptions {
    120   // The size of this structure, used for versioning.
    121   uint32_t struct_size;
    122 
    123   // Flags. Currently unused.
    124   MojoAddTriggerFlags flags;
    125 };
    126 MOJO_STATIC_ASSERT(sizeof(MojoAddTriggerOptions) == 8,
    127                    "MojoAddTriggerOptions has wrong size.");
    128 
    129 // Flags passed to |MojoRemoveTrigger()| via |MojoRemoveTriggerOptions|.
    130 typedef uint32_t MojoRemoveTriggerFlags;
    131 
    132 #ifdef __cplusplus
    133 const MojoRemoveTriggerFlags MOJO_REMOVE_TRIGGER_FLAG_NONE = 0;
    134 #else
    135 #define MOJO_REMOVE_TRIGGER_FLAG_NONE ((MojoRemoveTriggerFlags)0)
    136 #endif
    137 
    138 // Options passed to |MojoRemoveTrigger()|.
    139 struct MOJO_ALIGNAS(8) MojoRemoveTriggerOptions {
    140   // The size of this structure, used for versioning.
    141   uint32_t struct_size;
    142 
    143   // Flags. Currently unused.
    144   MojoRemoveTriggerFlags flags;
    145 };
    146 MOJO_STATIC_ASSERT(sizeof(MojoRemoveTriggerOptions) == 8,
    147                    "MojoRemoveTriggerOptions has wrong size.");
    148 
    149 // Flags passed to |MojoArmTrap()| via |MojoArmTrapOptions|.
    150 typedef uint32_t MojoArmTrapFlags;
    151 
    152 #ifdef __cplusplus
    153 const MojoArmTrapFlags MOJO_ARM_TRAP_FLAG_NONE = 0;
    154 #else
    155 #define MOJO_ARM_TRAP_FLAG_NONE ((MojoArmTrapFlags)0)
    156 #endif
    157 
    158 // Options passed to |MojoArmTrap()|.
    159 struct MOJO_ALIGNAS(8) MojoArmTrapOptions {
    160   // The size of this structure, used for versioning.
    161   uint32_t struct_size;
    162 
    163   // Flags. Currently unused.
    164   MojoArmTrapFlags flags;
    165 };
    166 MOJO_STATIC_ASSERT(sizeof(MojoArmTrapOptions) == 8,
    167                    "MojoArmTrapOptions has wrong size.");
    168 
    169 #ifdef __cplusplus
    170 extern "C" {
    171 #endif
    172 
    173 // A user-provided callback to handle trap events. Passed to |MojoCreateTrap()|.
    174 typedef void (*MojoTrapEventHandler)(const struct MojoTrapEvent* event);
    175 
    176 // Creates a new trap which can be used to detect signal changes on a handle.
    177 // Traps execute arbitrary user code when tripped.
    178 //
    179 // Traps can trip only while armed**, and new traps are created in a disarmed
    180 // state. Traps may be armed using |MojoArmTrap()|.
    181 //
    182 // Arming a trap is only possible when the trap has one or more triggers
    183 // attached to it. Triggers can be added or removed using |MojoAddTrigger()| and
    184 // |MojoRemoveTrigger()|.
    185 //
    186 // If a trap is tripped by any of its triggers, it is disarmed immediately and
    187 // the traps |MojoTrapEventHandler| is invoked once for every relevant trigger.
    188 //
    189 // |options| may be null.
    190 //
    191 // ** An unarmed trap will still fire an event when a trigger is removed. This
    192 // event will always convey the result |MOJO_RESULT_CANCELLED|.
    193 //
    194 // Parameters:
    195 //   |handler|: The |MojoTrapEventHandler| to invoke any time this trap is
    196 //       tripped. Note that this may be called from any arbitrary thread.
    197 //   |trap_handle|: The address at which to store the MojoHandle corresponding
    198 //       to the new trap if successfully created.
    199 //
    200 // Returns:
    201 //   |MOJO_RESULT_OK| if the trap has been successfully created.
    202 //   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a handle could not be allocated for
    203 //       this trap.
    204 MOJO_SYSTEM_EXPORT MojoResult
    205 MojoCreateTrap(MojoTrapEventHandler handler,
    206                const struct MojoCreateTrapOptions* options,
    207                MojoHandle* trap_handle);
    208 
    209 // Adds a trigger to a trap. This configures the trap to invoke its event
    210 // handler if the specified conditions are met (or can no longer be met) while
    211 // the trap is armed.
    212 //
    213 // Note that event handler invocations for a given trigger are mutually
    214 // exclusive in execution: the handler will never be entered for a trigger while
    215 // another thread is executing it for the same trigger. Similarly, event
    216 // handlers are never re-entered. If an event handler changes the state of the
    217 // system such that another event would fire, that event is deferred until the
    218 // first handler returns.
    219 //
    220 // Parameters:
    221 //   |trap_handle|: The trap to which this trigger is to be added.
    222 //   |handle|: The handle whose signals this trigger will observe. Must be a
    223 //       message pipe or data pipe handle.
    224 //   |signals|: The specific signal(s) this trigger will observe on |handle|.
    225 //   |condition|: The signaling condition this trigger will observe. i.e.
    226 //       whether to trip the trap when |signals| become satisfied or when they
    227 //       become unsatisfied.
    228 //   |context|: An arbitrary context value to be passed to the trap's event
    229 //       handler when this trigger was responsible for tripping the trap. See
    230 //       the |trigger_context| field in |MojoTrapEvent|. This value must be
    231 //       unique among all triggers on the trap.
    232 //
    233 //   |options| may be null.
    234 //
    235 // Returns:
    236 //   |MOJO_RESULT_OK| if the handle is now being observed by the trigger.
    237 //   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle,
    238 //       |handle| is not a valid message pipe or data pipe handle, or |signals|
    239 //       or |condition| are an invalid value.
    240 //   |MOJO_RESULT_ALREADY_EXISTS| if the trap already has a trigger associated
    241 //       with |context| or |handle|.
    242 MOJO_SYSTEM_EXPORT MojoResult
    243 MojoAddTrigger(MojoHandle trap_handle,
    244                MojoHandle handle,
    245                MojoHandleSignals signals,
    246                MojoTriggerCondition condition,
    247                uintptr_t context,
    248                const struct MojoAddTriggerOptions* options);
    249 
    250 // Removes a trigger from a trap.
    251 //
    252 // This ensures that the trigger is removed as soon as possible. Removal may
    253 // block an arbitrarily long time if the trap is already executing its handler.
    254 //
    255 // When removal is complete, the trap's handler is invoked one final time for
    256 // time for |context|, with the result |MOJO_RESULT_CANCELLED|.
    257 //
    258 // The same  behavior can be elicted by either closing the watched handle
    259 // associated with this trigger, or by closing |trap_handle| itself.
    260 //
    261 // Parameters:
    262 //   |trap_handle|: The handle of the trap from which to remove a trigger.
    263 //   |context|: The context of the trigger to be removed.
    264 //
    265 // Returns:
    266 //   |MOJO_RESULT_OK| if the trigger has been removed.
    267 //   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a trap handle.
    268 //   |MOJO_RESULT_NOT_FOUND| if there is no trigger registered on this trap for
    269 //       the given value of |context|.
    270 MOJO_SYSTEM_EXPORT MojoResult
    271 MojoRemoveTrigger(MojoHandle trap_handle,
    272                   uintptr_t context,
    273                   const struct MojoRemoveTriggerOptions* options);
    274 
    275 // Arms a trap, allowing it to invoke its event handler the next time any of its
    276 // triggers' conditions are met.
    277 //
    278 // Parameters:
    279 //   |trap_handle|: The handle of the trap to be armed.
    280 //   |num_blocking_events|: An address pointing to the number of elements
    281 //       available for storage at the address given by |blocking_events|.
    282 //       Optional and only used when |MOJO_RESULT_FAILED_PRECONDITION| is
    283 //       returned. See below.
    284 //   |blocking_events|: An output buffer for |MojoTrapEvent| structures to be
    285 //       filled in if one or more triggers would have tripped the trap
    286 //       immediately if it were armed. Optional and used only when
    287 //       |MOJO_RESULT_FAILED_PRECONDITION| is returned. See below.
    288 //
    289 // Returns:
    290 //   |MOJO_RESULT_OK| if the trap has been successfully armed.
    291 //       |num_blocking_events| and |blocking_events| are ignored.
    292 //   |MOJO_RESULT_NOT_FOUND| if the trap does not have any triggers.
    293 //       |num_blocking_events| and |blocking_events| are ignored.
    294 //   |MOJO_RESULT_INVALID_ARGUMENT| if |trap_handle| is not a valid trap handle,
    295 //       or if |num_blocking_events| is non-null but |blocking_events| is
    296 //       not.
    297 //   |MOJO_RESULT_FAILED_PRECONDITION| if one or more triggers would have
    298 //       tripped the trap immediately upon arming. If |num_blocking_events| is
    299 //       non-null, this assumes there is enough space for |*num_blocking_events|
    300 //       entries at the non-null address in |blocking_events|.
    301 //
    302 //       At most |*num_blocking_events| entries are populated there, with each
    303 //       entry corresponding to one of the triggers which would have tripped the
    304 //       trap. The actual number of entries populated is written to
    305 //       |*num_blocking_events| before returning.
    306 //
    307 //       If there are more ready triggers than available provided storage, the
    308 //       subset presented to the caller is arbitrary. The runtime makes an
    309 //       effort to circulate triggers returned by consecutive failed
    310 //       |MojoArmTrap()| calls so that callers may avoid handle starvation when
    311 //       observing a large number of active handles with a single trap.
    312 MOJO_SYSTEM_EXPORT MojoResult
    313 MojoArmTrap(MojoHandle trap_handle,
    314             const struct MojoArmTrapOptions* options,
    315             uint32_t* num_blocking_events,
    316             struct MojoTrapEvent* blocking_events);
    317 
    318 #ifdef __cplusplus
    319 }  // extern "C"
    320 #endif
    321 
    322 #endif  // MOJO_PUBLIC_C_SYSTEM_TRAP_H_
    323