mali_kbase_js_policy_cfs.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /*
  2. *
  3. * (C) COPYRIGHT 2011-2015 ARM Limited. All rights reserved.
  4. *
  5. * This program is free software and is provided to you under the terms of the
  6. * GNU General Public License version 2 as published by the Free Software
  7. * Foundation, and any use by you of this program is subject to the terms
  8. * of such GNU licence.
  9. *
  10. * A copy of the licence is included with the program, and can also be obtained
  11. * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  12. * Boston, MA 02110-1301, USA.
  13. *
  14. */
  15. /*
  16. * Job Scheduler: Completely Fair Policy Implementation
  17. */
  18. #include <mali_kbase.h>
  19. #include <mali_kbase_js.h>
  20. #include <mali_kbase_js_policy_cfs.h>
  21. #include <linux/version.h>
  22. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
  23. #include <linux/sched/rt.h>
  24. #endif
  25. /**
  26. * Define for when dumping is enabled.
  27. * This should not be based on the instrumentation level as whether dumping is enabled for a particular level is down to the integrator.
  28. * However this is being used for now as otherwise the cinstr headers would be needed.
  29. */
  30. #define CINSTR_DUMPING_ENABLED (2 == MALI_INSTRUMENTATION_LEVEL)
  31. /* Fixed point constants used for runtime weight calculations */
  32. #define WEIGHT_FIXEDPOINT_SHIFT 10
  33. #define WEIGHT_TABLE_SIZE 40
  34. #define WEIGHT_0_NICE (WEIGHT_TABLE_SIZE/2)
  35. #define WEIGHT_0_VAL (1 << WEIGHT_FIXEDPOINT_SHIFT)
  36. #define PROCESS_PRIORITY_MIN (-20)
  37. #define PROCESS_PRIORITY_MAX (19)
  38. /* Defines for easy asserts 'is scheduled'/'is queued'/'is neither queued norscheduled' */
  39. #define KBASEP_JS_CHECKFLAG_QUEUED (1u << 0) /**< Check the queued state */
  40. #define KBASEP_JS_CHECKFLAG_SCHEDULED (1u << 1) /**< Check the scheduled state */
  41. #define KBASEP_JS_CHECKFLAG_IS_QUEUED (1u << 2) /**< Expect queued state to be set */
  42. #define KBASEP_JS_CHECKFLAG_IS_SCHEDULED (1u << 3) /**< Expect scheduled state to be set */
  43. enum {
  44. KBASEP_JS_CHECK_NOTQUEUED = KBASEP_JS_CHECKFLAG_QUEUED,
  45. KBASEP_JS_CHECK_NOTSCHEDULED = KBASEP_JS_CHECKFLAG_SCHEDULED,
  46. KBASEP_JS_CHECK_QUEUED = KBASEP_JS_CHECKFLAG_QUEUED | KBASEP_JS_CHECKFLAG_IS_QUEUED,
  47. KBASEP_JS_CHECK_SCHEDULED = KBASEP_JS_CHECKFLAG_SCHEDULED | KBASEP_JS_CHECKFLAG_IS_SCHEDULED
  48. };
  49. typedef u32 kbasep_js_check;
  50. /*
  51. * Private Functions
  52. */
  53. /* Table autogenerated using util built from: base/tools/gen_cfs_weight_of_prio/ */
  54. /* weight = 1.25 */
  55. static const int weight_of_priority[] = {
  56. /* -20 */ 11, 14, 18, 23,
  57. /* -16 */ 29, 36, 45, 56,
  58. /* -12 */ 70, 88, 110, 137,
  59. /* -8 */ 171, 214, 268, 335,
  60. /* -4 */ 419, 524, 655, 819,
  61. /* 0 */ 1024, 1280, 1600, 2000,
  62. /* 4 */ 2500, 3125, 3906, 4883,
  63. /* 8 */ 6104, 7630, 9538, 11923,
  64. /* 12 */ 14904, 18630, 23288, 29110,
  65. /* 16 */ 36388, 45485, 56856, 71070
  66. };
  67. /*
  68. * Note: There is nothing to stop the priority of the ctx containing
  69. * ctx_info changing during or immediately after this function is called
  70. * (because its jsctx_mutex cannot be held during IRQ). Therefore, this
  71. * function should only be seen as a heuristic guide as to the priority weight
  72. * of the context.
  73. */
  74. static u64 priority_weight(struct kbasep_js_policy_cfs_ctx *ctx_info, u64 time_us)
  75. {
  76. u64 time_delta_us;
  77. int priority;
  78. priority = ctx_info->process_priority;
  79. /* Adjust runtime_us using priority weight if required */
  80. if (priority != 0 && time_us != 0) {
  81. int clamped_priority;
  82. /* Clamp values to min..max weights */
  83. if (priority > PROCESS_PRIORITY_MAX)
  84. clamped_priority = PROCESS_PRIORITY_MAX;
  85. else if (priority < PROCESS_PRIORITY_MIN)
  86. clamped_priority = PROCESS_PRIORITY_MIN;
  87. else
  88. clamped_priority = priority;
  89. /* Fixed point multiplication */
  90. time_delta_us = (time_us * weight_of_priority[WEIGHT_0_NICE + clamped_priority]);
  91. /* Remove fraction */
  92. time_delta_us = time_delta_us >> WEIGHT_FIXEDPOINT_SHIFT;
  93. /* Make sure the time always increases */
  94. if (0 == time_delta_us)
  95. time_delta_us++;
  96. } else {
  97. time_delta_us = time_us;
  98. }
  99. return time_delta_us;
  100. }
  101. #if KBASE_TRACE_ENABLE
  102. static int kbasep_js_policy_trace_get_refcnt_nolock(struct kbase_device *kbdev, struct kbase_context *kctx)
  103. {
  104. struct kbasep_js_device_data *js_devdata;
  105. int as_nr;
  106. int refcnt = 0;
  107. js_devdata = &kbdev->js_data;
  108. as_nr = kctx->as_nr;
  109. if (as_nr != KBASEP_AS_NR_INVALID) {
  110. struct kbasep_js_per_as_data *js_per_as_data;
  111. js_per_as_data = &js_devdata->runpool_irq.per_as_data[as_nr];
  112. refcnt = js_per_as_data->as_busy_refcount;
  113. }
  114. return refcnt;
  115. }
  116. static inline int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx)
  117. {
  118. unsigned long flags;
  119. struct kbasep_js_device_data *js_devdata;
  120. int refcnt = 0;
  121. js_devdata = &kbdev->js_data;
  122. spin_lock_irqsave(&js_devdata->runpool_irq.lock, flags);
  123. refcnt = kbasep_js_policy_trace_get_refcnt_nolock(kbdev, kctx);
  124. spin_unlock_irqrestore(&js_devdata->runpool_irq.lock, flags);
  125. return refcnt;
  126. }
  127. #else /* KBASE_TRACE_ENABLE */
  128. static inline int kbasep_js_policy_trace_get_refcnt(struct kbase_device *kbdev, struct kbase_context *kctx)
  129. {
  130. CSTD_UNUSED(kbdev);
  131. CSTD_UNUSED(kctx);
  132. return 0;
  133. }
  134. #endif /* KBASE_TRACE_ENABLE */
  135. /*
  136. * Non-private functions
  137. */
  138. int kbasep_js_policy_init(struct kbase_device *kbdev)
  139. {
  140. struct kbasep_js_device_data *js_devdata;
  141. struct kbasep_js_policy_cfs *policy_info;
  142. KBASE_DEBUG_ASSERT(kbdev != NULL);
  143. js_devdata = &kbdev->js_data;
  144. policy_info = &js_devdata->policy.cfs;
  145. atomic64_set(&policy_info->least_runtime_us, KBASEP_JS_RUNTIME_EMPTY);
  146. atomic64_set(&policy_info->rt_least_runtime_us, KBASEP_JS_RUNTIME_EMPTY);
  147. policy_info->head_runtime_us = 0;
  148. return 0;
  149. }
  150. void kbasep_js_policy_term(union kbasep_js_policy *js_policy)
  151. {
  152. CSTD_UNUSED(js_policy);
  153. }
  154. int kbasep_js_policy_init_ctx(struct kbase_device *kbdev, struct kbase_context *kctx)
  155. {
  156. struct kbasep_js_device_data *js_devdata;
  157. struct kbasep_js_policy_cfs_ctx *ctx_info;
  158. struct kbasep_js_policy_cfs *policy_info;
  159. int policy;
  160. KBASE_DEBUG_ASSERT(kbdev != NULL);
  161. KBASE_DEBUG_ASSERT(kctx != NULL);
  162. js_devdata = &kbdev->js_data;
  163. policy_info = &kbdev->js_data.policy.cfs;
  164. ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs;
  165. KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_INIT_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx));
  166. policy = current->policy;
  167. if (policy == SCHED_FIFO || policy == SCHED_RR) {
  168. ctx_info->process_rt_policy = true;
  169. ctx_info->process_priority = (((MAX_RT_PRIO - 1) - current->rt_priority) / 5) - 20;
  170. } else {
  171. ctx_info->process_rt_policy = false;
  172. ctx_info->process_priority = (current->static_prio - MAX_RT_PRIO) - 20;
  173. }
  174. /* Initial runtime (relative to least-run context runtime)
  175. *
  176. * This uses the Policy Queue's most up-to-date head_runtime_us by using the
  177. * queue mutex to issue memory barriers - also ensure future updates to
  178. * head_runtime_us occur strictly after this context is initialized */
  179. mutex_lock(&js_devdata->queue_mutex);
  180. /* No need to hold the the runpool_irq.lock here, because we're initializing
  181. * the value, and the context is definitely not being updated in the
  182. * runpool at this point. The queue_mutex ensures the memory barrier. */
  183. ctx_info->runtime_us = policy_info->head_runtime_us + priority_weight(ctx_info, (u64) js_devdata->cfs_ctx_runtime_init_slices * (u64) (js_devdata->ctx_timeslice_ns / 1000u));
  184. mutex_unlock(&js_devdata->queue_mutex);
  185. return 0;
  186. }
  187. void kbasep_js_policy_term_ctx(union kbasep_js_policy *js_policy, struct kbase_context *kctx)
  188. {
  189. struct kbasep_js_policy_cfs_ctx *ctx_info;
  190. struct kbasep_js_policy_cfs *policy_info;
  191. struct kbase_device *kbdev;
  192. KBASE_DEBUG_ASSERT(js_policy != NULL);
  193. KBASE_DEBUG_ASSERT(kctx != NULL);
  194. policy_info = &js_policy->cfs;
  195. ctx_info = &kctx->jctx.sched_info.runpool.policy_ctx.cfs;
  196. kbdev = container_of(js_policy, struct kbase_device, js_data.policy);
  197. KBASE_TRACE_ADD_REFCOUNT(kbdev, JS_POLICY_TERM_CTX, kctx, NULL, 0u, kbasep_js_policy_trace_get_refcnt(kbdev, kctx));
  198. /* No work to do */
  199. }
  200. /*
  201. * Job Chain Management
  202. */
  203. void kbasep_js_policy_log_job_result(union kbasep_js_policy *js_policy, struct kbase_jd_atom *katom, u64 time_spent_us)
  204. {
  205. struct kbasep_js_policy_cfs_ctx *ctx_info;
  206. struct kbase_context *parent_ctx;
  207. KBASE_DEBUG_ASSERT(js_policy != NULL);
  208. KBASE_DEBUG_ASSERT(katom != NULL);
  209. CSTD_UNUSED(js_policy);
  210. parent_ctx = katom->kctx;
  211. KBASE_DEBUG_ASSERT(parent_ctx != NULL);
  212. ctx_info = &parent_ctx->jctx.sched_info.runpool.policy_ctx.cfs;
  213. ctx_info->runtime_us += priority_weight(ctx_info, time_spent_us);
  214. katom->time_spent_us += time_spent_us;
  215. }
  216. bool kbasep_js_policy_ctx_has_priority(union kbasep_js_policy *js_policy, struct kbase_context *current_ctx, struct kbase_context *new_ctx)
  217. {
  218. struct kbasep_js_policy_cfs_ctx *current_ctx_info;
  219. struct kbasep_js_policy_cfs_ctx *new_ctx_info;
  220. KBASE_DEBUG_ASSERT(current_ctx != NULL);
  221. KBASE_DEBUG_ASSERT(new_ctx != NULL);
  222. CSTD_UNUSED(js_policy);
  223. current_ctx_info = &current_ctx->jctx.sched_info.runpool.policy_ctx.cfs;
  224. new_ctx_info = &new_ctx->jctx.sched_info.runpool.policy_ctx.cfs;
  225. if (!current_ctx_info->process_rt_policy && new_ctx_info->process_rt_policy)
  226. return true;
  227. if (current_ctx_info->process_rt_policy ==
  228. new_ctx_info->process_rt_policy)
  229. return true;
  230. return false;
  231. }