sort_data_handles.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /*
  2. * StarPU
  3. * Copyright (C) Université Bordeaux 1, CNRS 2008-2010 (see AUTHORS file)
  4. *
  5. * This program 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. * This program 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. #include <starpu.h>
  17. #include <common/config.h>
  18. #include <datawizard/filters.h>
  19. /* To avoid deadlocks in case we have multiple tasks accessing the same piece
  20. * of data (eg. task T1 needs A and B, and T2 needs B and A), we need to lock
  21. * them in order, so that we need a total order over data. We must also not
  22. * lock a child before its parent. */
  23. static void find_data_path(struct starpu_data_state_t *data, unsigned path[])
  24. {
  25. unsigned depth = data->depth;
  26. struct starpu_data_state_t *current = data;
  27. /* Compute the path from the root to the data */
  28. unsigned level; /* level is the distance between the node and the current node */
  29. for (level = 0; level < depth; level++)
  30. {
  31. STARPU_ASSERT(data);
  32. path[depth - level - 1] = current->sibling_index;
  33. current = data->father_handle;
  34. }
  35. }
  36. static int _compar_data_paths(const unsigned pathA[], unsigned depthA,
  37. const unsigned pathB[], unsigned depthB)
  38. {
  39. unsigned level;
  40. unsigned depth = STARPU_MIN(depthA, depthB);
  41. for (level = 0; level < depth; level++)
  42. {
  43. if (pathA[level] != pathB[level])
  44. return (pathA[level] < pathB[level])?-1:1;
  45. }
  46. /* If this is the same path */
  47. if (depthA == depthB)
  48. return 0;
  49. /* A is a subdata of B or B is a subdata of A, so the smallest one is
  50. * the father of the other (we take this convention). */
  51. return (depthA < depthB)?-1:1;
  52. }
  53. /* A comparision function between two handles makes it possible to use qsort to
  54. * sort a list of handles */
  55. static int _starpu_compar_handles(struct starpu_data_state_t *dataA,
  56. struct starpu_data_state_t *dataB)
  57. {
  58. /* Perhaps we have the same piece of data */
  59. if (dataA == dataB)
  60. return 0;
  61. /* In case we have data/subdata from different trees */
  62. if (dataA->root_handle != dataB->root_handle)
  63. return ((dataA->root_handle < dataB->root_handle)?-1:1);
  64. /* Things get more complicated: we need to find the location of dataA
  65. * and dataB within the tree. */
  66. unsigned dataA_path[dataA->depth - 1];
  67. unsigned dataB_path[dataB->depth - 1];
  68. find_data_path(dataA, dataA_path);
  69. find_data_path(dataB, dataB_path);
  70. return _compar_data_paths(dataA_path, dataA->depth, dataB_path, dataB->depth);
  71. }
  72. static int _starpu_compar_buffer_descr(const void *_descrA, const void *_descrB)
  73. {
  74. const starpu_buffer_descr *descrA = _descrA;
  75. const starpu_buffer_descr *descrB = _descrB;
  76. return _starpu_compar_handles(descrA->handle, descrB->handle);
  77. }
  78. /* The descr array will be overwritten, so this must be a copy ! */
  79. void _starpu_sort_task_handles(starpu_buffer_descr descr[], unsigned nbuffers)
  80. {
  81. qsort(descr, nbuffers, sizeof(starpu_buffer_descr), _starpu_compar_buffer_descr);
  82. }