Почему __sync_add_and_fetch работает для 64-битной переменной в 32-битной системе?

Рассмотрим следующий сокращенный код:

/* Compile: gcc -pthread -m32 -ansi x.c */
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>

static volatile uint64_t v = 0;

void *func (void *x) {
    __sync_add_and_fetch (&v, 1);
    return x;
}

int main (void) {
    pthread_t t;
    pthread_create (&t, NULL, func, NULL);
    pthread_join (t, NULL);
    printf ("v = %"PRIu64"\n", v);
    return 0;
}

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

Если я скомпилирую для системы amd64 (-m64), полученный ассемблерный код будет легко понять. Используяlock addqпроцессор гарантирует, что приращение будет атомарным.

 400660:       f0 48 83 05 d7 09 20    lock addq $0x1,0x2009d7(%rip)

Но тот же код C создает очень сложный код ASM в системе ia32 (-m32):

804855a:       a1 28 a0 04 08          mov    0x804a028,%eax
804855f:       8b 15 2c a0 04 08       mov    0x804a02c,%edx
8048565:       89 c1                   mov    %eax,%ecx
8048567:       89 d3                   mov    %edx,%ebx
8048569:       83 c1 01                add    $0x1,%ecx
804856c:       83 d3 00                adc    $0x0,%ebx
804856f:       89 ce                   mov    %ecx,%esi
8048571:       89 d9                   mov    %ebx,%ecx
8048573:       89 f3                   mov    %esi,%ebx
8048575:       f0 0f c7 0d 28 a0 04    lock cmpxchg8b 0x804a028
804857c:       08 
804857d:       75 e6                   jne    8048565 <func+0x15>

Вот что я не понимаю:

lock cmpxchg8b делает гарантировать, что измененная переменная записывается, только если ожидаемое значение все еще находится в целевом адресе. Сравнение и обмен гарантированно произойдут атомарно.Но что гарантирует, что чтение переменной в 0x804855a и 0x804855f будет атомарным?

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

Далее: Почему сгенерированный код возвращается к 0x8048565, а не к 0x804855a? Я уверен, что это верно только в том случае, если другие авторы тоже только увеличивают переменную. Является ли это имплицитным требованием для__sync_add_and_fetch функционировать?

Ответы на вопрос(2)

Ваш ответ на вопрос