statistics.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /*
  2. * Copyright (c) 2021 Intel Corporation
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <kernel.h>
  7. #include <kernel_internal.h>
  8. #include <syscall_handler.h>
  9. #include <toolchain.h>
  10. #include <sys/mem_manage.h>
  11. extern struct k_mem_paging_stats_t paging_stats;
  12. #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM
  13. struct k_mem_paging_histogram_t z_paging_histogram_eviction;
  14. struct k_mem_paging_histogram_t z_paging_histogram_backing_store_page_in;
  15. struct k_mem_paging_histogram_t z_paging_histogram_backing_store_page_out;
  16. #ifdef CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS
  17. /*
  18. * The frequency of timing functions is highly dependent on
  19. * architecture, SoC or board. It is also not available at build time.
  20. * Therefore, the bounds for the timing histograms needs to be defined
  21. * externally to this file, and must be tailored to the platform
  22. * being used.
  23. */
  24. extern unsigned long
  25. k_mem_paging_eviction_histogram_bounds[
  26. CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS];
  27. extern unsigned long
  28. k_mem_paging_backing_store_histogram_bounds[
  29. CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS];
  30. #else
  31. #define NS_TO_CYC(ns) (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / 1000000U * ns)
  32. /*
  33. * This provides the upper bounds of the bins in eviction timing histogram.
  34. */
  35. __weak unsigned long
  36. k_mem_paging_eviction_histogram_bounds[CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS] = {
  37. NS_TO_CYC(1),
  38. NS_TO_CYC(5),
  39. NS_TO_CYC(10),
  40. NS_TO_CYC(50),
  41. NS_TO_CYC(100),
  42. NS_TO_CYC(200),
  43. NS_TO_CYC(500),
  44. NS_TO_CYC(1000),
  45. NS_TO_CYC(2000),
  46. ULONG_MAX
  47. };
  48. /*
  49. * This provides the upper bounds of the bins in backing store timing histogram
  50. * (both page-in and page-out).
  51. */
  52. __weak unsigned long
  53. k_mem_paging_backing_store_histogram_bounds[
  54. CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS] = {
  55. NS_TO_CYC(10),
  56. NS_TO_CYC(100),
  57. NS_TO_CYC(125),
  58. NS_TO_CYC(250),
  59. NS_TO_CYC(500),
  60. NS_TO_CYC(1000),
  61. NS_TO_CYC(2000),
  62. NS_TO_CYC(5000),
  63. NS_TO_CYC(10000),
  64. ULONG_MAX
  65. };
  66. #endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */
  67. #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */
  68. unsigned long z_num_pagefaults_get(void)
  69. {
  70. unsigned long ret;
  71. int key;
  72. key = irq_lock();
  73. ret = paging_stats.pagefaults.cnt;
  74. irq_unlock(key);
  75. return ret;
  76. }
  77. void z_impl_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats)
  78. {
  79. if (stats == NULL) {
  80. return;
  81. }
  82. /* Copy statistics */
  83. memcpy(stats, &paging_stats, sizeof(paging_stats));
  84. }
  85. #ifdef CONFIG_USERSPACE
  86. static inline
  87. void z_vrfy_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats)
  88. {
  89. Z_OOPS(Z_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats)));
  90. z_impl_k_mem_paging_stats_get(stats);
  91. }
  92. #include <syscalls/k_mem_paging_stats_get_mrsh.c>
  93. #endif /* CONFIG_USERSPACE */
  94. #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS
  95. void z_impl_k_mem_paging_thread_stats_get(struct k_thread *thread,
  96. struct k_mem_paging_stats_t *stats)
  97. {
  98. if ((thread == NULL) || (stats == NULL)) {
  99. return;
  100. }
  101. /* Copy statistics */
  102. memcpy(stats, &thread->paging_stats, sizeof(thread->paging_stats));
  103. }
  104. #ifdef CONFIG_USERSPACE
  105. static inline
  106. void z_vrfy_k_mem_paging_thread_stats_get(struct k_thread *thread,
  107. struct k_mem_paging_stats_t *stats)
  108. {
  109. Z_OOPS(Z_SYSCALL_OBJ(thread, K_OBJ_THREAD));
  110. Z_OOPS(Z_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats)));
  111. z_impl_k_mem_paging_thread_stats_get(thread, stats);
  112. }
  113. #include <syscalls/k_mem_paging_thread_stats_get_mrsh.c>
  114. #endif /* CONFIG_USERSPACE */
  115. #endif /* CONFIG_DEMAND_PAGING_THREAD_STATS */
  116. #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM
  117. void z_paging_histogram_init(void)
  118. {
  119. /*
  120. * Zero out the histogram structs and copy the bounds.
  121. * The copying is done as the histogram structs need
  122. * to be pinned in memory and never swapped out, while
  123. * the source bound array may not be pinned.
  124. */
  125. memset(&z_paging_histogram_eviction, 0, sizeof(z_paging_histogram_eviction));
  126. memcpy(z_paging_histogram_eviction.bounds,
  127. k_mem_paging_eviction_histogram_bounds,
  128. sizeof(z_paging_histogram_eviction.bounds));
  129. memset(&z_paging_histogram_backing_store_page_in, 0,
  130. sizeof(z_paging_histogram_backing_store_page_in));
  131. memcpy(z_paging_histogram_backing_store_page_in.bounds,
  132. k_mem_paging_backing_store_histogram_bounds,
  133. sizeof(z_paging_histogram_backing_store_page_in.bounds));
  134. memset(&z_paging_histogram_backing_store_page_out, 0,
  135. sizeof(z_paging_histogram_backing_store_page_out));
  136. memcpy(z_paging_histogram_backing_store_page_out.bounds,
  137. k_mem_paging_backing_store_histogram_bounds,
  138. sizeof(z_paging_histogram_backing_store_page_out.bounds));
  139. }
  140. /**
  141. * Increment the counter in the timing histogram.
  142. *
  143. * @param hist The timing histogram to be updated.
  144. * @param cycles Time spent in measured operation.
  145. */
  146. void z_paging_histogram_inc(struct k_mem_paging_histogram_t *hist,
  147. uint32_t cycles)
  148. {
  149. int idx;
  150. for (idx = 0;
  151. idx < CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM_NUM_BINS;
  152. idx++) {
  153. if (cycles <= hist->bounds[idx]) {
  154. hist->counts[idx]++;
  155. break;
  156. }
  157. }
  158. }
  159. void z_impl_k_mem_paging_histogram_eviction_get(
  160. struct k_mem_paging_histogram_t *hist)
  161. {
  162. if (hist == NULL) {
  163. return;
  164. }
  165. /* Copy statistics */
  166. memcpy(hist, &z_paging_histogram_eviction,
  167. sizeof(z_paging_histogram_eviction));
  168. }
  169. void z_impl_k_mem_paging_histogram_backing_store_page_in_get(
  170. struct k_mem_paging_histogram_t *hist)
  171. {
  172. if (hist == NULL) {
  173. return;
  174. }
  175. /* Copy histogram */
  176. memcpy(hist, &z_paging_histogram_backing_store_page_in,
  177. sizeof(z_paging_histogram_backing_store_page_in));
  178. }
  179. void z_impl_k_mem_paging_histogram_backing_store_page_out_get(
  180. struct k_mem_paging_histogram_t *hist)
  181. {
  182. if (hist == NULL) {
  183. return;
  184. }
  185. /* Copy histogram */
  186. memcpy(hist, &z_paging_histogram_backing_store_page_out,
  187. sizeof(z_paging_histogram_backing_store_page_out));
  188. }
  189. #ifdef CONFIG_USERSPACE
  190. static inline
  191. void z_vrfy_k_mem_paging_histogram_eviction_get(
  192. struct k_mem_paging_histogram_t *hist)
  193. {
  194. Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist)));
  195. z_impl_k_mem_paging_histogram_eviction_get(hist);
  196. }
  197. #include <syscalls/k_mem_paging_histogram_eviction_get_mrsh.c>
  198. static inline
  199. void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get(
  200. struct k_mem_paging_histogram_t *hist)
  201. {
  202. Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist)));
  203. z_impl_k_mem_paging_histogram_backing_store_page_in_get(hist);
  204. }
  205. #include <syscalls/k_mem_paging_histogram_backing_store_page_in_get_mrsh.c>
  206. static inline
  207. void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get(
  208. struct k_mem_paging_histogram_t *hist)
  209. {
  210. Z_OOPS(Z_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist)));
  211. z_impl_k_mem_paging_histogram_backing_store_page_out_get(hist);
  212. }
  213. #include <syscalls/k_mem_paging_histogram_backing_store_page_out_get_mrsh.c>
  214. #endif /* CONFIG_USERSPACE */
  215. #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */