starpurm_dlb.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2017,2018 Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. /* CPUSET routines */
  17. #define _GNU_SOURCE
  18. #include <sched.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <assert.h>
  23. #include <config.h>
  24. #include <hwloc.h>
  25. #ifdef HAVE_HWLOC_GLIBC_SCHED_H
  26. #include <hwloc/glibc-sched.h>
  27. #endif
  28. #include <pthread.h>
  29. #include <starpu.h>
  30. #include <starpurm.h>
  31. #include <starpurm_private.h>
  32. #ifndef STARPURM_HAVE_DLB
  33. #error "STARPU-RM DLB support not enabled"
  34. #endif
  35. #include <dlb_sp.h>
  36. /*
  37. * DLB interfacing
  38. */
  39. static dlb_handler_t dlb_handle;
  40. static cpu_set_t starpurm_process_mask;
  41. static hwloc_cpuset_t starpurm_process_cpuset;
  42. static struct s_starpurm *_starpurm = NULL;
  43. static pthread_mutex_t dlb_handle_mutex = PTHREAD_MUTEX_INITIALIZER;
  44. #if 0
  45. /* unused for now */
  46. static void _glibc_cpuset_to_hwloc_cpuset(const cpu_set_t *glibc_cpuset, hwloc_cpuset_t *hwloc_cpuset)
  47. {
  48. assert(_starpurm != NULL);
  49. assert(_starpurm->state != state_uninitialized);
  50. struct s_starpurm *rm = _starpurm;
  51. int status = hwloc_cpuset_from_glibc_sched_affinity(rm->topology, *hwloc_cpuset, glibc_cpuset, sizeof(cpu_set_t));
  52. assert(status == 0);
  53. }
  54. #endif
  55. static void _hwloc_cpuset_to_glibc_cpuset(const hwloc_cpuset_t hwloc_cpuset, cpu_set_t *glibc_cpuset)
  56. {
  57. assert(_starpurm != NULL);
  58. assert(_starpurm->state != state_uninitialized);
  59. struct s_starpurm *rm = _starpurm;
  60. int status = hwloc_cpuset_to_glibc_sched_affinity(rm->topology, hwloc_cpuset, glibc_cpuset, sizeof(cpu_set_t));
  61. assert(status == 0);
  62. }
  63. int starpurm_dlb_notify_starpu_worker_mask_going_to_sleep(const hwloc_cpuset_t hwloc_workers_cpuset)
  64. {
  65. int status = 0;
  66. pthread_mutex_lock(&dlb_handle_mutex);
  67. if (dlb_handle != NULL)
  68. {
  69. hwloc_cpuset_t hwloc_to_lend_cpuset = hwloc_bitmap_alloc();
  70. hwloc_cpuset_t hwloc_to_return_cpuset = hwloc_bitmap_alloc();
  71. hwloc_bitmap_zero(hwloc_to_lend_cpuset);
  72. hwloc_bitmap_zero(hwloc_to_return_cpuset);
  73. hwloc_bitmap_and(hwloc_to_lend_cpuset, hwloc_workers_cpuset, starpurm_process_cpuset);
  74. hwloc_bitmap_andnot(hwloc_to_return_cpuset, hwloc_workers_cpuset, starpurm_process_cpuset);
  75. if (!hwloc_bitmap_iszero(hwloc_to_lend_cpuset))
  76. {
  77. cpu_set_t glibc_to_lend_cpuset;
  78. CPU_ZERO(&glibc_to_lend_cpuset);
  79. _hwloc_cpuset_to_glibc_cpuset(hwloc_to_lend_cpuset, &glibc_to_lend_cpuset);
  80. DLB_LendCpuMask_sp(dlb_handle, &glibc_to_lend_cpuset);
  81. }
  82. if (!hwloc_bitmap_iszero(hwloc_to_return_cpuset))
  83. {
  84. cpu_set_t glibc_to_return_cpuset;
  85. CPU_ZERO(&glibc_to_return_cpuset);
  86. _hwloc_cpuset_to_glibc_cpuset(hwloc_to_return_cpuset, &glibc_to_return_cpuset);
  87. DLB_ReturnCpuMask_sp(dlb_handle, &glibc_to_return_cpuset);
  88. }
  89. hwloc_bitmap_free(hwloc_to_lend_cpuset);
  90. hwloc_bitmap_free(hwloc_to_return_cpuset);
  91. status = 1;
  92. }
  93. pthread_mutex_unlock(&dlb_handle_mutex);
  94. return status;
  95. }
  96. int starpurm_dlb_notify_starpu_worker_mask_waking_up(const hwloc_cpuset_t hwloc_workers_cpuset)
  97. {
  98. int status = 0;
  99. pthread_mutex_lock(&dlb_handle_mutex);
  100. if (dlb_handle != NULL)
  101. {
  102. hwloc_cpuset_t hwloc_to_reclaim_cpuset = hwloc_bitmap_alloc();
  103. hwloc_cpuset_t hwloc_to_acquire_cpuset = hwloc_bitmap_alloc();
  104. hwloc_bitmap_zero(hwloc_to_reclaim_cpuset);
  105. hwloc_bitmap_zero(hwloc_to_acquire_cpuset);
  106. hwloc_bitmap_and(hwloc_to_reclaim_cpuset, hwloc_workers_cpuset, starpurm_process_cpuset);
  107. hwloc_bitmap_andnot(hwloc_to_acquire_cpuset, hwloc_workers_cpuset, starpurm_process_cpuset);
  108. if (!hwloc_bitmap_iszero(hwloc_to_reclaim_cpuset))
  109. {
  110. cpu_set_t glibc_to_reclaim_cpuset;
  111. CPU_ZERO(&glibc_to_reclaim_cpuset);
  112. _hwloc_cpuset_to_glibc_cpuset(hwloc_to_reclaim_cpuset, &glibc_to_reclaim_cpuset);
  113. DLB_ReclaimCpuMask_sp(dlb_handle, &glibc_to_reclaim_cpuset);
  114. }
  115. if (!hwloc_bitmap_iszero(hwloc_to_acquire_cpuset))
  116. {
  117. cpu_set_t glibc_to_acquire_cpuset;
  118. CPU_ZERO(&glibc_to_acquire_cpuset);
  119. _hwloc_cpuset_to_glibc_cpuset(hwloc_to_acquire_cpuset, &glibc_to_acquire_cpuset);
  120. DLB_AcquireCpuMask_sp(dlb_handle, &glibc_to_acquire_cpuset);
  121. }
  122. hwloc_bitmap_free(hwloc_to_reclaim_cpuset);
  123. hwloc_bitmap_free(hwloc_to_acquire_cpuset);
  124. status = 1;
  125. }
  126. pthread_mutex_unlock(&dlb_handle_mutex);
  127. return status;
  128. }
  129. #ifdef STARPURM_STARPU_HAVE_WORKER_CALLBACKS
  130. static void _dlb_callback_enable_cpu(int cpuid)
  131. {
  132. starpurm_enqueue_event_cpu_unit_available(cpuid);
  133. }
  134. static void _dlb_callback_disable_cpu(int cpuid)
  135. {
  136. /* nothing */
  137. }
  138. #endif
  139. void starpurm_dlb_init(struct s_starpurm *rm)
  140. {
  141. _starpurm = rm;
  142. CPU_ZERO(&starpurm_process_mask);
  143. starpurm_process_cpuset = hwloc_bitmap_dup(rm->selected_cpuset);
  144. hwloc_bitmap_and(starpurm_process_cpuset, starpurm_process_cpuset, rm->initially_owned_cpuset_mask);
  145. _hwloc_cpuset_to_glibc_cpuset(starpurm_process_cpuset, &starpurm_process_mask);
  146. pthread_mutex_lock(&dlb_handle_mutex);
  147. dlb_handle = DLB_Init_sp(0, &starpurm_process_mask, "--policy=new --mode=async");
  148. /* cpu-based callbacks are mutually exclusive with mask-based callbacks,
  149. * we only register cpu-based callbacks */
  150. #ifdef STARPURM_STARPU_HAVE_WORKER_CALLBACKS
  151. assert(DLB_CallbackSet_sp(dlb_handle, dlb_callback_disable_cpu, (dlb_callback_t)_dlb_callback_disable_cpu) == DLB_SUCCESS);
  152. assert(DLB_CallbackSet_sp(dlb_handle, dlb_callback_enable_cpu, (dlb_callback_t)_dlb_callback_enable_cpu) == DLB_SUCCESS);
  153. #endif
  154. DLB_Enable_sp(dlb_handle);
  155. pthread_mutex_unlock(&dlb_handle_mutex);
  156. }
  157. void starpurm_dlb_exit(void)
  158. {
  159. pthread_mutex_lock(&dlb_handle_mutex);
  160. dlb_handler_t dlb_handle_save = dlb_handle;
  161. dlb_handle = 0;
  162. pthread_mutex_unlock(&dlb_handle_mutex);
  163. /* lend every resources that StarPU may still have */
  164. DLB_Lend_sp(dlb_handle_save);
  165. DLB_Return_sp(dlb_handle_save);
  166. pthread_mutex_lock(&dlb_handle_mutex);
  167. DLB_Disable_sp(dlb_handle_save);
  168. DLB_Finalize_sp(dlb_handle_save);
  169. hwloc_bitmap_free(starpurm_process_cpuset);
  170. pthread_mutex_unlock(&dlb_handle_mutex);
  171. }