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