Разобраться в коде, где непосредственно делается вызов чтобы разбудить все потоки - C (СИ)

Узнай цену своей работы

Формулировка задачи:

помогите разобраться в коде где непосредственно делается вызов чтобы разбудить все потоки? Какой вызов используется? Есть один вызов lll_lock и два вызова lll_unlock, но при этом всё правильно работает. Почему?
Листинг программы
  1. /* Copyright (C) 2003-2015 Free Software Foundation, Inc.
  2. 2 This file is part of the GNU C Library.
  3. 3 Contributed by Martin Schwidefsky <removed@mail.ru>, 2003.
  4. 4
  5. 5 The GNU C Library is free software; you can redistribute it and/or
  6. 6 modify it under the terms of the GNU Lesser General Public
  7. 7 License as published by the Free Software Foundation; either
  8. 8 version 2.1 of the License, or (at your option) any later version.
  9. 9
  10. 10 The GNU C Library is distributed in the hope that it will be useful,
  11. 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. 13 Lesser General Public License for more details.
  14. 14
  15. 15 You should have received a copy of the GNU Lesser General Public
  16. 16 License along with the GNU C Library; if not, see
  17. 17 <http://www.gnu.org/licenses/>. */
  18. 18
  19. 19 #include <endian.h>
  20. 20 #include <errno.h>
  21. 21 #include <sysdep.h>
  22. 22 #include <lowlevellock.h>
  23. 23 #include <pthread.h>
  24. 24 #include <pthreadP.h>
  25. 25 #include <stap-probe.h>
  26. 26
  27. 27 #include <shlib-compat.h>
  28. 28 #include <kernel-features.h>
  29. 29
  30. 30
  31. 31 int
  32. 32 __pthread_cond_broadcast (cond)
  33. 33 pthread_cond_t *cond;
  34. 34 {
  35. 35 LIBC_PROBE (cond_broadcast, 1, cond);
  36. 36
  37. 37 int pshared = (cond->__data.__mutex == (void *) ~0l)
  38. 38 ? LLL_SHARED : LLL_PRIVATE;
  39. 39 /* Make sure we are alone. */
  40. 40 lll_lock (cond->__data.__lock, pshared);
  41. 41
  42. 42 /* Are there any waiters to be woken? */
  43. 43 if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
  44. 44 {
  45. 45 /* Yes. Mark them all as woken. */
  46. 46 cond->__data.__wakeup_seq = cond->__data.__total_seq;
  47. 47 cond->__data.__woken_seq = cond->__data.__total_seq;
  48. 48 cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2;
  49. 49 int futex_val = cond->__data.__futex;
  50. 50 /* Signal that a broadcast happened. */
  51. 51 ++cond->__data.__broadcast_seq;
  52. 52
  53. 53 /* We are done. */
  54. 54 lll_unlock (cond->__data.__lock, pshared);
  55. 55
  56. 56 /* Wake everybody. */
  57. 57 pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
  58. 58
  59. 59 /* Do not use requeue for pshared condvars. */
  60. 60 if (mut == (void *) ~0l
  61. 61 || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
  62. 62 goto wake_all;
  63. 63
  64. 64 #if (defined lll_futex_cmp_requeue_pi \
  65. 65 && defined __ASSUME_REQUEUE_PI)
  66. 66 if (USE_REQUEUE_PI (mut))
  67. 67 {
  68. 68 if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
  69. 69 &mut->__data.__lock, futex_val,
  70. 70 LLL_PRIVATE) == 0)
  71. 71 return 0;
  72. 72 }
  73. 73 else
  74. 74 #endif
  75. 75 /* lll_futex_requeue returns 0 for success and non-zero
  76. 76 for errors. */
  77. 77 if (!__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1,
  78. 78 INT_MAX, &mut->__data.__lock,
  79. 79 futex_val, LLL_PRIVATE), 0))
  80. 80 return 0;
  81. 81
  82. 82 wake_all:
  83. 83 lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
  84. 84 return 0;
  85. 85 }
  86. 86
  87. 87 /* We are done. */
  88. 88 lll_unlock (cond->__data.__lock, pshared);
  89. 89
  90. 90 return 0;
  91. 91 }
  92. 92
  93. 93 versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
  94. 94 GLIBC_2_3_2);

Решение задачи: «Разобраться в коде, где непосредственно делается вызов чтобы разбудить все потоки»

textual
Листинг программы
  1. /* Wake everybody.  */
  2. pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
  3.  
  4. /* Do not use requeue for pshared condvars.  */
  5. if (mut == (void *) ~0l
  6. || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
  7. goto wake_all;
  8.  
  9. /* ... */
  10. wake_all:
  11.   lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);

Объяснение кода листинга программы

  1. pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; - в этой строке кода происходит приведение типа указателя на объект типа pthread_mutex_t к типу void* с помощью оператора cast. Это необходимо для того, чтобы привести указатель к типу, который ожидает функция lll_futex_wake.
  2. if (mut == (void *) ~0l || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT) - в этом блоке кода выполняется проверка условия. Если значение указателя mut равно значению, которое возвращает оператор ~0l (что эквивалентно UINT_MAX), или бит PTHREAD_MUTEX_PSHARED в значении mut установлен в 1, то управление передается оператору goto wake_all.
  3. goto wake_all; - переход к оператору lll_futex_wake с помощью оператора goto.
  4. lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared); - в этой строке кода происходит вызов функции lll_futex_wake, которая предназначена для пробуждения всех потоков, ожидающих на условной переменной. Аргументами функции являются адрес условной переменной, максимальное количество потоков, которые следует разбудить, и флаг, указывающий, является ли условная переменная общей.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

8   голосов , оценка 4 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы