Синхронизация Linux с очередью ожидания FIFO - PullRequest
5 голосов
/ 16 июня 2010

Есть ли блокировки в Linux, где очередь ожидания FIFO? Это кажется очевидной вещью, и все же я только что обнаружил, что мьютексы pthread не являются FIFO, и семафоры, очевидно, тоже не FIFO (я работаю над ядром 2.4 (домашняя работа)) ...

Есть ли у Linux блокировка с ожидающей очередью FIFO или есть простой способ сделать ее с помощью существующих механизмов?

Ответы [ 3 ]

4 голосов
/ 16 июня 2010

Вот способ создать простой «тикет» с очередями, построенный на примитивах pthreads. Это должно дать вам несколько идей:

#include <pthread.h>

typedef struct ticket_lock {
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    unsigned long queue_head, queue_tail;
} ticket_lock_t;

#define TICKET_LOCK_INITIALIZER { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER }

void ticket_lock(ticket_lock_t *ticket)
{
    unsigned long queue_me;

    pthread_mutex_lock(&ticket->mutex);
    queue_me = ticket->queue_tail++;
    while (queue_me != ticket->queue_head)
    {
        pthread_cond_wait(&ticket->cond, &ticket->mutex);
    }
    pthread_mutex_unlock(&ticket->mutex);
}

void ticket_unlock(ticket_lock_t *ticket)
{
    pthread_mutex_lock(&ticket->mutex);
    ticket->queue_head++;
    pthread_cond_broadcast(&ticket->cond);
    pthread_mutex_unlock(&ticket->mutex);
}
4 голосов
/ 16 июня 2010

Если вы спрашиваете, что я думаю, вы спрашиваете, короткий ответ - нет.Потоки / процессы контролируются планировщиком ОС.Один случайный поток получит блокировку, остальные - нет.Ну, потенциально больше, чем один, если вы используете счетный семафор, но это, вероятно, не то, о чем вы просите.

Возможно, вы захотите взглянуть на pthread_setschedparam , но это не поможет вам понять, где яПодозреваю, что вы хотите пойти.

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

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

0 голосов
/ 29 декабря 2017

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

  • Если вам нужно 100% правильное упорядочение по FIFO, используйте кафе pthread ticket .

  • Если вы довольны 99% и предпочитаете простоту, семафор или мьютекс может действительно хорошо работать.

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

Использование семафора:

static sem_t *sem = NULL;

void fifo_init()
{
    sem = sem_open("/server_fifo", O_CREAT, 0600, 1);
    if (sem == SEM_FAILED)  fail("sem_open");
}

void fifo_lock()
{
    int r;
    struct timespec ts;
    if (clock_gettime(CLOCK_REALTIME, &ts) == -1)  fail("clock_gettime");
    ts.tv_sec += 5;     /* 5s timeout */

    while ((r = sem_timedwait(sem, &ts)) == -1 && errno == EINTR)
        continue;       /* Restart if interrupted */
    if (r == 0)  return;

    if (errno == ETIMEDOUT) fprintf(stderr, "timeout ...\n");
    else                    fail("sem_timedwait");
}

void fifo_unlock()
{
    /* If we somehow end up with more than one token, don't increment the semaphore... */
    int val;
    if (sem_getvalue(sem, &val) == 0 && val <= 0)
        if (sem_post(sem))  fail("sem_post");
    usleep(1);  /* Yield to other processes */
}

Заказ почти на 100% FIFO.

Примечание: это с ядром Linux 4.4, 2.4 может отличаться.

...