Операции из atomic.h кажутся неатомарными - PullRequest
10 голосов
/ 04 мая 2009

Следующий код выдает случайные значения как для n, так и для v. Неудивительно, что n является случайным без надлежащей защиты. Но предполагается, что в конечном итоге v должно быть 0. Что-то не так в моем коде? Или кто-нибудь может объяснить это для меня? Спасибо.

Я работаю на 4-ядерном сервере архитектуры x86. Uname выглядит следующим образом.

Linux 2.6.9-22.ELsmp # 1 SMP Mon 19 сентября 18:00:54 ПО ВОСТОЧНОМУ ВРЕМЕНИ 2005 x86_64 x86_64 x86_64 GNU / Linux

#include <stdio.h>
#include <pthread.h>
#include <asm-x86_64/atomic.h>

int n = 0;
atomic_t v;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

#define LOOP 10000

void* foo(void *p)
{
    int i = 0;
    for(i = 0; i < LOOP; i++) {
//        pthread_mutex_lock(&mutex);
        ++n;
        --n;
        atomic_inc(&v);
        atomic_dec(&v);
//        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

#define COUNT 50

int main(int argc, char **argv)
{
    int i;
    pthread_t pids[COUNT];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    atomic_set(&v, 0);

    for(i = 0; i < COUNT; i++) {
        pthread_create(&pids[i], &attr, foo, NULL);
    }

    for(i = 0; i < COUNT; i++) {
        pthread_join(pids[i], NULL);
    }

    printf("%d\n", n);
    printf("%d\n", v);
    return 0;
}

Ответы [ 4 ]

6 голосов
/ 04 мая 2009

Вместо этого следует использовать встроенные модули gcc (см. this ). Это прекрасно работает, а также работает с icc.

int a; 
__sync_fetch_and_add(&a, 1); // atomic a++

Обратите внимание, что вы должны знать о проблемах согласованности кэша при изменении переменных без блокировки.

4 голосов
/ 04 мая 2009

Этот старый пост подразумевает, что

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

Итак ... Возможно, в этом причина проблем, с которыми вы сталкиваетесь?

3 голосов
/ 04 мая 2009

Можем ли мы взглянуть на вывод ассемблера кода (я думаю, gcc -E). Даже мысль о том, что uname указывает на его поддержку SMP, не обязательно означает, что он был скомпилирован с CONFIG_SMP.

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

Но я бы все равно использовал функции pthread, поскольку они переносимы на большее количество платформ.

0 голосов
/ 10 июня 2013

Ядро Linux atomic.h не может быть использовано пользователем и никогда не было. На x86 некоторые из них могут работать, потому что x86 является довольно дружественной к синхронизации архитектурой, но на некоторых платформах она в значительной степени зависит от возможности выполнять привилегированные операции (более ранняя версия) или, по крайней мере, от возможности отключения приоритетной работы (более старая версия и поддержка по крайней мере), что не так в пользовательском пространстве!

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