Forth и другие саморасширяющиеся системы программирования Locations of visitors to this page
Текущее время: Пт дек 15, 2017 23:44

...
Google Search
Forth-FAQ Spy Grafic

Часовой пояс: UTC + 3 часа [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 11 ] 
Автор Сообщение
 Заголовок сообщения: синхронизация задач - мьютексы
СообщениеДобавлено: Сб июн 30, 2007 00:41 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
Мьютекс, это такая штука, которая запрещает одновременно выполнять одно и то же действие, например доступ к одному устройству двум и более процессам одновременно. Наиболее простой и быстрый вариант, нежели семафоры, например.

Код:
\ 21-06-2007 ~mOleg
\ Copyright [C] 2007 mOleg mininoleg@yahoo.com
\ мьютексы

REQUIRE ?DEFINED  devel\~moleg\lib\util\ifdef.f
REQUIRE B,        devel\~mOleg\lib\util\bytes.f

\ пробуем удостовериться в том, что ресурс свободен
\ если свободен, устанавливаем флаг занятости, возвращаем TRUE
\ иначе FALSE
: ?LockMutex ( addr --> flag )
             [ 0x8B B, 0xD8 B,       \ MOV addr , tos
               0xC7 B, 0xC0 B, -1 ,  \ MOV tos , # -1
               0x87 B, 0x03 B,       \ XCHG [addr] , tos
               0xF7 B, 0xD0 B,       \ NOT tos
             ] ;

\ освобождаем занимаемый ресурс
: UnlockMutex ( addr --> )
              [ 0x33 B, 0xD2 B,         \ XOR temp , temp
                0x87 B, 0x10 B,         \ XCHG [tos], temp
                0x8B B, 0x45 B, 0x00 B,
                0x8D B, 0x6D B, 0x04 B, \ dpop tos
              ] ;

\ ждем освобождения ресурса, после чего его лочим за собой
: WaitUnlock ( addr --> ) BEGIN DUP ?LockMutex UNTIL DROP ;

