timer_migration.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. #ifndef _KERNEL_TIME_MIGRATION_H
  3. #define _KERNEL_TIME_MIGRATION_H
  4. /* Per group capacity. Must be a power of 2! */
  5. #define TMIGR_CHILDREN_PER_GROUP 8
  6. /**
  7. * struct tmigr_event - a timer event associated to a CPU
  8. * @nextevt: The node to enqueue an event in the parent group queue
  9. * @cpu: The CPU to which this event belongs
  10. * @ignore: Hint whether the event could be ignored; it is set when
  11. * CPU or group is active;
  12. */
  13. struct tmigr_event {
  14. struct timerqueue_node nextevt;
  15. unsigned int cpu;
  16. bool ignore;
  17. };
  18. /**
  19. * struct tmigr_group - timer migration hierarchy group
  20. * @lock: Lock protecting the event information and group hierarchy
  21. * information during setup
  22. * @parent: Pointer to the parent group. Pointer is updated when a
  23. * new hierarchy level is added because of a CPU coming
  24. * online the first time. Once it is set, the pointer will
  25. * not be removed or updated. When accessing parent pointer
  26. * lock less to decide whether to abort a propagation or
  27. * not, it is not a problem. The worst outcome is an
  28. * unnecessary/early CPU wake up. But do not access parent
  29. * pointer several times in the same 'action' (like
  30. * activation, deactivation, check for remote expiry,...)
  31. * without holding the lock as it is not ensured that value
  32. * will not change.
  33. * @groupevt: Next event of the group which is only used when the
  34. * group is !active. The group event is then queued into
  35. * the parent timer queue.
  36. * Ignore bit of @groupevt is set when the group is active.
  37. * @next_expiry: Base monotonic expiry time of the next event of the
  38. * group; It is used for the racy lockless check whether a
  39. * remote expiry is required; it is always reliable
  40. * @events: Timer queue for child events queued in the group
  41. * @migr_state: State of the group (see union tmigr_state)
  42. * @level: Hierarchy level of the group; Required during setup
  43. * @numa_node: Required for setup only to make sure CPU and low level
  44. * group information is NUMA local. It is set to NUMA node
  45. * as long as the group level is per NUMA node (level <
  46. * tmigr_crossnode_level); otherwise it is set to
  47. * NUMA_NO_NODE
  48. * @num_children: Counter of group children to make sure the group is only
  49. * filled with TMIGR_CHILDREN_PER_GROUP; Required for setup
  50. * only
  51. * @groupmask: mask of the group in the parent group; is set during
  52. * setup and will never change; can be read lockless
  53. * @list: List head that is added to the per level
  54. * tmigr_level_list; is required during setup when a
  55. * new group needs to be connected to the existing
  56. * hierarchy groups
  57. */
  58. struct tmigr_group {
  59. raw_spinlock_t lock;
  60. struct tmigr_group *parent;
  61. struct tmigr_event groupevt;
  62. u64 next_expiry;
  63. struct timerqueue_head events;
  64. atomic_t migr_state;
  65. unsigned int level;
  66. int numa_node;
  67. unsigned int num_children;
  68. u8 groupmask;
  69. struct list_head list;
  70. };
  71. /**
  72. * struct tmigr_cpu - timer migration per CPU group
  73. * @lock: Lock protecting the tmigr_cpu group information
  74. * @online: Indicates whether the CPU is online; In deactivate path
  75. * it is required to know whether the migrator in the top
  76. * level group is to be set offline, while a timer is
  77. * pending. Then another online CPU needs to be notified to
  78. * take over the migrator role. Furthermore the information
  79. * is required in CPU hotplug path as the CPU is able to go
  80. * idle before the timer migration hierarchy hotplug AP is
  81. * reached. During this phase, the CPU has to handle the
  82. * global timers on its own and must not act as a migrator.
  83. * @idle: Indicates whether the CPU is idle in the timer migration
  84. * hierarchy
  85. * @remote: Is set when timers of the CPU are expired remotely
  86. * @tmgroup: Pointer to the parent group
  87. * @groupmask: mask of tmigr_cpu in the parent group
  88. * @wakeup: Stores the first timer when the timer migration
  89. * hierarchy is completely idle and remote expiry was done;
  90. * is returned to timer code in the idle path and is only
  91. * used in idle path.
  92. * @cpuevt: CPU event which could be enqueued into the parent group
  93. */
  94. struct tmigr_cpu {
  95. raw_spinlock_t lock;
  96. bool online;
  97. bool idle;
  98. bool remote;
  99. struct tmigr_group *tmgroup;
  100. u8 groupmask;
  101. u64 wakeup;
  102. struct tmigr_event cpuevt;
  103. };
  104. /**
  105. * union tmigr_state - state of tmigr_group
  106. * @state: Combined version of the state - only used for atomic
  107. * read/cmpxchg function
  108. * @struct: Split version of the state - only use the struct members to
  109. * update information to stay independent of endianness
  110. */
  111. union tmigr_state {
  112. u32 state;
  113. /**
  114. * struct - split state of tmigr_group
  115. * @active: Contains each mask bit of the active children
  116. * @migrator: Contains mask of the child which is migrator
  117. * @seq: Sequence counter needs to be increased when an update
  118. * to the tmigr_state is done. It prevents a race when
  119. * updates in the child groups are propagated in changed
  120. * order. Detailed information about the scenario is
  121. * given in the documentation at the begin of
  122. * timer_migration.c.
  123. */
  124. struct {
  125. u8 active;
  126. u8 migrator;
  127. u16 seq;
  128. } __packed;
  129. };
  130. #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
  131. extern void tmigr_handle_remote(void);
  132. extern bool tmigr_requires_handle_remote(void);
  133. extern void tmigr_cpu_activate(void);
  134. extern u64 tmigr_cpu_deactivate(u64 nextevt);
  135. extern u64 tmigr_cpu_new_timer(u64 nextevt);
  136. extern u64 tmigr_quick_check(u64 nextevt);
  137. #else
  138. static inline void tmigr_handle_remote(void) { }
  139. static inline bool tmigr_requires_handle_remote(void) { return false; }
  140. static inline void tmigr_cpu_activate(void) { }
  141. #endif
  142. #endif