Как реализовать барьер с помощью семафоров posix?

Как реализовать барьер с помощью семафоров posix?

void my_barrier_init(int a){

    int i;  
    bar.number = a;
    bar.counter = 0;

    bar.arr = (sem_t*) malloc(sizeof(sem_t)*bar.number);
    bar.cont = (sem_t*) malloc(sizeof(sem_t)*bar.number);
    for(i = 0; i < bar.number; i++){    
    sem_init(&bar.arr[i], 0, 0);
    sem_init(&bar.cont[i], 0, 0);   }
}

void my_barrier_wait(){
    int i;    
    bar.counter++;

    if(bar.number == bar.counter){      
    for(i = 0; i < bar.number-1; i++){  sem_wait(&bar.arr[i]);    }
    for(i = 0; i < bar.number-1; i++){   sem_post(&bar.cont[i]);     }
    bar.counter = 0;
    }else{
        sem_post(&bar.arr[pthread_self()-2]);
        sem_wait(&bar.cont[pthread_self()-2]);
  }
}

Когда вызывается функция my_barrier_wait, сначала (N-1) раз она устанавливает (+1) для семафоров в массиве 'arr' и переходит в спящий режим (вызывая sem_wait). N-й раз он уменьшает семафоры в 'arr' и ДОЛЖЕН (как я ожидаю) разбудить потоки [0..bar.number-1], размещающие +1 для семафоров в массиве 'cont'. Это не работает как барьер.


person diana-pure    schedule 22.12.2012    source источник
comment
Что означает pthread_self()-2? Значение, возвращаемое из pthread_self(), является непрозрачным идентификатором. Откуда вы знаете, что можете вычесть из него 2 и использовать его как индекс массива?   -  person Celada    schedule 23.12.2012
comment
У меня есть основной поток, который создает N подпотоков, их идентификаторы 2,3,..(N+1), сопоставление с массивом семафоров. Я сдвигаю индексы на (-2)   -  person diana-pure    schedule 23.12.2012
comment
Из справочной страницы pthread_self(): Идентификаторы потоков следует считать непрозрачными.   -  person Celada    schedule 23.12.2012
comment
когда я тестировал его, семафоры работали правильно, getvalue возвращал ожидаемое число. В любом случае, спасибо, пожалуй, исправлю. Но поможет ли это мне заставить его работать как барьер?   -  person diana-pure    schedule 23.12.2012
comment
Нет, это не так. Но вы на самом деле не сказали, что идет не так (просто это не работает как барьер), поэтому трудно догадаться, в чем проблема. Может быть, bar.counter нужно защитить от одновременных обновлений с помощью мьютекса?   -  person Celada    schedule 23.12.2012
comment
Откровенно говоря, этот код - только моя попытка (он скомпилирован, но N потоков ждут друг друга только один раз 1-й раз, а затем просыпаются на барьере один за другим, а не все в кучу). Я прошу алгоритм, который работает.   -  person diana-pure    schedule 24.12.2012
comment
Что ж, на первый взгляд все выглядит нормально, за исключением того, что bar.counter не защищен от одновременной модификации несколькими потоками. Я мог упустить что-то еще (о параллельных алгоритмах трудно рассуждать), но вам следует начать с bar.counter. Затем, я думаю, вы можете добавить вывод отладки, чтобы показать состояние до/после ожидания каждого потока, и, возможно, вывод покажет состояние, которого вы не ожидали, что будет подсказкой.   -  person Celada    schedule 24.12.2012


Ответы (1)


Вам нужно взглянуть на это (PDF), "Маленькая книга семафоров" Аллена Дауни. В частности, раздел 3.6.7. Это на Python, но суть должна быть достаточно ясной.

person bazza    schedule 09.03.2013