Спин блокировка - atomic(?) operation. Что это значит и как работает?

Тема в разделе "WASM.NT.KERNEL", создана пользователем smileyoufake, 25 мар 2009.

  1. smileyoufake

    smileyoufake New Member

    Публикаций:
    0
    Регистрация:
    14 янв 2009
    Сообщения:
    16
    Доброго времени суток!

    У У.Они , когда речь идет о спин блокировках, есть такое уточнение “an atomic operation that tests and then sets a memory variable in such a way that no other CPU can access the variable until the operation completes”. Воот..
    KeAcquireSpinLock(…) на асме (машины с дебагером нету под рукой, и посмотреть смогу не скоро,но видимо это так) представляет сабой некоторый набор инстукций, я не уверен в порядке следования, но условно оное действо, как я полагаю,включает в себя некоторые инструкции проверки, инуструкции установки, прочую херь(уж я не знаю точно именно irql там повышается, мож что путаю). Может я уже херь сморозил, но я приведу собственно сам вопрос, чтобы добрые люди помогли прояснить неразбериху.

    Рассмотрим ситуацию, да потока (П)оток1 и (П)оток2.
    Значит теоретически может возникнуть такая ситуация
    //Выполняется код П1 на CPU1

    какие-то телодвижения

    KeAquireSpinLock()//теперь конкретно в этом вызове
    Выполняются инструкции проверки, все хорошо, доступ разрешен

    //Выполняется код П2 на CPU2
    KeAquireSpinLock(тот ж объект KSPIN_LOCK)
    И он тоже успешно проходит проверку, так как поток 1 "не успел"(?) еще
    добраться до инструкций «взводящих» спинблокировку.
    //а здесь тем временем в П1
    Выполняются инструкции устанавливающие спинблокировку.

    Таким образом при НЕКОТОРОМ стечении обстоятельств два потока усешно чекнуть спин блокировку.

    Допустим вариант на системе с 1 процом.Да я читал, что в однопроцессорной системе гемороя меньше и при захвате спинблока поток просто повышает IRQL до DISPATCH_LEVEL.

    но в любом случае будут инструкции проверки и установки.И квант П1 может кончится ровно после инструкций проверки, тогда П2 теоретически может в своем коде чекнуть спинблок, а далее уже хоть трава не расти...О.о

    Чую, что собака зарыта в atomic operation, но что именно это означает не пойму, точнее не пойму как оное может быть реализовано.Как эта она не может быть вытеснена?


    Собственно вопрос можно интерполировать и на объекты синхронизации типа событий мютексов и тд.

    Как реализуется (и реализуется ли вообще) защита от вытеснения на каком то шаге KeWaitForSingleObject
    KeWaitForMultipleObject

    Ведь в любом случает есть(?) инструкции проверки а потом уже захвата объекта, и почему между ними то как раз не может вклинится другой поток и опять запросить проверку?

    Заранее благодарен!
     
  2. Forever

    Forever Виталий

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    244
    atomic operation - операция выполняющаяся атомарно. Фактически перед такой инструкцией подается префикс LOCK, который блокирует шину адресса. Таким образом можно проверять значение, изменять и ... т.д. некоторые переменные атомарно.
     
  3. smileyoufake

    smileyoufake New Member

    Публикаций:
    0
    Регистрация:
    14 янв 2009
    Сообщения:
    16
    Блин говорили мне читай Зубкова:) Спасибо за наводку, покопал в сторону lock и тд.Ну теперь вырисовывается.
     
  4. s0larian

    s0larian New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2004
    Сообщения:
    489
    Адрес:
    Крыжёпполь
    Это примитива операционки - семафоры, spinlocks, mutexes, и т.д. Про атомарные инструкции тебе уже ответили, а эти вещи - чисто теоретическая абстракция. Напремер mutex (win32 critical section) - всё упирается в системный вызов который блокирует поток. То есть, примитива даёт эксклюзивный доступ для обычного потока.
     
  5. smileyoufake

    smileyoufake New Member

    Публикаций:
    0
    Регистрация:
    14 янв 2009
    Сообщения:
    16
    solarian , ты прости, но твой коментарий, вообще не ответ ни разу. Я знаю, что такое примитивы синхронизации и как ими пользоваться.точнее думал так:)

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

    Я тут полистал зубкова и мануал интела и всетаки...
    lock - это префикс для блокировки шины на время выполнения микрокоманд в рамках одной инструкции те типа:
    lock xadd
    lock xchg

    но между ними все равно код может быть вытеснен!
    Те в рамках П1 между проверкой состояния спинлока и его установкой код в П2 может также совершить успешную проверку этого самого спинлока.И далее оба потока будут пытаться установить энтот спинлок, соответственно бсод.

    вот небольшая вырезка из Oney в коментариях для ExInterlockedAddLargeStatistic.Да для каждой инструкции lock работает, но между ними...
    А именно, lock конечно спасает в рамках одной инструкции, но между ними может быть чито угодно.

    Все таки не понял я этот момент.Вразумите пожалуйста :dntknw: Боюсь теперь объектов синхронизации, придется переходить под дос :)
    Я не нашел пока нигде толкового пояснения этой ситуации.
     
  6. iZzz32

    iZzz32 Sergey Sfeli

    Публикаций:
    0
    Регистрация:
    3 сен 2006
    Сообщения:
    355
    В отрывке про 64-битную переменную. Чтобы с ней работать, надо установить спинлок сначала.
    Идея в том, что инструкцию xchg eax,[spinlock] процессоры выполнят один за другим, соответственно, 0 из spinlock в eax получит только один из них, а второй уже получит 1, поймёт, что спинлок занят и пойдёт крутиться (spin – отсюда и название) в wait, дожидаясь следующего благоприятного случая (но и когда он его дождётся, нет гарантии, что у него получится захватить ресурс).
    Код (Text):
    1. spinlock        dd 0
    2. acquire:
    3.         xor     eax,eax
    4.         inc     eax             ; EAX = 1.
    5.         xchg    eax,[spinlock]  ; LOCK неявный тут.
    6.         test    eax,eax         ; Проверяем, что было в spinlock до нас (было ли свободно)?
    7.         jnz     .wait           ; Было 1 (занято)? Тогда ждём.
    8. work:
    9.         ; делаешь своё чёрное дело с данными
    10.         xor     eax,eax
    11.         mov     [spinlock],eax  ; Освобождаем.
    12.         jmp     done
    13. wait:
    14.         cmp     [spinlock],0    ; Занято?
    15.         jnz     wait            ; Ждём, если занято.
    16.         jmp     acquire         ; Не занято. Попробуем завладеть.
    17. done:
     
  7. smileyoufake

    smileyoufake New Member

    Публикаций:
    0
    Регистрация:
    14 янв 2009
    Сообщения:
    16
    xchg....xchg...как все просто!
    Благодарствую!теперь все точно clear :)

    UPDT:

    если кому вдруг будет интересно, то вот дернул из hal.dll:
    Код (Text):
    1.          
    2. KfAcquireSpinLock:
    3. ;судя по мануалу ia32 fffe0080 энто у нас "the address of TPR register of Local APIC"
    4. ;а следовательно со старта эта функция поднимает уровень irql, видимо до
    5. ;уровня DISPATCH_LEVEL, а потом уже делаются все сеты и тесты...от так вот :)
    6.  
    7.                 mov      edx,[FFFE0080h]
    8.                 mov      dword ptr [FFFE0080h],00000041h
    9.                 shr      edx,04h
    10.                 movzx    eax,[edx-7FFE2DE8h]
    11.      
    12. L1_8001284A:
    13.                 lock bts dword ptr [ecx],00h ;чутка подредактировал
    14.                 jc       L1_80012854
    15.                 retn
    16.  
    17. L2_80012854:
    18.                 test     dword ptr [ecx],00000001h
    19.                 jz       L2_8001284A
    20.                 pause              
    21.                 jmp      L80012854
    22.                 retn