1 /* 2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 17 #define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 18 19 #include <array> 20 #include <atomic> 21 #include <functional> 22 #include <list> 23 #include <map> 24 #include <mutex> 25 26 #include "inner_event.h" 27 #include "event_handler_errors.h" 28 #include "file_descriptor_listener.h" 29 #include "dumper.h" 30 31 namespace OHOS { 32 namespace AppExecFwk { 33 class IoWaiter; 34 class EventHandler; 35 class DeamonIoWaiter; 36 struct PendingTaskInfo; 37 38 enum class EventInsertType: uint32_t { 39 // Insert event at end 40 AT_END = 0, 41 // Insert event at front 42 AT_FRONT 43 }; 44 45 enum class Observer { 46 ARKTS_GC, 47 }; 48 49 enum class EventRunnerStage { 50 // enter loop 51 STAGE_ENTRY_RUNNER = 1<<0, 52 // exit loop 53 STAGE_EXIT_RUNNER = 1<<1, 54 // waiting 55 STAGE_BEFORE_WAITING = 1<<2, 56 // recover form sleeping 57 STAGE_AFTER_WAITING = 1<<3, 58 // insert vip task 59 STAGE_VIP_EXISTED = 1<<4, 60 // current queue not exists vip task 61 STAGE_VIP_NONE = 1<<5, 62 // invaild key 63 STAGE_INVAILD = 0, 64 }; 65 66 struct StageInfo { 67 // STAGE_BEFORE_WAITING, timesteap 68 int64_t timestamp; 69 // STAGE_BEFORE_WAITING, milliseconds 70 int32_t sleepTime; 71 // STAGE_AFTER_WAITING 72 int reason; 73 }; 74 75 using EventRunnerObserverCallBack = std::function<int(EventRunnerStage stage, const StageInfo* info)>; 76 77 struct EventRunnerObserver { 78 Observer observer; 79 uint32_t stages; 80 EventRunnerObserverCallBack notifyCb; ClearObserverEventRunnerObserver81 void ClearObserver() 82 { 83 stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD); 84 notifyCb = nullptr; 85 } 86 }; 87 88 struct ObserverTrace { 89 std::string source; 90 std::string stage; ObserverTraceObserverTrace91 ObserverTrace() {}; ObserverTraceObserverTrace92 ObserverTrace(std::string currentSource, std::string currentStage) 93 : source(currentSource), stage(currentStage) {} getTraceInfoObserverTrace94 std::string getTraceInfo() 95 { 96 std::string traceInfo; 97 traceInfo.append("Et-obs:"); 98 if (stage.empty()) { 99 traceInfo.append(" "); 100 } else { 101 traceInfo.append(stage); 102 } 103 traceInfo.append(","); 104 if (!source.empty()) { 105 traceInfo.append(source); 106 } 107 return traceInfo; 108 } 109 }; 110 111 #define NOW_NS std::chrono::duration_cast<std::chrono::nanoseconds>( \ 112 InnerEvent::Clock::now().time_since_epoch()).count() 113 #define CHECK_VSYNC_DELAY_NS 1000000 114 #define MAX_INIT_VSYNC_PERIOD_NS 34000000 115 #define MAX_CHECK_VSYNC_PERIOD_NS 69000000 116 #define VSYNC_TASK_DELAYMS 50 117 #define MS_TO_NS_RATIO 1000000 118 119 class EventQueue { 120 public: 121 // Priority for the events 122 enum class Priority : uint32_t { 123 // The highest priority queue, should be distributed until the tasks in the queue are completed. 124 VIP = 0, 125 // Event that should be distributed at once if possible. 126 IMMEDIATE, 127 // High priority event, sorted by handle time, should be distributed before low priority event. 128 HIGH, 129 // Normal event, sorted by handle time. 130 LOW, 131 // Event that should be distributed only if no other event right now. 132 IDLE, 133 }; 134 135 EventQueue(); 136 explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter); 137 virtual ~EventQueue(); 138 DISALLOW_COPY_AND_MOVE(EventQueue); 139 140 /** 141 * Insert an event into event queue with different priority. 142 * The events will be sorted by handle time. 143 * 144 * @param event Event instance which should be added into event queue. 145 * @param Priority Priority of the event 146 * @param insertType The type of insertint event to queue 147 * 148 * @see #Priority 149 */ 150 virtual bool Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW, 151 EventInsertType insertType = EventInsertType::AT_END) = 0; 152 153 /** 154 * Remove events if its owner is invalid, for base queue. 155 */ RemoveOrphan()156 virtual void RemoveOrphan() {}; 157 158 /** 159 * Remove events if its owner is invalid, for ffrt queue. 160 */ RemoveOrphanByHandlerId(const std::string & handlerId)161 virtual void RemoveOrphanByHandlerId(const std::string& handlerId) { (void)handlerId; }; 162 163 /** 164 * Remove all events. 165 */ 166 virtual void RemoveAll() = 0; 167 168 /** 169 * Remove events with specified requirements. 170 * 171 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 172 */ 173 virtual void Remove(const std::shared_ptr<EventHandler> &owner) = 0; 174 175 /** 176 * Remove events with specified requirements. 177 * 178 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 179 * @param innerEventId Remove events by event id. 180 */ 181 virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0; 182 183 /** 184 * Remove events with specified requirements. 185 * 186 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 187 * @param innerEventId Remove events by event id. 188 * @param param Remove events by value of param. 189 */ 190 virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param) = 0; 191 192 /** 193 * Remove events with specified requirements. 194 * 195 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 196 * @param name Remove events by name of the task. 197 */ 198 virtual bool Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name) = 0; 199 200 /** 201 * Add file descriptor listener for a file descriptor. 202 * 203 * @param fileDescriptor File descriptor. 204 * @param events Events from file descriptor, such as input, output, error 205 * @param listener Listener callback. 206 * @return Return 'ERR_OK' on success. 207 */ 208 virtual ErrCode AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events, 209 const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName, 210 Priority priority = Priority::HIGH) = 0; 211 212 /** 213 * Remove all file descriptor listeners for a specified owner. 214 * 215 * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'. 216 */ 217 virtual void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner) = 0; 218 219 /** 220 * Remove file descriptor listener for a file descriptor. 221 * 222 * @param fileDescriptor File descriptor. 223 */ 224 virtual void RemoveFileDescriptorListener(int32_t fileDescriptor) = 0; 225 226 /** 227 * Prepare event queue, before calling {@link #GetEvent}. 228 * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}. 229 */ 230 virtual void Prepare() = 0; 231 232 /** 233 * Exit from blocking in {@link #GetEvent}, and mark the event queue finished. 234 * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called. 235 */ 236 virtual void Finish() = 0; 237 238 /** 239 * Get event from event queue one by one. 240 * Before calling this method, developers should call {@link #Prepare} first. 241 * If none should be handled right now, the thread will be blocked in this method. 242 * Call {@link #Finish} to exit from blocking. 243 * 244 * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called. 245 * Otherwise returns event instance. 246 */ 247 virtual InnerEvent::Pointer GetEvent(); 248 249 /** 250 * Get expired event from event queue one by one. 251 * Before calling this method, developers should call {@link #Prepare} first. 252 * 253 * @param nextExpiredTime Output the expired time for the next event. 254 * @return Returns nullptr if none in event queue is expired. 255 * Otherwise returns event instance. 256 */ 257 virtual InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime); 258 259 /** 260 * Prints out the internal information about an object in the specified format, 261 * helping you diagnose internal errors of the object. 262 * 263 * @param dumper The Dumper object you have implemented to process the output internal information. 264 */ 265 virtual void Dump(Dumper &dumper) = 0; 266 267 /** 268 * Print out the internal information about an object in the specified format, 269 * helping you diagnose internal errors of the object. 270 * 271 * @param queueInfo queue Info. 272 */ 273 virtual void DumpQueueInfo(std::string& queueInfo) = 0; 274 275 /** 276 * Checks whether the current EventHandler is idle. 277 * 278 * @return Returns true if all events have been processed; returns false otherwise. 279 */ 280 virtual bool IsIdle() = 0; 281 282 /** 283 * Check whether this event queue is empty. 284 * 285 * @return If queue is empty return true otherwise return false. 286 */ 287 virtual bool IsQueueEmpty() = 0; 288 289 /** 290 * Check whether an event with the given ID can be found among the events that have been sent but not processed. 291 * 292 * @param owner Owner of the event which is point to an instance of 'EventHandler'. 293 * @param innerEventId The id of the event. 294 */ 295 virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0; 296 297 /** 298 * Check whether an event carrying the given param can be found among the events that have been sent but not 299 * processed. 300 * 301 * @param owner The owner of the event which is point to an instance of 'EventHandler'. 302 * @param param The basic parameter of the event. 303 */ 304 virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param) = 0; 305 PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)306 virtual void PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event) { (void)event; } 307 PushHistoryQueueAfterDistribute()308 virtual void PushHistoryQueueAfterDistribute() {} 309 310 virtual bool HasPreferEvent(int basePrio) = 0; 311 312 virtual std::string DumpCurrentQueueSize() = 0; 313 314 /** 315 * Check whether there are currenty file descriptors is need to be processed. 316 */ 317 void CheckFileDescriptorEvent(); 318 319 /** 320 * Set waiter mode, true for deamon io waiter 321 */ SetIoWaiter(bool useDeamonIoWaiter)322 void SetIoWaiter(bool useDeamonIoWaiter) 323 { 324 useDeamonIoWaiter_ = useDeamonIoWaiter; 325 } 326 327 /** 328 * Get ffrt queue handler type, only for ffrt thread mode. 329 */ GetFfrtQueue()330 virtual void* GetFfrtQueue() { return nullptr; } 331 332 /** 333 * Insert task to ffrt queue, and wait to handled, only for ffrt thread mode. 334 */ 335 virtual bool InsertSyncEvent(InnerEvent::Pointer &event, Priority priority = Priority::LOW, 336 EventInsertType insertType = EventInsertType::AT_END) 337 { 338 (void)event; 339 (void)priority; 340 (void)insertType; 341 return true; 342 } 343 344 /** 345 * Get pending task info 346 */ 347 virtual PendingTaskInfo QueryPendingTaskInfo(int32_t fileDescriptor) = 0; 348 /** 349 * add observer 350 * 351 * @param observer runner observer. 352 * @param stages The stages of observer 353 * @param callback observer callback. 354 */ AddObserver(Observer observer,uint32_t stages,EventRunnerObserverCallBack callback)355 void AddObserver(Observer observer, uint32_t stages, EventRunnerObserverCallBack callback) 356 { 357 observer_.observer = observer; 358 observer_.notifyCb = callback; 359 observer_.stages = stages; 360 } 361 362 /** 363 * Cancel And Wait 364 */ 365 virtual void CancelAndWait() = 0; 366 367 /** 368 * notify GC Observer vip events finished 369 */ 370 virtual void NotifyObserverVipDone(const InnerEvent::Pointer &event); 371 372 /** 373 * Get the first event handle time in the prioritized task queue. 374 * 375 * @param priority The specified priority. 376 */ 377 virtual inline uint64_t GetQueueFirstEventHandleTime(int32_t priority) = 0; 378 379 /** 380 * Set the lazy mode for AppVsync 381 */ 382 void SetVsyncLazyMode(bool isLazy); 383 384 /** 385 * Set the first policy of AppVsync 386 */ 387 void SetVsyncFirst(bool isFirst); 388 389 /** 390 * the vsync task is comming. 391 */ DispatchVsyncTaskNotify()392 inline void DispatchVsyncTaskNotify() 393 { 394 ++sumOfPendingVsync_; 395 needEpoll_ = true; 396 vsyncCheckTime_ = INT64_MAX; 397 } 398 399 /** 400 * the vsync task be handled. 401 */ HandleVsyncTaskNotify()402 inline void HandleVsyncTaskNotify() 403 { 404 --sumOfPendingVsync_; 405 } 406 407 /** 408 * set the barrier mode. 409 */ SetBarrierMode(bool isBarrierMode)410 inline void SetBarrierMode(bool isBarrierMode) 411 { 412 isBarrierMode_ = isBarrierMode; 413 } 414 415 /** 416 * get the barrier mode. 417 */ IsBarrierMode()418 inline bool IsBarrierMode() 419 { 420 return isBarrierMode_; 421 } 422 423 /** 424 * get the delay time of vsync task. 425 */ GetDelayTimeOfVsyncTask()426 inline int64_t GetDelayTimeOfVsyncTask() 427 { 428 int64_t now = NOW_NS; 429 return isLazyMode_.load()? INT32_MAX : ((now > vsyncCheckTime_)? 430 VSYNC_TASK_DELAYMS - (now - vsyncCheckTime_ + CHECK_VSYNC_DELAY_NS) / MS_TO_NS_RATIO : VSYNC_TASK_DELAYMS); 431 } 432 433 /** 434 * update the timestamp of epoll vsyncfd. 435 */ UpdateVsyncCheckTime(int64_t lastFrameTime,int64_t period)436 inline void UpdateVsyncCheckTime(int64_t lastFrameTime, int64_t period) 437 { 438 //In order to epolling vsync fd successfully, we delay a time(CHECK_VSYNC_DELAY_NS). 439 if (__builtin_expect(period > 0, 1)) { 440 int64_t now = NOW_NS; 441 vsyncPeriod_ = (period > MAX_INIT_VSYNC_PERIOD_NS) ? MAX_INIT_VSYNC_PERIOD_NS : period; 442 vsyncCheckTime_ = (lastFrameTime > now) ? (now + CHECK_VSYNC_DELAY_NS + ((lastFrameTime - now) % period)) : 443 (now + period + CHECK_VSYNC_DELAY_NS - ((now - lastFrameTime) % period)); 444 } 445 } 446 447 protected: 448 void RemoveInvalidFileDescriptor(); 449 450 /** 451 * Add file descriptor base. 452 * 453 * @param fileDescriptor File descriptor. 454 * @param events Events from file descriptor, such as input, output, error 455 * @param listener Listener callback. 456 * @param taskName task name. 457 * @param Priority Priority of the event. 458 * @return Return result ErrCode. 459 */ 460 ErrCode AddFileDescriptorListenerBase(int32_t fileDescriptor, uint32_t events, 461 const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName, 462 Priority priority); 463 464 /** 465 * Add file descriptor by fd. 466 * 467 * @param fileDescriptor File descriptor. 468 * @param events Events from file descriptor, such as input, output, error 469 * @param taskName task name. 470 * @param listener Listener callback. 471 * @param Priority Priority of the event. 472 * @return Return result boolean. 473 */ 474 bool AddFileDescriptorByFd(int32_t fileDescriptor, uint32_t events, const std::string &taskName, 475 const std::shared_ptr<FileDescriptorListener>& listener, EventQueue::Priority priority); 476 477 bool EnsureIoWaiterLocked(const std::shared_ptr<FileDescriptorListener>& listener); 478 479 /** 480 * handle file descriptor event. 481 * 482 * @param fileDescriptor File descriptor. 483 * @param events Events from file descriptor, such as input, output, error 484 * @param name task name. 485 * @param Priority Priority of the event. 486 */ 487 void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events, const std::string &name, 488 Priority priority); 489 490 /** 491 * remove listener by owner. 492 * 493 * @param owner current eventhandler. 494 */ 495 void RemoveListenerByOwner(const std::shared_ptr<EventHandler> &owner); 496 497 /** 498 * remove listener by fd. 499 * 500 * @param fileDescriptor fd. 501 */ 502 void RemoveListenerByFd(int32_t fileDescriptor); 503 504 void PrepareBase(); 505 506 void FinishBase(); 507 508 void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock, bool vsyncOnly = false); 509 510 /** 511 * Try epoll fds according to the vsync info. 512 */ 513 void TryEpollFd(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock); 514 515 std::mutex queueLock_; 516 517 std::atomic_bool usable_ {true}; 518 519 bool isIdle_ {true}; 520 521 // Mark if the event queue is finished. 522 bool finished_ {true}; 523 524 // IO waiter used to block if no events while calling 'GetEvent'. 525 std::shared_ptr<IoWaiter> ioWaiter_; 526 527 // select different epoll 528 bool useDeamonIoWaiter_ = false; 529 530 // File descriptor listeners to handle IO events. 531 std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_; 532 533 EventRunnerObserver observer_ = {.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD), 534 .notifyCb = nullptr}; 535 536 int8_t sumOfPendingVsync_ = 0; 537 bool needEpoll_ = false; 538 std::atomic_bool isLazyMode_ = true; 539 bool isBarrierMode_ = false; 540 int64_t vsyncPeriod_ = INT64_MAX; 541 int64_t vsyncCheckTime_ = INT64_MAX; 542 543 private: 544 std::shared_ptr<FileDescriptorListener> GetListenerByfd(int32_t FileDescriptor); 545 }; 546 } // namespace AppExecFwk 547 } // namespace OHOS 548 549 #endif // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H 550