Подайте сигнал определенному pthread с условием

Я работаю с pthreads и семафорами и пытаюсь выяснить, как сигнализировать конкретному потоку.

Поток, который я хочу сигнализировать с определенным условием, будет потоком, ожидающим в голове моей очереди.

Основная часть моего файла semaphore.h:

struct entry_thread {
    int threadID;
    SIMPLEQ_ENTRY(entry_thread) next;
} *np;

struct semaphore {
    int count;
    int headThreadID;
    pthread_mutex_t mutex;
    pthread_cond_t flag;
    SIMPLEQ_HEAD(queuehead, entry_thread) head;
};

typedef struct semaphore semaphore_t;

И связанные части моего файла semaphore.c:

void down( semaphore_t* sem )
{

    pthread_mutex_lock( &sem->mutex );
    while ( sem->count <= 0)
    {
        // First check if queue is empty, if so, set a new headThreadID
        if (SIMPLEQ_EMPTY( &(sem->head) ))
        {
            sem->headThreadID = pthread_self();
        }
        np = malloc( sizeof( struct entry_thread ) );
        np->threadID = pthread_self();
        SIMPLEQ_INSERT_TAIL( &(sem->head), np, next);
        pthread_cond_wait( &sem->flag, &sem->mutex );
    }
    sem->count--;
    pthread_mutex_unlock( &sem->mutex );
}

void up( semaphore_t* sem )
{
    pthread_mutex_lock( &sem->mutex );
    sem->count++;
    if ( sem->count == 1 )
    {
        // Get the head of the semaphore's queue
        SIMPLEQ_REMOVE_HEAD( &(sem->head), (np = SIMPLEQ_FIRST(&(sem->head))), next );

        /* I WANT TO ONLY SIGNAL THE HEAD THREAD!!! */
        pthread_cond_signal( &sem->flag );
        /* THE ABOVE SIGNALS A RANDOM SINGLE THREAD */

        free( np );
    }
    pthread_mutex_unlock( &sem->mutex );
}

Итак, моя проблема заключается в том, что, хотя я могу получить идентификатор потока, мне нужно иметь возможность сигнализировать этому потоку, что условие, которого он ожидает, изменилось, и он может снова проверить семафор. Мы будем очень признательны за любые советы.


person Zach    schedule 01.11.2015    source источник


Ответы (1)


Первый совет: всегда проверяйте возвращаемое значение вызовов для блокировки мьютекса, а также функции API условий.

Хотя все в порядке, отсутствие проверки возвращаемого значения работает нормально, но когда что-то идет не так, вся система падает таким образом, что невозможно отладить или отследить источник проблемы.

Идея pthread_cond_signal пробуждения случайного одиночного потока такова: в многопоточном приложении ваши задачи не зависят от порядка выполнения. Когда у вас есть потоки X, ожидающие выполнения одного и того же условия, предполагается, что любой из них может выполняться при появлении сигнала об условии.

Как правило, разные потоки, выполняющие разные задачи, должны ожидать выполнения на разных условиях.

Кажется, что ваш код вставляет в очередь только один поток, на самом деле это не очередь.

Использование вами pthread_cond_wait не включает проверку (значимого) предиката, если вы не уверены, зачем вам нужен предикат, проведите небольшое исследование. Если предикат должен быть while, то я думаю, что в вашем коде есть логические ошибки.

Если я полностью ошибаюсь в том, как работает ваш код, это потому, что большая его часть отсутствует: https://stackoverflow.com/help/mcve< /а>

Как только ваша очередь будет правильно заполнена всеми потоками, ожидающими процессорного времени, вы можете поменять местами pthread_cond_signal на pthread_cond_broadcast и сделать предикат для pthread_cond_wait флагом, чтобы определить, является ли текущий поток запланированным потоком. Я предполагаю, что затем вам нужно как-то разбудить другие потоки, ожидающие в правильном порядке...

Это не лучшая реализация планировщика, которую я могу себе представить, но она близка к вашей попытке. Вы должны заставить его работать, а затем посмотреть, сможете ли вы улучшить его, определив, каковы его характеристики производительности и какими они должны быть.

Поскольку это задание, я не буду писать код за вас, это бесполезно.

person Joe Watkins    schedule 01.11.2015
comment
Спасибо за совет. Я ценю, что вы сообщили мне, что я делаю неправильно, это часть задания из моего курса по ОС, и я очень новичок в C, поэтому мне действительно нужно изучить лучшие практики. Задача здесь должна эмулировать создание нашего собственного алгоритма планирования, и один из них в назначении заключается в том, что первый поток, добавленный в очередь семафора, должен быть уведомлен, когда условие, которого он ожидает, изменилось. Таким образом, приоритет каждого потока определяется тем, находится ли он во главе очереди. С помощью этой информации вы понимаете, чего я пытаюсь добиться? - person Zach; 01.11.2015
comment
Спасибо за обновления. Поэтому я считаю, что, возможно, решил свою проблему, добавив дополнительное условие в функцию down() в режиме защиты от цикла. Там я также сейчас проверяю, если sem->headThreadID != pthread_self(), и если да, то pthread вернется в ожидание. В моей функции up() я удаляю из очереди первый элемент в очереди, проверяю, есть ли в очереди другой элемент, и если он есть, я устанавливаю sem->headThreadID в качестве идентификатора этого потока. - person Zach; 01.11.2015