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