\ создать именованый мьютекс
\ при выполнении слова с именем name с параметром 'cfa можно быть
\ уверенным, что ресурс, связанный с мьютексом доступен монопольно.
: MUTEX: ( / name --> )
         CREATE 0 ,
         ( 'cfa --> )
         DOES> DUP >R WaitUnlock EXECUTE R> UnlockMutex ;

?DEFINED test{ \EOF -- тестовая секция ---------------------------------------

test{ VARIABLE res
         res ?LockMutex 0= THROW
         res ?LockMutex THROW
         res UnlockMutex
         res ?LockMutex 0= THROW
         res UnlockMutex
  S" passed" TYPE
}test

\EOF -- типа пример ---------------------------------------------------------

  MUTEX: sample

: test 100 0 DO I . 100 PAUSE LOOP ;

: testa ['] test sample ;

: testb CR ."  passed" CR ;


' testa TASK: proba

: zzzz  0 proba START        \ поток proba лочит за собой мьютекс sample
        200 PAUSE ." zzzzzz "

        ['] testb sample     \ до тех пор, пока sample залочен, testb
                             \ будет стоять в ожидании
        ;

zzzz

\EOF

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




Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 02:02 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
profiT писал(а):
SPF_DEVEL:

Цитата:

REQUIRE CREATE-MUTEX lib/win/mutex.f \ Мутексы

REQUIRE ENTER-CS ~pinka/lib/multi/critical.f \ Critical sections

REQUIRE WaitAll ~pinka/lib/multi/synchr.f \ Синхронизация потоков - "ожидание одного", "ожидание всех"

Азамат, кончай фигню писать!

данный пример находится не в теме SPF а в теме OS так что все виндошные примочки отпадают, это раз.
Второе, есть различие в том, вызываешь ли ты внешнюю функцию из DLL или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс. Ну и третье, область видимости мьютекса для приведенных примеров различна, в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде.

да, и еще - не вижу ничего плохого в том, что добавляется еще одна либа, у куже существующим, тем более, что она отличается от них.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 02:18 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
profiT писал(а):
mOleg писал(а):данный пример находится не в теме SPF а в теме OS так что все виндошные примочки отпадают, это раз.

mOleg писал(а):в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде


тем не менее одно другому не противоречит 8)
и из одного вытекает второе 8)

Просто не обязательно напоминать, что есть и другие варианты, потому как выглядит упреком.


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 12:46 
Не в сети

Зарегистрирован: Чт май 04, 2006 18:18
Сообщения: 456
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Фигню пишет кто-то другой.
Вы вообще понимаете что такое мутексы?

mOleg писал(а):
данный пример находится не в теме SPF а в теме OS так что все виндошные примочки отпадают, это раз.

Мутексы не могут быть реализованы на уровне выше чем ядро ОС (планировщик/переключатель потоков), а т.к. вся Forth OS существует до сих пор только в виде флейма то и приведённая реализация имеет нулевую ценность и вообще называться мутексами никак не может.

В коде демонстрируется пример на виндовских потоках. Это просто бред. Запустите 100 потоков, возьмите один ресурс и попробуйте залочить этими с позволения сказать "мутексами".

mOleg писал(а):
Второе, есть различие в том, вызываешь ли ты внешнюю функцию из DLL или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс.

Мда? DLL отображается на адресное пространство процесса и вызов функции DLL ничем не отличается от вызова "внутренней" функции.

mOleg писал(а):
Ну и третье, область видимости мьютекса для приведенных примеров различна, в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде.

Видны только именованные мутексы. Неименованные надо передавать другому процессу явно.
Обсуждать подобные отличия этой "реализации" вообще смешно т.к. она не выполняет (и не может в принципе выполнять) своего прямого назначения - обеспечивать монопольный доступ к разделяемым ресурсам.

_________________
http://forth.org.ru/~ygrek


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 21:25 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
ygrek писал(а):
Вы вообще понимаете что такое мутексы?

вполне

ygrek писал(а):
Мутексы не могут быть реализованы на уровне выше чем ядро ОС (планировщик/переключатель потоков), а т.к. вся Forth OS существует до сих пор только в виде флейма то и приведённая реализация имеет нулевую ценность и вообще называться мутексами никак не может.

читайте доку, как раз таки могут и используются.

ygrek писал(а):
В коде демонстрируется пример на виндовских потоках. Это просто бред. Запустите 100 потоков, возьмите один ресурс и попробуйте залочить этими с позволения сказать "мутексами".

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

ygrek писал(а):
Второе, есть различие в том, вызываешь ли ты внешнюю функцию из DLL или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс.

Мда? DLL отображается на адресное пространство процесса и вызов функции DLL ничем не отличается от вызова "внутренней" функции.

любой вызов функции ДЛЛ в СПФ очень накладен!!!
Поэтому главное отличие - это время исполнения, ну и область видимости данного мьютекса.

ygrek писал(а):
Видны только именованные мутексы. Неименованные надо передавать другому процессу явно.

Обсуждать подобные отличия этой "реализации" вообще смешно т.к. она не выполняет (и не может в принципе выполнять) своего прямого назначения - обеспечивать монопольный доступ к разделяемым ресурсам.

слишком громко сказано. Но при этом бездоказательно!!!
еще раз читай внимательно, в рамках одной запущенной форт-системы такими мьютексами можно пользоваться.
Разделяемым ресурсом может быть словарь, например (он и есть такой)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 21:45 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
ygrek писал(а):
вся Forth OS существует до сих пор только в виде флейма

ну, теперь не только в виде флейма 8)
не у всех с окончанием флейма кончилось желание что-либо делать в этом направлении!
8)


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 22:57 
Не в сети

Зарегистрирован: Чт май 04, 2006 18:18
Сообщения: 456
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
Ок, я был не совсем прав.
Во-первых то что реализовал mOleg на самом деле работает и обеспечивает монопольный доступ. В связи с чем прошу простить меня за резкие высказывания насчёт работоспособности этой либы.. (Надо было сначала проверить а не языком ляпать)..
Во-вторых это всё таки никак не мутексы. Ибо по определению мутекс это обьект ядра.
В-третьих то что реализовано называется спин-блокировкой. Насколько я понял суть в том что команда xchg по умолчанию имеет префикс LOCK который аппаратно запрещает доступ к адресуемой ячейке памяти. Именно в этом месте и происходит исключение взаимной порчи. В KERNEL32.DLL есть эквивалентная функция (точнее семейство функций) - InterlockedExchange. На Win98 её код аналогичен тому что привёл mOleg, на WinXP немного отличается. Проверял дизасмом.
Недостаток спин-блокировки в том что в цикле проверки абсолютно впустую тратится процессорное время. Чтобы с этим справиться можно в слово WaitUnlock добавить 0 PAUSE.

Итого вывод - в обязательном порядке читать всем Рихтера :)

_________________
http://forth.org.ru/~ygrek


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Сб июн 30, 2007 23:54 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
ygrek писал(а):
Во-первых то что реализовал mOleg на самом деле работает и обеспечивает монопольный доступ. В связи с чем прошу простить меня за резкие высказывания насчёт работоспособности этой либы.. (Надо было сначала проверить а не языком ляпать)..
Во-вторых это всё таки никак не мутексы. Ибо по определению мутекс это обьект ядра.

