Forth http://fforum.winglion.ru/ |
|
синхронизация задач - мьютексы http://fforum.winglion.ru/viewtopic.php?f=16&t=831 |
Страница 1 из 1 |
Автор: | mOleg [ Сб июн 30, 2007 00:41 ] |
Заголовок сообщения: | синхронизация задач - мьютексы |
Мьютекс, это такая штука, которая запрещает одновременно выполнять одно и то же действие, например доступ к одному устройству двум и более процессам одновременно. Наиболее простой и быстрый вариант, нежели семафоры, например. Код: \ 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 при работе в многопоточном режиме бывает необходимо быть уверенным, что к ресурсу имеется монопольный доступ. |
Автор: | mOleg [ Сб июн 30, 2007 02:02 ] |
Заголовок сообщения: | |
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 или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс. Ну и третье, область видимости мьютекса для приведенных примеров различна, в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде. да, и еще - не вижу ничего плохого в том, что добавляется еще одна либа, у куже существующим, тем более, что она отличается от них. |
Автор: | mOleg [ Сб июн 30, 2007 02:18 ] |
Заголовок сообщения: | |
profiT писал(а): mOleg писал(а):данный пример находится не в теме SPF а в теме OS так что все виндошные примочки отпадают, это раз.
mOleg писал(а):в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде тем не менее одно другому не противоречит и из одного вытекает второе Просто не обязательно напоминать, что есть и другие варианты, потому как выглядит упреком. |
Автор: | ygrek [ Сб июн 30, 2007 12:46 ] |
Заголовок сообщения: | |
Фигню пишет кто-то другой. Вы вообще понимаете что такое мутексы? mOleg писал(а): данный пример находится не в теме SPF а в теме OS так что все виндошные примочки отпадают, это раз. Мутексы не могут быть реализованы на уровне выше чем ядро ОС (планировщик/переключатель потоков), а т.к. вся Forth OS существует до сих пор только в виде флейма то и приведённая реализация имеет нулевую ценность и вообще называться мутексами никак не может. В коде демонстрируется пример на виндовских потоках. Это просто бред. Запустите 100 потоков, возьмите один ресурс и попробуйте залочить этими с позволения сказать "мутексами". mOleg писал(а): Второе, есть различие в том, вызываешь ли ты внешнюю функцию из DLL или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс. Мда? DLL отображается на адресное пространство процесса и вызов функции DLL ничем не отличается от вызова "внутренней" функции. mOleg писал(а): Ну и третье, область видимости мьютекса для приведенных примеров различна, в моем случае все ограничивается только пределами форт-системы(СПФ) вместе с ее потоками, в то время, как для других приведенных либ мьютексы видны всем прогам в винде.
Видны только именованные мутексы. Неименованные надо передавать другому процессу явно. Обсуждать подобные отличия этой "реализации" вообще смешно т.к. она не выполняет (и не может в принципе выполнять) своего прямого назначения - обеспечивать монопольный доступ к разделяемым ресурсам. |
Автор: | mOleg [ Сб июн 30, 2007 21:25 ] |
Заголовок сообщения: | |
ygrek писал(а): Вы вообще понимаете что такое мутексы? вполне ygrek писал(а): Мутексы не могут быть реализованы на уровне выше чем ядро ОС (планировщик/переключатель потоков), а т.к. вся Forth OS существует до сих пор только в виде флейма то и приведённая реализация имеет нулевую ценность и вообще называться мутексами никак не может. читайте доку, как раз таки могут и используются. ygrek писал(а): В коде демонстрируется пример на виндовских потоках. Это просто бред. Запустите 100 потоков, возьмите один ресурс и попробуйте залочить этими с позволения сказать "мутексами". я же сказал, только в пределах одной запущенной форт-системы с ее потоками. То есть, например, можно добавить возможность многопоточной компиляции, за счет именно такого мьютекса (системный использовать смысла нет). ygrek писал(а): Второе, есть различие в том, вызываешь ли ты внешнюю функцию из DLL или используешь внутреннюю, по крайней мере по скорости, особенно для такой быстрой вещи, как мьютекс. Мда? DLL отображается на адресное пространство процесса и вызов функции DLL ничем не отличается от вызова "внутренней" функции. любой вызов функции ДЛЛ в СПФ очень накладен!!! Поэтому главное отличие - это время исполнения, ну и область видимости данного мьютекса. ygrek писал(а): Видны только именованные мутексы. Неименованные надо передавать другому процессу явно.
Обсуждать подобные отличия этой "реализации" вообще смешно т.к. она не выполняет (и не может в принципе выполнять) своего прямого назначения - обеспечивать монопольный доступ к разделяемым ресурсам. слишком громко сказано. Но при этом бездоказательно!!! еще раз читай внимательно, в рамках одной запущенной форт-системы такими мьютексами можно пользоваться. Разделяемым ресурсом может быть словарь, например (он и есть такой) |
Автор: | mOleg [ Сб июн 30, 2007 21:45 ] |
Заголовок сообщения: | |
ygrek писал(а): вся Forth OS существует до сих пор только в виде флейма
ну, теперь не только в виде флейма не у всех с окончанием флейма кончилось желание что-либо делать в этом направлении! |
Автор: | ygrek [ Сб июн 30, 2007 22:57 ] |
Заголовок сообщения: | |
Ок, я был не совсем прав. Во-первых то что реализовал mOleg на самом деле работает и обеспечивает монопольный доступ. В связи с чем прошу простить меня за резкие высказывания насчёт работоспособности этой либы.. (Надо было сначала проверить а не языком ляпать).. Во-вторых это всё таки никак не мутексы. Ибо по определению мутекс это обьект ядра. В-третьих то что реализовано называется спин-блокировкой. Насколько я понял суть в том что команда xchg по умолчанию имеет префикс LOCK который аппаратно запрещает доступ к адресуемой ячейке памяти. Именно в этом месте и происходит исключение взаимной порчи. В KERNEL32.DLL есть эквивалентная функция (точнее семейство функций) - InterlockedExchange. На Win98 её код аналогичен тому что привёл mOleg, на WinXP немного отличается. Проверял дизасмом. Недостаток спин-блокировки в том что в цикле проверки абсолютно впустую тратится процессорное время. Чтобы с этим справиться можно в слово WaitUnlock добавить 0 PAUSE. Итого вывод - в обязательном порядке читать всем Рихтера |
Автор: | mOleg [ Сб июн 30, 2007 23:54 ] |
Заголовок сообщения: | |
ygrek писал(а): Во-первых то что реализовал mOleg на самом деле работает и обеспечивает монопольный доступ. В связи с чем прошу простить меня за резкие высказывания насчёт работоспособности этой либы.. (Надо было сначала проверить а не языком ляпать).. Во-вторых это всё таки никак не мутексы. Ибо по определению мутекс это обьект ядра. вообще, то, что я привел, тоже называется мьютексом по крайней мере в нескольких книгах. И вполне возможно под виндой называется иначе. Я не обижен ygrek писал(а): В-третьих то что реализовано называется спин-блокировкой. Насколько я понял суть в том что команда xchg по умолчанию имеет префикс LOCK который аппаратно запрещает доступ к адресуемой ячейке памяти. да, поэтому данный код будет работоспособен даже на многопроцессорных машинах, но, при условии, что страница памяти. в которой хранится переменная блокировки не находится в кеше, а это можно обеспечить только на уровне ядра ОС но в рамках одной форт-системы по-любому работоспособно. ygrek писал(а): На Win98 её код аналогичен тому что привёл mOleg, на WinXP немного отличается. Проверял дизасмом. странно не думал, неужели полностью аналогичен? вместе с NOT EAX ? ygrek писал(а): Недостаток спин-блокировки в том что в цикле проверки абсолютно впустую тратится процессорное время. Чтобы с этим справиться можно в слово WaitUnlock добавить 0 PAUSE.
на самом деле все не совсем так, как взаправду дело в том, что основное слово ?LockMutex предполагает, что можно многократно пытаться залочить ресурс, но при обломе заниматься другими делами То есть не обязательно пользоваться WaitUnlock при работе ( это только вариант исполнения ) |
Автор: | ygrek [ Вс июл 01, 2007 11:03 ] |
Заголовок сообщения: | |
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 |
Автор: | mOleg [ Вс июл 01, 2007 21:21 ] |
Заголовок сообщения: | |
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 ; |
Автор: | mOleg [ Вт июл 17, 2007 01:07 ] |
Заголовок сообщения: | |
продолжение. Теперь освободить мьютекс может только залочивший его поток. В случае попытки освободить мьютекс из другого потока будет выполняться ожидание. Код: \ 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 |
Автор: | Victor__v [ Ср янв 09, 2019 23:49 ] |
Заголовок сообщения: | Re: синхронизация задач - мьютексы |
В x86 есть комманда CMPXCHG Соот-но сравнить и поменять за одну инструкцию Может лучше её использовать, во избежание шустрых потоков Быстро узнали что по адресу записан 0 записали единичку и поехали |
Автор: | Victor__v [ Сб янв 12, 2019 12:54 ] |
Заголовок сообщения: | Re: синхронизация задач - мьютексы |
Двоичный семафор для x86 Это мы компилируем в бинарник LOCKEDx32.BIN Код: use32 ; без этого фасм тупит почему-то ; проверить addr ; если в нём пусто (0), то загрузить в переменную 1 ; и положить на стек 0 - признак того, что ресурс свободен ; если же в переменной что-то есть, то это укладывается на стек ; addr -- 0|1 MOV EBX, EAX XOR EAX, EAX MOV EDX, 1h ; сравниваем [EBX] и EAX и если равно загружаем в [EBX] EDX LOCK CMPXCHG [EBX], EDX RET Файл LOCKED.F Цитата: \ если addr свободен занять его и положить на стек 0 \ иначе положить на стек число из переменной addr HEADER LOCKING? \ addr -- 0|n LOCKEDx32.BIN:BIN Сам двоичный семафор Код: LOCKED.F
: THREAD-TIME-ZERO 0 PAUSE ; \ отдать оставшееся время другим потокам \ дождаться когда семафор освободиться и занять его : ONLY-THREAD ( addr -- ) >R BEGIN R@ LOCKING? WHILE THREAD-TIME-ZERO REPEAT RDROP ; \ дождаться когда семафор освободиться и занять его, а после выполнения последующего кода обнулить семафор : LOCK: \ addr -- >R R@ ONLY-THREAD 1 RPICK EXECUTE R> 0! RDROP ; |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа [ Летнее время ] |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |