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

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

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

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

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

textual
Листинг программы
/* Wake everybody.  */
pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
 
/* Do not use requeue for pshared condvars.  */
if (mut == (void *) ~0l
|| PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
goto wake_all;
 
/* ... */
wake_all:
  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
Похожие ответы