вообще, то, что я привел, тоже называется мьютексом по крайней мере в нескольких книгах. И вполне возможно под виндой называется иначе.
Я не обижен 8)

ygrek писал(а):
В-третьих то что реализовано называется спин-блокировкой. Насколько я понял суть в том что команда xchg по умолчанию имеет префикс LOCK который аппаратно запрещает доступ к адресуемой ячейке памяти.

да, поэтому данный код будет работоспособен даже на многопроцессорных машинах, но, при условии, что страница памяти. в которой хранится переменная блокировки не находится в кеше, а это можно обеспечить только на уровне ядра ОС 8) но в рамках одной форт-системы по-любому работоспособно.

ygrek писал(а):
На Win98 её код аналогичен тому что привёл mOleg, на WinXP немного отличается. Проверял дизасмом.

странно 8) не думал, неужели полностью аналогичен? вместе с NOT EAX ?

ygrek писал(а):
Недостаток спин-блокировки в том что в цикле проверки абсолютно впустую тратится процессорное время. Чтобы с этим справиться можно в слово WaitUnlock добавить 0 PAUSE.

на самом деле все не совсем так, как взаправду 8)
дело в том, что основное слово ?LockMutex предполагает, что можно многократно пытаться залочить ресурс, но при обломе заниматься другими делами 8) То есть не обязательно пользоваться WaitUnlock при работе ( это только вариант исполнения )


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс июл 01, 2007 11:03 
Не в сети

Зарегистрирован: Чт май 04, 2006 18:18
Сообщения: 456
Благодарил (а): 0 раз.
Поблагодарили: 1 раз.
mOleg писал(а):
странно не думал, неужели полностью аналогичен? вместе с NOT EAX ?


Ну не байт в байт. Главное идея та же.
Там и описание аргументов немного другое. Возвращают предыдущее значение.
Это дизасм из WinXP, тут LOCK префикс явно прописан.
Код:
7C809766 >  8B4C24 04       MOV ECX,DWORD PTR SS:[ESP+4]             ; InterlockedIncrement
7C80976A    B8 01000000     MOV EAX,1
7C80976F    F0:0FC101       LOCK XADD DWORD PTR DS:[ECX],EAX         ; LOCK prefix
7C809773    40              INC EAX
7C809774    C2 0400         RETN 4
7C809777    8D49 00         LEA ECX,DWORD PTR DS:[ECX]
7C80977A >  8B4C24 04       MOV ECX,DWORD PTR SS:[ESP+4]             ; InterlockedDecrement
7C80977E    B8 FFFFFFFF     MOV EAX,-1
7C809783    F0:0FC101       LOCK XADD DWORD PTR DS:[ECX],EAX         ; LOCK prefix
7C809787    48              DEC EAX
7C809788    C2 0400         RETN 4
7C80978B    8D49 00         LEA ECX,DWORD PTR DS:[ECX]
7C80978E >  8B4C24 04       MOV ECX,DWORD PTR SS:[ESP+4]             ; InterlockedExchange
7C809792    8B5424 08       MOV EDX,DWORD PTR SS:[ESP+8]
7C809796    8B01            MOV EAX,DWORD PTR DS:[ECX]
7C809798    F0:0FB111       LOCK CMPXCHG DWORD PTR DS:[ECX],EDX      ; LOCK prefix
7C80979C  ^ 75 FA           JNZ SHORT kernel32.7C809798
7C80979E    C2 0800         RETN 8
7C8097A1    90              NOP
7C8097A2 >  8B4C24 04       MOV ECX,DWORD PTR SS:[ESP+4]             ; InterlockedCompareExchange
7C8097A6    8B5424 08       MOV EDX,DWORD PTR SS:[ESP+8]
7C8097AA    8B4424 0C       MOV EAX,DWORD PTR SS:[ESP+C]
7C8097AE    F0:0FB111       LOCK CMPXCHG DWORD PTR DS:[ECX],EDX      ; LOCK prefix
7C8097B2    C2 0C00         RETN 0C

_________________
http://forth.org.ru/~ygrek


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вс июл 01, 2007 21:21 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
ygrek писал(а):
Недостаток спин-блокировки в том что в цикле проверки абсолютно впустую тратится процессорное время. Чтобы с этим справиться можно в слово WaitUnlock добавить 0 PAUSE.

точнее даже так: (чтобы блокировка была снята в любом случае)

