event_loop.h revision 53bc18a9e15f478ea0332a733b77c718114a8610
1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef CHRE_CORE_EVENT_LOOP_H_ 18#define CHRE_CORE_EVENT_LOOP_H_ 19 20#include "chre/core/event.h" 21#include "chre/core/nanoapp.h" 22#include "chre/core/timer_pool.h" 23#include "chre/platform/mutex.h" 24#include "chre/platform/platform_nanoapp.h" 25#include "chre/platform/power_control_manager.h" 26#include "chre/util/dynamic_vector.h" 27#include "chre/util/fixed_size_blocking_queue.h" 28#include "chre/util/non_copyable.h" 29#include "chre/util/synchronized_memory_pool.h" 30#include "chre/util/unique_ptr.h" 31#include "chre_api/chre/event.h" 32 33namespace chre { 34 35/** 36 * The EventLoop represents a single thread of execution that is shared among 37 * zero or more nanoapps. As the name implies, the EventLoop is built around a 38 * loop that delivers events to the nanoapps managed within for processing. 39 */ 40class EventLoop : public NonCopyable { 41 public: 42 /** 43 * Synchronous callback used with forEachNanoapp 44 */ 45 typedef void (NanoappCallbackFunction)(const Nanoapp *nanoapp, void *data); 46 47 /** 48 * Searches the set of nanoapps managed by this EventLoop for one with the 49 * given app ID. If found, provides its instance ID, which can be used to send 50 * events to the app. 51 * 52 * This function is safe to call from any thread. 53 * 54 * @param appId The nanoapp identifier to search for. 55 * @param instanceId If this function returns true, will be populated with the 56 * instanceId associated with the given appId; otherwise unmodified. 57 * Must not be null. 58 * @return true if the given app ID was found and instanceId was populated 59 */ 60 bool findNanoappInstanceIdByAppId(uint64_t appId, uint32_t *instanceId) const; 61 62 /** 63 * Iterates over the list of Nanoapps managed by this EventLoop, and invokes 64 * the supplied callback for each one. This holds a lock if necessary, so it 65 * is safe to call from any thread. 66 * 67 * @param callback Function to invoke on each Nanoapp (synchronously) 68 * @param data Arbitrary data to pass to the callback 69 */ 70 void forEachNanoapp(NanoappCallbackFunction *callback, void *data); 71 72 /** 73 * Invokes a message to host free callback supplied by the given nanoapp 74 * (identified by app ID). Ensures that the calling context is updated 75 * appropriately. 76 * 77 * @param appId Identifies the nanoapp that sent this message and supplied the 78 * free callback 79 * @param freeFunction The non-null message free callback given by the nanoapp 80 * @param message Pointer to the message data 81 * @param messageSize Size of the message 82 */ 83 void invokeMessageFreeFunction( 84 uint64_t appId, chreMessageFreeFunction *freeFunction, void *message, 85 size_t messageSize); 86 87 /** 88 * Invokes the Nanoapp's start callback, and if successful, adds it to the 89 * set of Nanoapps managed by this EventLoop. This function must only be 90 * called from the context of the thread that runs this event loop (i.e. from 91 * the same thread that will call run() or from a callback invoked within 92 * run()). 93 * 94 * @param nanoapp The nanoapp that will be started. Upon success, this 95 * UniquePtr will become invalid, as the underlying Nanoapp instance 96 * will have been transferred to be managed by this EventLoop. 97 * @return true if the app was started successfully 98 */ 99 bool startNanoapp(UniquePtr<Nanoapp>& nanoapp); 100 101 /** 102 * Stops and unloads a nanoapp identified by its instance ID. The end entry 103 * point will be invoked, and the chre::Nanoapp instance will be destroyed. 104 * After this function returns, all references to the Nanoapp instance are 105 * invalidated. 106 * 107 * @param instanceId The nanoapp's unique instance identifier 108 * @param allowSystemNanoappUnload If false, this function will reject 109 * attempts to unload a system nanoapp 110 * 111 * @return true if the nanoapp with the given instance ID was found & unloaded 112 */ 113 bool unloadNanoapp(uint32_t instanceId, bool allowSystemNanoappUnload); 114 115 /** 116 * Executes the loop that blocks on the event queue and delivers received 117 * events to nanoapps. Only returns after stop() is called (from another 118 * context). 119 */ 120 void run(); 121 122 /** 123 * Signals the event loop currently executing in run() to exit gracefully at 124 * the next available opportunity. This function is thread-safe. 125 */ 126 void stop(); 127 128 /** 129 * Posts an event to a nanoapp that is currently running (or all nanoapps if 130 * the target instance ID is kBroadcastInstanceId). If the senderInstanceId is 131 * kSystemInstanceId and the event fails to post, this is considered a fatal 132 * error. 133 * 134 * This function is safe to call from any thread. 135 * 136 * @param eventType The type of data being posted. 137 * @param eventData The data being posted. 138 * @param freeCallback The callback to invoke when the event is no longer 139 * needed. 140 * @param senderInstanceId The instance ID of the sender of this event. 141 * @param targetInstanceId The instance ID of the destination of this event. 142 * 143 * @return true if the event was successfully added to the queue. Note that 144 * unlike chreSendEvent, this does *not* invoke the free callback if 145 * it failed to post the event. 146 * 147 * @see chreSendEvent 148 */ 149 bool postEvent(uint16_t eventType, void *eventData, 150 chreEventCompleteFunction *freeCallback, 151 uint32_t senderInstanceId = kSystemInstanceId, 152 uint32_t targetInstanceId = kBroadcastInstanceId); 153 154 /** 155 * Post an event to a nanoapp. If it fails, free the event with freeCallback. 156 * 157 * @see postEvent 158 */ 159 bool postEventOrFree(uint16_t eventType, void *eventData, 160 chreEventCompleteFunction *freeCallback, 161 uint32_t senderInstanceId = kSystemInstanceId, 162 uint32_t targetInstanceId = kBroadcastInstanceId); 163 164 /** 165 * Returns a pointer to the currently executing Nanoapp, or nullptr if none is 166 * currently executing. Must only be called from within the thread context 167 * associated with this EventLoop. 168 * 169 * @return the currently executing nanoapp, or nullptr 170 */ 171 Nanoapp *getCurrentNanoapp() const { 172 return mCurrentApp; 173 } 174 175 /** 176 * Gets the number of nanoapps currently associated with this event loop. Must 177 * only be called within the context of this EventLoop. 178 * 179 * @return The number of nanoapps managed by this event loop 180 */ 181 size_t getNanoappCount() const { 182 return mNanoapps.size(); 183 } 184 185 /** 186 * Obtains the TimerPool associated with this event loop. 187 * 188 * @return The timer pool owned by this event loop. 189 */ 190 TimerPool& getTimerPool() { 191 return mTimerPool; 192 } 193 194 /** 195 * Searches the set of nanoapps managed by this EventLoop for one with the 196 * given instance ID. 197 * 198 * This function is safe to call from any thread. 199 * 200 * @param instanceId The nanoapp instance ID to search for. 201 * @return a pointer to the found nanoapp or nullptr if no match was found. 202 */ 203 Nanoapp *findNanoappByInstanceId(uint32_t instanceId) const; 204 205 /** 206 * Looks for an app with the given ID and if found, populates info with its 207 * metadata. Safe to call from any thread. 208 * 209 * @see chreGetNanoappInfoByAppId 210 */ 211 bool populateNanoappInfoForAppId(uint64_t appId, 212 struct chreNanoappInfo *info) const; 213 214 /** 215 * Looks for an app with the given instance ID and if found, populates info 216 * with its metadata. Safe to call from any thread. 217 * 218 * @see chreGetNanoappInfoByInstanceId 219 */ 220 bool populateNanoappInfoForInstanceId(uint32_t instanceId, 221 struct chreNanoappInfo *info) const; 222 223 /** 224 * @return true if the current Nanoapp (or entire CHRE) is being unloaded, and 225 * therefore it should not be allowed to send events or messages, etc. 226 */ 227 bool currentNanoappIsStopping() const; 228 229 /** 230 * Prints state in a string buffer. Must only be called from the context of 231 * the main CHRE thread. 232 * 233 * @param buffer Pointer to the start of the buffer. 234 * @param bufferPos Pointer to buffer position to start the print (in-out). 235 * @param size Size of the buffer in bytes. 236 * 237 * @return true if entire log printed, false if overflow or error. 238 */ 239 bool logStateToBuffer(char *buffer, size_t *bufferPos, 240 size_t bufferSize) const; 241 242 243 /** 244 * Returns a reference to the power control manager. This allows power 245 * controls from subsystems outside the event loops. 246 */ 247 PowerControlManager& getPowerControlManager() { 248 return mPowerControlManager; 249 } 250 251 private: 252 //! The maximum number of events that can be active in the system. 253 static constexpr size_t kMaxEventCount = 96; 254 255 //! The minimum number of events to reserve in the event pool for system 256 //! events. 257 static constexpr size_t kMinReservedSystemEventCount = 16; 258 259 //! The maximum number of events that are awaiting to be scheduled. These 260 //! events are in a queue to be distributed to apps. 261 static constexpr size_t kMaxUnscheduledEventCount = 96; 262 263 //! The memory pool to allocate incoming events from. 264 SynchronizedMemoryPool<Event, kMaxEventCount> mEventPool; 265 266 //! The timer used schedule timed events for tasks running in this event loop. 267 TimerPool mTimerPool; 268 269 //! The list of nanoapps managed by this event loop. 270 DynamicVector<UniquePtr<Nanoapp>> mNanoapps; 271 272 //! This lock *must* be held whenever we: 273 //! (1) make changes to the mNanoapps vector, or 274 //! (2) read the mNanoapps vector from a thread other than the one 275 //! associated with this EventLoop 276 //! It is not necessary to acquire the lock when reading mNanoapps from within 277 //! the thread context of this EventLoop. 278 mutable Mutex mNanoappsLock; 279 280 //! The blocking queue of incoming events from the system that have not been 281 //! distributed out to apps yet. 282 FixedSizeBlockingQueue<Event *, kMaxUnscheduledEventCount> mEvents; 283 284 // TODO: should probably be atomic to be fully correct 285 volatile bool mRunning = true; 286 287 //! The nanoapp that is currently executing - must be set any time we call 288 //! into the nanoapp's entry points or callbacks 289 Nanoapp *mCurrentApp = nullptr; 290 291 //! Set to the nanoapp we are in the process of unloading in unloadNanoapp() 292 Nanoapp *mStoppingNanoapp = nullptr; 293 294 //! The object which manages power related controls. 295 PowerControlManager mPowerControlManager; 296 297 //! The maximum number of events ever waiting in the event pool. 298 size_t mMaxEventPoolUsage = 0; 299 300 /** 301 * Allolcates an event from the event pool and post it. 302 * 303 * @return true if the event has been successfully allocated and posted. 304 * 305 * @see postEvent and postEventOrFree 306 */ 307 bool allocateAndPostEvent(uint16_t eventType, void *eventData, 308 chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId, 309 uint32_t targetInstanceId); 310 311 /** 312 * Do one round of Nanoapp event delivery, only considering events in 313 * Nanoapps' own queues (not mEvents). 314 * 315 * @return true if there are more events pending in Nanoapps' own queues 316 */ 317 bool deliverEvents(); 318 319 /** 320 * Delivers the next event pending in the Nanoapp's queue, and takes care of 321 * freeing events once they have been delivered to all nanoapps. Must only be 322 * called after confirming that the app has at least 1 pending event. 323 * 324 * @return true if the nanoapp has another event pending in its queue 325 */ 326 bool deliverNextEvent(const UniquePtr<Nanoapp>& app); 327 328 /** 329 * Given an event pulled from the main incoming event queue (mEvents), deliver 330 * it to all Nanoapps that should receive the event, or free the event if 331 * there are no valid recipients. 332 * 333 * @param event The Event to distribute to Nanoapps 334 */ 335 void distributeEvent(Event *event); 336 337 /** 338 * Distribute all events pending in the inbound event queue. Note that this 339 * function only guarantees that any events in the inbound queue at the time 340 * it is called will be distributed to Nanoapp event queues - new events may 341 * still be posted during or after this function call from other threads as 342 * long as postEvent() will accept them. 343 */ 344 void flushInboundEventQueue(); 345 346 /** 347 * Delivers events pending in Nanoapps' own queues until they are all empty. 348 */ 349 void flushNanoappEventQueues(); 350 351 /** 352 * Call after when an Event has been delivered to all intended recipients. 353 * Invokes the event's free callback (if given) and releases resources. 354 * 355 * @param event The event to be freed 356 */ 357 void freeEvent(Event *event); 358 359 /** 360 * Finds a Nanoapp with the given 64-bit appId. 361 * 362 * Only safe to call within this EventLoop's thread, or if mNanoappsLock is 363 * held. 364 * 365 * @param appId Nanoapp ID 366 * @return Pointer to Nanoapp instance in this EventLoop with the given app 367 * ID, or nullptr if not found 368 */ 369 Nanoapp *lookupAppByAppId(uint64_t appId) const; 370 371 /** 372 * Finds a Nanoapp with the given instanceId. 373 * 374 * Only safe to call within this EventLoop's thread, or if mNanoappsLock is 375 * held. 376 * 377 * @param instanceId Nanoapp instance identifier 378 * @return Nanoapp with the given instanceId, or nullptr if not found 379 */ 380 Nanoapp *lookupAppByInstanceId(uint32_t instanceId) const; 381 382 /** 383 * Sends an event with payload struct chreNanoappInfo populated from the given 384 * Nanoapp instance to inform other nanoapps about it starting/stopping. 385 * 386 * @param eventType Should be one of CHRE_EVENT_NANOAPP_{STARTED, STOPPED} 387 * @param nanoapp The nanoapp instance whose status has changed 388 */ 389 void notifyAppStatusChange(uint16_t eventType, const Nanoapp& nanoapp); 390 391 /** 392 * Stops and unloads the Nanoapp at the given index in mNanoapps. 393 * 394 * IMPORTANT: prior to calling this function, the event queues must be in a 395 * safe condition for removal of this nanoapp. This means that there must not 396 * be any pending events in this nanoapp's queue, and there must not be any 397 * outstanding events sent by this nanoapp, as they may reference the 398 * nanoapp's own memory (even if there is no free callback). 399 */ 400 void unloadNanoappAtIndex(size_t index); 401}; 402 403} // namespace chre 404 405#endif // CHRE_CORE_EVENT_LOOP_H_ 406