Код:
\ ждем освобождения ресурса, после чего его лочим за собой
: WaitUnlock ( addr --> )
             BEGIN DUP ?LockMutex WHILENOT
                   0 PAUSE    \ чтобы не расходовать квант времени до конца
             REPEAT DROP ;

\ создать именованый мьютекс
\ при выполнении слова с именем name с параметром 'cfa можно быть
\ уверенным, что ресурс, связанный с мьютексом доступен монопольно.
: MUTEX: ( / name --> )
         CREATE 0 ,
         ( 'cfa --> )
         DOES> DUP >R WaitUnlock
               ['] EXECUTE CATCH
                   R> UnlockMutex \ освобождаем ресурс даже в случае ошибки
               THROW ;


Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
 Заголовок сообщения:
СообщениеДобавлено: Вт июл 17, 2007 01:07 
Не в сети
Moderator
Moderator
Аватара пользователя

Зарегистрирован: Чт май 04, 2006 00:53
Сообщения: 4832
Откуда: был Крым, теперь Новосибирск
Благодарил (а): 18 раз.
Поблагодарили: 52 раз.
продолжение.
Теперь освободить мьютекс может только залочивший его поток.
В случае попытки освободить мьютекс из другого потока будет выполняться ожидание.

Код:
\ 21-06-2007 ~mOleg
\ Copyright [C] 2007 mOleg mininoleg@yahoo.com
\ мьютексы

REQUIRE ?DEFINED   devel\~moleg\lib\util\ifdef.f
REQUIRE B,         devel\~mOleg\lib\util\bytes.f
REQUIRE ADDR       devel\~mOleg\lib\util\addr.f
REQUIRE IFNOT      devel\~moleg\lib\util\ifnot.f
REQUIRE AllotErase devel\~moleg\lib\util\useful.f
REQUIRE STREAM[    devel\~moleg\lib\arrays\stream.f

\ пробуем удостовериться в том, что ресурс свободен
\ если свободен, устанавливаем флаг занятости, возвращаем TRUE
\ иначе FALSE
: ?LockMutex ( addr --> flag ) STREAM[ x8BD8C7C0FFFFFFFF8703F7D0 ] ;

\ освобождаем занимаемый ресурс
: UnlockMutex ( addr --> ) STREAM[ x33D287108B45008D6D04 ] ;

\ ждем освобождения ресурса, после чего его лочим за собой
: WaitUnlock ( addr --> )
             BEGIN DUP ?LockMutex WHILENOT
                   1 PAUSE    \ чтобы не расходовать квант времени до конца
             REPEAT DROP ;

0
   CELL -- off_mutex \ хранит мьютекс
   ADDR -- off_ident \ хранит число однозначно идентифицирующее задачу
CONSTANT /pmutex

\ освободить мьютекс только в случае, если он залочен текущим потоком
\ иначе ждем освобождения мьютекса
: free-mutex ( 'pmutex --> )
             >R BEGIN R@ ?LockMutex WHILENOT
                      R@ off_ident @ TlsIndex@ = WHILENOT
                  1 PAUSE 
              REPEAT
             THEN R> UnlockMutex ;

\ присвоить мьютекс и запомнить taskid застолбившей задачи
: lock-mutex ( 'pmutex --> ) DUP WaitUnlock  TlsIndex@ SWAP off_ident A! ;

\ по сути то же, что и MUTEX: только фиксирует еще и id потока
\ (то есть уникальное число для потока) используется вместе с free-mutex,
\ который освобождать умеет только мьютексы залоченные в собственном потоке
: PMUTEX: ( / name --> )
          CREATE /pmutex AllotErase
          ( 'cfa --> )
          DOES> DUP >R lock-mutex
                ['] EXECUTE CATCH
                    R> free-mutex
                THROW ;

\EOF

0 VALUE t1
0 VALUE t2

: testa ."  aaaaaa> " t1 1+ TO t1 500 PAUSE ." <aaaaa "  ;
: testb ."  bbbbbb> " t2 1+ TO t2 300 PAUSE ." <bbbbb "  ;

PMUTEX: proba

: ttt BEGIN ['] testa proba t1 . t2 . CR 0  PAUSE AGAIN ;
: eee BEGIN ['] testb proba t1 . t2 . CR 0  PAUSE AGAIN ;

' ttt TASK: testt
testt START
eee



Вернуться к началу
 Профиль Отправить личное сообщение  
Ответить с цитатой  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 11 ] 

Часовой пояс: UTC + 3 часа [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 3


Вы не можете начинать темы
Вы можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
phpBB сборка от FladeX // Русская поддержка phpBB