Re: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 07.09.06 14:02
Оценка: +1 -2 :))
SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — чистое зло и ошибка эволюции. Поток должен усыплятся когда он сам этого ждет. Каким нить мутексовым/семафоровым локом.
Re[11]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 12:54
Оценка: :))) :)
Вы хотели юзать SuspendThread в проге управляющей атомным реактором?
ггг.. /me спас мир
Re[7]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 12:40
Оценка: 75 (1)
А>Упс... А можно ли поподробнее чем череват SuspendThread в системных библиотеках (каких???). Я что-то в этой жизни похоже пропустил. здесь я даже упоминания про SuspendThread не увидел (зрение — плохое, английский ещё хуже, а поиск ничего не дал ).
Вообще говоря в любых. Многие API функции используют синхронизацию для thread-safe работы со своими внутренними структурами. memory manager тоже естественно использует дабы можно было одновременно из нескольких потоков выделять/освобождать память банальнымм malloc/free/new/delete. Если поток будет заморожен в тот момент когда он находится в синхронизироанном коде, любой другой поток при доступе к синхронизированными данным зависнет. Т.е.:
Поток A вызывает malloc. malloc уходит в HeapAlloc во втором параметре которого нету флага HEAP_NO_SERIALIZE. HeapAlloc вызовет RtlAllocateHeap. RtlAllocateHeap завладеет какимто мутексом в недрах ntdll дабы сериализовать работу с кучей между потоками. И в тот момент как поток А будет ковыряться в куче выделяя память, поток Б ему сделает SuspendThread. Поток А останется замороженным на середине выделения памяти. Все. Любая попытка другого потока выделить/освободить память приведет к его ожиданию пока поток А освободит мутекс. А он его не освободит потому что он suspended. Прога повисла. Если бы вместо SuspendThread юзался бы TerminateThread то поток А был бы убит во время работы с кучей, мутекс бы освободился, но куча бы осталась в поврежденном состоянии и прога бы свалилась.
Пример с памятью — это просто самый показательный, на самом деле многие апи функции чегото лочат. Иначе они не были бы thread-safe.
Re[2]: SuspendThread, ResumeThread для pthread
От: Pavel Dvorkin Россия  
Дата: 08.09.06 05:48
Оценка: -1
Здравствуйте, apple-antonovka, Вы писали:

AA>SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — чистое зло и ошибка эволюции.


ExitThread может вызываться только для текущего потока и это единственный (в конечном счете) способ ему закончиться, так что злом это быть никак не может.
With best regards
Pavel Dvorkin
Re[3]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 11:27
Оценка: +1
Засунуть ::WaitForSingleObject(hSuspendEvent,INFINITE); в относительно редко используемое место вычислений. Только не говорите что у вас таких нет.
Кроме того конкретно вашу задачу можно решить безо всяких остановок потоков — просто установкой IDLE приоритета наименее важным в данный момент потокам.
Re[2]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 11.09.06 08:05
Оценка: +1
Здравствуйте, apple-antonovka, Вы писали:

AA>SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — чистое зло и ошибка эволюции. Поток должен усыплятся когда он сам этого ждет. Каким нить мутексовым/семафоровым локом.


В общем-то да, только как ты вытесняющую многозадачность без этой ошибки эволюции сделаешь
Re[4]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 11.09.06 13:46
Оценка: +1
Здравствуйте, apple-antonovka, Вы писали:

А>>В общем-то да, только как ты вытесняющую многозадачность без этой ошибки эволюции сделаешь

AA>Многозадачностью и запуском/остановок в любом месте userspace кода должно заниматься ядро. А не другой юзерспейс код.
AA>Почему — см http://www.rsdn.ru/Forum/Message.aspx?mid=2103250&only=1
Автор: apple-antonovka
Дата: 11.09.06


Да я и не спорю.
Просто не стоит так вот обобщенно говорить об "ошибке эволюции".
SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 07.09.06 10:55
Оценка:
Не так давно я здесь
Автор:
Дата: 29.08.06
пытался узнать как создать "усыплённую" нить. Сейчас хочется выяснить, как покрасивее можно сделать SuspendThread(...) и ResumeThread(...) для pthreads. Как я понял стадартных средств нет (хоть бы я был не прав ). Есть идеи написать что-то вроде:
pthread_kill(..., SIGSTOP )
sleep(...)
pthread_kill(..., SIGCONT)

но нутром чую — работать не будет
Подскажите, как быть?
Re[3]: SuspendThread, ResumeThread для pthread
От: k. Россия  
Дата: 08.09.06 06:26
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Здравствуйте, apple-antonovka, Вы писали:


AA>>SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — чистое зло и ошибка эволюции.


PD>ExitThread может вызываться только для текущего потока и это единственный (в конечном счете) способ ему закончиться, так что злом это быть никак не может.


не совсем согласен. вот что говорит MSDN на эту тему:

ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[3]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 07:00
Оценка:
PD>ExitThread может вызываться только для текущего потока и это единственный (в конечном счете) способ ему закончиться, так что злом это быть никак не может.

Да это так. НО! Если ExitThread вызовется в то время как на стеке лежат какие нить плюсатые объекты их деструкторы не будут вызваны. Со всеми вытекающими.
Re[4]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 07:04
Оценка:
Немного грамотно написанных общих ошибок с потоками http://www.flounder.com/badprogram.htm
+ добавлю что SuspendThread зачастую не менее опасен чем TerminateThread.
Re[4]: SuspendThread, ResumeThread для pthread
От: Pavel Dvorkin Россия  
Дата: 08.09.06 08:26
Оценка:
Здравствуйте, k., Вы писали:

k.>ExitThread is the preferred method of exiting a thread in C code. However, in C++ code, the thread is exited before any destructors can be called or any other automatic cleanup can be performed. Therefore, in C++ code, you should return from your thread function.


Что означает, что непосредственный вызов ExitThread не рекомендуется, так как не будут вызваны деструкторы. Это верно. Но return приведет к их вызову (возврат из функции потока), а потом к выполнению финишного кода потока, который и вызовет ExitThread. Потому что выход из функции по return никак не может закончить поток, для этого надо обратиться к Win API.

А я ясно сказал "это единственный (в конечном счете)"
With best regards
Pavel Dvorkin
Re[4]: SuspendThread, ResumeThread для pthread
От: Pavel Dvorkin Россия  
Дата: 08.09.06 08:27
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

PD>>ExitThread может вызываться только для текущего потока и это единственный (в конечном счете) способ ему закончиться, так что злом это быть никак не может.


AA>Да это так. НО! Если ExitThread вызовется в то время как на стеке лежат какие нить плюсатые объекты их деструкторы не будут вызваны. Со всеми вытекающими.


См. мой ответ k.

http://rsdn.ru/Forum/Message.aspx?mid=2099941&amp;only=1
Автор: Pavel Dvorkin
Дата: 08.09.06
With best regards
Pavel Dvorkin
Re[4]: SuspendThread, ResumeThread для pthread
От: Pavel Dvorkin Россия  
Дата: 08.09.06 08:30
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

PD>>ExitThread может вызываться только для текущего потока и это единственный (в конечном счете) способ ему закончиться, так что злом это быть никак не может.


AA>Да это так. НО! Если ExitThread вызовется в то время как на стеке лежат какие нить плюсатые объекты их деструкторы не будут вызваны. Со всеми вытекающими.


И даже на чистом С вызов ExitThread (и CreateThread) не рекомендуется, так как не произойдет инициализации/очистки данных CRT. Надо beginthreadex/endthreadex. Но повторяю — я писал "(в конечном счете)"
With best regards
Pavel Dvorkin
Re[5]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 08:43
Оценка:
PD>Что означает, что непосредственный вызов ExitThread не рекомендуется, так как не будут вызваны деструкторы. Это верно. Но return приведет к их вызову (возврат из функции потока), а потом к выполнению финишного кода потока, который и вызовет ExitThread. Потому что выход из функции по return никак не может закончить поток, для этого надо обратиться к Win API.

PD>А я ясно сказал "это единственный (в конечном счете)"

Речь вроде шла об необходимости использования этой функции в своем коде. А то если так рассуждать то ExitThread в конце концов вызывает ZwTerminateThread, а CRT при выходе из WinMain/main процесса вызывает ExitProcess который дважды дергает ZwTerminateProcess. То что эти функции юзает CRT и винда отнюдь не значит что их можно безопасно юзать из своего кода.
Re[6]: SuspendThread, ResumeThread для pthread
От: Pavel Dvorkin Россия  
Дата: 08.09.06 09:16
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Речь вроде шла об необходимости использования этой функции в своем коде. А то если так рассуждать то ExitThread в конце концов вызывает ZwTerminateThread, а CRT при выходе из WinMain/main процесса вызывает ExitProcess который дважды дергает ZwTerminateProcess. То что эти функции юзает CRT и винда отнюдь не значит что их можно безопасно юзать из своего кода.


Вообще-то исходно речь шла о том, как сделать SuspendThread(...) и ResumeThread(...). TerminateThread и ExitThread обругал ты, ну я и вступился за их честь — мне без последней как-то неуютно
With best regards
Pavel Dvorkin
Re[7]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 10:58
Оценка:
PD>Вообще-то исходно речь шла о том, как сделать SuspendThread(...) и ResumeThread(...). TerminateThread
SuspendThread отличается от TerminateThread только тем что не приводит к утечке ресурсов, а в тех ситуациях когда TerminateThread убивает апликуху SuspendThread ее обычно просто завешивает

PD>и ExitThread обругал ты, ну я и вступился за их честь — мне без последней как-то неуютно

try/catch/throw не для настоящих мужчин?
Re[2]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 11:08
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — чистое зло и ошибка эволюции. Поток должен усыплятся когда он сам этого ждет. Каким нить мутексовым/семафоровым локом.

Ну... зло, не зло, но очень у меня востребовано. Есть вычисление некой траектории (ну положим — полёт на Марс ). Значит считаем мы в течении надцати часов это дело и тут нам срочно (ну прям очень срочно) нужно произвести ещё один расчёт попроще, секунд на 10, но быстро. Как тут быть? Да... забыл — процессор у нас один, нить в которой происходит расчёт траектории — без циклов (да, да просто километровая функция без циклов в которых на каждой итерации можно было бы анализировать мутекс, семафор или просто bool is_suspending = true ). Как мне быть без SuspendThread в этом случае? Я не вижу (пока — т.к. эволюционирую потихоньку) выхода. Подскажите — дайте толчок эволюции!!!
Re[4]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 11:43
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Засунуть ::WaitForSingleObject(hSuspendEvent,INFINITE); в относительно редко используемое место вычислений. Только не говорите что у вас таких нет.

AA>Кроме того конкретно вашу задачу можно решить безо всяких остановок потоков — просто установкой IDLE приоритета наименее важным в данный момент потокам.
Эх... я так и думал... пример я конечно привёл может и не совсем корректный — я вёл к тому,что SuspendThread не всегда зло и кака, и порой лучше уж с ним чем без него, а про WaitForSingleObject и т.п. — не правильно это... в моём примере это приведёт к тому что код будет усыпан этими вайтами через каждые 50-100 строк. Так что вопрос остаётся открытым — как сымитировать SuspendThread для pthreads? Лично мне это пока не ясно.
Re[5]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 11:55
Оценка:
>SuspendThread не всегда зло и кака, и порой лучше уж с ним чем без него, а про WaitForSingleObject
SuspendThread _ВСЕГДА_ зло и кака. И это не голословное утверждения из разряда "goto — зло", а реально не раз потвержденный на практике факт. На момент вызова SuspendThread поток может исполнять глобально синхронизированный код в каком нить memory manager'е или просто в системых библиотеках. И тогда придется вам пересчитывать полет на Марс заново
Re[6]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 12:17
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

>>SuspendThread не всегда зло и кака, и порой лучше уж с ним чем без него, а про WaitForSingleObject

AA>SuspendThread _ВСЕГДА_ зло и кака. И это не голословное утверждения из разряда "goto — зло", а реально не раз потвержденный на практике факт. На момент вызова SuspendThread поток может исполнять глобально синхронизированный код в каком нить memory manager'е или просто в системых библиотеках. И тогда придется вам пересчитывать полет на Марс заново
Упс... А можно ли поподробнее чем череват SuspendThread в системных библиотеках (каких???). Я что-то в этой жизни похоже пропустил. здесь я даже упоминания про SuspendThread не увидел (зрение — плохое, английский ещё хуже, а поиск ничего не дал ).
Re[8]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 12:44
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Вообще говоря в любых. Многие API функции используют синхронизацию для thread-safe работы со своими внутренними структурами. memory manager тоже естественно ....

AA>Пример с памятью — это просто самый показательный, на самом деле многие апи функции чегото лочат. Иначе они не были бы thread-safe.
Благодарю Вас за исчерпывающий ответ. Можно сказать открыли мне глаза. То, что я не наступил на подобне грабли — чистая случайность... Просто жуть — полметра кода переписывать фактически с нуля
Re[9]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 08.09.06 12:46
Оценка:
А>Благодарю Вас за исчерпывающий ответ. Можно сказать открыли мне глаза. То, что я не наступил на подобне грабли — чистая случайность... Просто жуть — полметра кода переписывать фактически с нуля
Пол-кода переписывать чтобы всунуть WaitForSingleObject и заменить SuspendThread на ResetEvent? Какой то у вас код неправильный
Re[10]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 12:51
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Пол-кода переписывать чтобы всунуть WaitForSingleObject и заменить SuspendThread на ResetEvent? Какой то у вас код неправильный

Не пол-кода, а "всего" полмегабайта — сущий пустяк для атомной энергетики Впрочем, это тема для отдельного вопроса — люди, где мне взять прямые руки?
Re[12]: SuspendThread, ResumeThread для pthread
От: Аноним  
Дата: 08.09.06 12:56
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Вы хотели юзать SuspendThread в проге управляющей атомным реактором?

AA>ггг.. /me спас мир
шутка. шутка это была.
Re[6]: SuspendThread, ResumeThread для pthread
От: gear nuke  
Дата: 10.09.06 18:36
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>SuspendThread _ВСЕГДА_ зло и кака. И это не голословное утверждения из разряда "goto — зло", а реально не раз потвержденный на практике факт. На момент вызова SuspendThread поток может исполнять глобально синхронизированный код в каком нить memory manager'е или просто в системых библиотеках.


Перефразируя Будду, корень зла — это не SuspendThread, а незнание истины.

А тред может быть остановлен в произвольные момент времени (во всех тех же, а так же многих других местах) не только SuspendThread, но планировщиком ОС. Время, на которое в последнем случае останавливается поток, никто не регламентирует! Однако многозадачность до сих пор не признана вселенским злом, а лишь жизненной необходимостью


Если проблемы вызваны непродуманным кодом
Автор: apple-antonovka
Дата: 08.09.06
— это проблема кода, а не SuspendThread. (кто мешает использовать отдельный хип для усыпляемого треда?)
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[7]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 10.09.06 19:32
Оценка:
GN>Если проблемы вызваны непродуманным кодом
Автор: apple-antonovka
Дата: 08.09.06
— это проблема кода, а не SuspendThread. (кто мешает использовать отдельный хип для усыпляемого треда?)


Проблемы SuspendThread в том что исполняющий код в принципе не может точно быть уверенным в том что тот кого он успыляет находится в безопасном месте. Если вы думаете что вы уверены — вы ошибаетесь. Ядро может использовать userspace потоки для исполнения своих APC, без их ведома. Кроме того многие АПИ функции документированно расширябельны — хуки, LSP, и конкретная их имплементация их никак не гарантируется. Пример с планировщиком ядра неудачен тк код планировщика работает на высоком IRQL и управляет потоками работающими на низких. В userspace такого механизма не предусмотрено, потому единственно безопасный вызов SuspendThread() — SuspendThread(GetCurrentThread()).
Re[8]: SuspendThread, ResumeThread для pthread
От: Cyberax Марс  
Дата: 10.09.06 19:49
Оценка:
apple-antonovka wrote:
> Проблемы SuspendThread в том что исполняющий код в принципе не может
> точно быть уверенным в том что тот кого он успыляет находится в
> безопасном месте. Если вы думаете что вы уверены — вы ошибаетесь.
> Ядро может использовать userspace потоки для исполнения своих APC, без их
> ведома.
Тут подробнее. Для каких целей? И чем тут помешает SuspendThread?

> Кроме того многие АПИ функции документированно расширябельны —

> хуки, LSP, и конкретная их имплементация их никак не гарантируется.
И что? Чем это отличается от вытеснения потока с хуком другим потоком?

> Пример с планировщиком ядра неудачен тк код планировщика работает на

> высоком IRQL и управляет потоками работающими на низких.
Мимо. Поток при обработке хука или работы в крит. секции может быть
запросто вытеснен на неопределенное время другим потоком (например, если
кто-то решил себе поставить realtime-приоритет) так как ядру это
абсолютно фиолетово.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[9]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 10.09.06 20:31
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>apple-antonovka wrote:

>> Проблемы SuspendThread в том что исполняющий код в принципе не может
>> точно быть уверенным в том что тот кого он успыляет находится в
>> безопасном месте. Если вы думаете что вы уверены — вы ошибаетесь.
>> Ядро может использовать userspace потоки для исполнения своих APC, без их
>> ведома.
C>Тут подробнее. Для каких целей? И чем тут помешает SuspendThread?
для исполнения completeion routine асинхронных операций ввода-вывода например. Чем чревато — читайте мыше.

>> Кроме того многие АПИ функции документированно расширябельны —

>> хуки, LSP, и конкретная их имплементация их никак не гарантируется.
C>И что? Чем это отличается от вытеснения потока с хуком другим потоком?
Не понимаю, причем тут вытеснение потоков.


>> Пример с планировщиком ядра неудачен тк код планировщика работает на

>> высоком IRQL и управляет потоками работающими на низких.
C>Мимо. Поток при обработке хука или работы в крит. секции может быть
C>запросто вытеснен на неопределенное время другим потоком (например, если
C>кто-то решил себе поставить realtime-приоритет) так как ядру это
C>абсолютно фиолетово.
Извините, но IRQL и приоритет потока вещи несколько разного гхм.. плана. Весь userspace код исполняется га IRQL=PASSIVE_LEVEL независимо от того приоритета потока, о котором вы пишете. Это раз.
Два — то что поток может быть вытеснен никто не спорит, он и будет вытестен если найдутся кандидаты. Речь о том что остановка потока в то время когда он исполняет некий вызов (системы, third-party library etc) чревата тем что пока замороженный поток будет находится внутри критической секции (о который вы не знаете, для вас это просто вызов функции) и не позволит никакому другому потоку вашего процесса туда залезть (читайте, вызов любой функции той библиотеки другим потоком вашего процесса приведет к зависанию другого потока).
Re[8]: SuspendThread, ResumeThread для pthread
От: gear nuke  
Дата: 10.09.06 22:52
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>SuspendThread отличается от TerminateThread только тем что не приводит к утечке ресурсов,


TerminateThread так же приводит к утечке ресурсов. Освобождение стека потока.
Автор:
Дата: 25.08.06


AA>а в тех ситуациях когда TerminateThread убивает апликуху SuspendThread ее обычно просто завешивает


People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[8]: SuspendThread, ResumeThread для pthread
От: gear nuke  
Дата: 10.09.06 22:52
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Проблемы SuspendThread в том что исполняющий код в принципе не может точно быть уверенным в том что тот кого он успыляет находится в безопасном месте.


В общем случае это верно, но для каждого частного случая можно найти исключающее проблемы решение. Пример с хипом я приводил.

AA>Если вы думаете что вы уверены — вы ошибаетесь. Ядро может использовать userspace потоки для исполнения своих APC, без их ведома.


Добавлю, что ISR так же могут выполняться в контексте любого треда, но по их завершению контекст восстанавливается. А какие от этого могут быть проблемы?

AA>Кроме того многие АПИ функции документированно расширябельны — хуки, LSP, и конкретная их имплементация их никак не гарантируется.


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

AA>Пример с планировщиком ядра неудачен тк код планировщика работает на высоком IRQL и управляет потоками работающими на низких.


Действительно, планировщик работает на IRQL DPC_LEVEL, а треды прерываются аж на CLOCK2_LEVEL. Причем, это происходит асинхронно (в отличие от синхронного SuspendThread). Это работает не только для юзерлендных тредов (PASSIVE_LEVEL), но и почти для всех возможных вообще. И ядро NT работает так уже много лет.

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

Возьмём тот же пример с хипом.
Стандарт языка С ничего не знает о тредах. Поэтому при раелизации стандартной библиотеки разработчик волен имплементировать malloc как ему захочется, и выделять из общего для всех тредов пула (нужна синхронизация) — это лишь одно из решений.
У разработчика конкретной библиотеки было 2 пути: учесть возможные проблемы, и тогда SuspendThread будет работать, или ничего не далать и объвить его "неправильным". Они пошли по простому пути.

AA>В userspace такого механизма не предусмотрено, потому единственно безопасный вызов SuspendThread() — SuspendThread(GetCurrentThread()).


Пример с расчетами полетов на Марс
Автор:
Дата: 08.09.06
(при правильном дизайне) вполне позволяет безопасно использовать SuspendThread. Установка низкого приоритета
Автор: apple-antonovka
Дата: 08.09.06
— тоже хорошее решение, но что, если юзер хочет кнопочку "pause"? Опрашивать переменную в цикле... это путь к 100% загрузки CPU и куча copy-paste WaitForSingleObject — вызов ядра (непосредственно планировщика — по сути, закат Солнца вручную).

Без SuspendThread некоторые вещи не возможны в принципе (например — вменяемый отладчик), некторые решаются заметно сложнее, и называть её "чистое зло и ошибка эволюции" — ИМХО похоже на теорию, потверждаемую ошибочной практикой. Я бы сказал, что бездумное применение этой функции может породить проблемы... но так можно о многом сказать

PS: Кстати, "вред" от усыпления тредов можно понаблюдать используя Process Explorer.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[9]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 10.09.06 23:27
Оценка:
GN>Возьмём тот же пример с хипом.
GN>Стандарт языка С ничего не знает о тредах. Поэтому при раелизации стандартной библиотеки разработчик волен имплементировать malloc как ему захочется, и выделять из общего для всех тредов пула (нужна синхронизация) — это лишь одно из решений.
GN>У разработчика конкретной библиотеки было 2 пути: учесть возможные проблемы, и тогда SuspendThread будет работать, или ничего не далать и объвить его "неправильным". Они пошли по простому пути.
Он неправильный Дело не в объявлении. Просто эта функция предоставляет низкоуровневое управление над объектом, который вы не полностью контролируете на том уровне на котором пытаетесь управлять.
Вот вы опять начинаете доказывать абстракцию на детяльных примерах, и опять неудачно
1) Память выделенная потоко-независимым хипом сама по себе потоко-зависимая. Те выделив память в отдном потоке освободить в другом не выйдет. Это уже не malloc
2) Память для этого придется выделять из общего хранилища процесса. Обращения к которому будут синхронизированы.
ХОТЯ. Вообще говоря raw VirtualAlloc/Free можно использовать на чистой системе с SuspendThread т.к. SuspendThread останавливает юзерский код, если поток исполняется в кернеле — он доделывает то что начал (по кр мере я так думаю), (вот это и назыается — управление над полностью контролируемым объектом — для ядра SuspendThread безопасен). Но пример с менежером памяти — это одна из множества потенциальных проблем. И даже использование безопасности VirtualAlloc/Free по отношению к SuspendThread — это уже опора на implementation details конретной функции под конкретной версией конкретной чистой ос. В другой системе, даже с такой же ОС, эту функцию может похукать мега-твикер-оптимизатор, а шишки покатяться на вас .


AA>>В userspace такого механизма не предусмотрено, потому единственно безопасный вызов SuspendThread() — SuspendThread

GN>Без SuspendThread некоторые вещи не возможны в принципе (например — вменяемый отладчик), некторые решаются заметно сложнее, и называть её "чистое зло и ошибка эволюции" — ИМХО похоже на теорию, потверждаемую ошибочной практикой. Я бы сказал, что бездумное применение этой функции может породить проблемы... но так можно о многом сказать
Вот не надо, отладчик — это отдельный процесс , и то он не юзает SuspendThread, а юзает генерацию исключения (банальный int 3) в потоке созданном через CreateRemoteThread в удаленном процессе и далее — WaitForDebugEvent. Про то как конкретно эти функции реаилизованы — плз не рассказывать. Абстрагируйте все внешние вызовы как черный ящик

GN>PS: Кстати, "вред" от усыпления тредов можно понаблюдать используя Process Explorer.

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

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

Вообще просто функция SuspendThread — одна из тех функций которые действительно не стоило делать в win32 api, думаю микрософтовские программеры это уже 100 раз поняли, но никуда не деться — обратную совместимость надо соблюдать.
Re[10]: SuspendThread - зло???
От: gear nuke  
Дата: 11.09.06 03:49
Оценка:
Здравствуйте, apple-antonovka,

AA>Дело не в объявлении. Просто эта функция предоставляет низкоуровневое управление над объектом, который вы не полностью контролируете на том уровне на котором пытаетесь управлять.

AA>Вот вы опять начинаете доказывать абстракцию на детяльных примерах, и опять неудачно
AA>1) Память выделенная потоко-независимым хипом сама по себе потоко-зависимая. Те выделив память в отдном потоке освободить в другом не выйдет. Это уже не malloc

Память можно освободить даже в адресном пространстве чужого процесса, что же говорить о своём Откуда там потокозависимость возьмётся? У каждого хипа свой хендл? Ну дык передавать их между тредами можно, хотя при нормальном дизайне не знаю, зачем

AA>2) Память для этого придется выделять из общего хранилища процесса. Обращения к которому будут синхронизированы.


1) Каждый тред может использовать отдельный хип.
2) Память для рабочего треда может выделять другой тред.

AA>ХОТЯ. Вообще говоря raw VirtualAlloc/Free можно использовать на чистой системе с SuspendThread т.к. SuspendThread останавливает юзерский код, если поток исполняется в кернеле — он доделывает то что начал (по кр мере я так думаю)


Не факт ведь, что правильно думаете. И на этом строите какие-то проблемы с SuspendThread. Эта функция (точнее, KeSuspendThread) поднимает IRQL до DISPATCH_LEVEL, лочит базу данных планировщика и ставит пустую APC усыпляемому треду. Так что тред запросто может быть усыплен и в ядре.

AA> (вот это и назыается — управление над полностью контролируемым объектом — для ядра SuspendThread безопасен). Но пример с менежером памяти — это одна из множества потенциальных проблем.


Ага, вот еще: 2 треда вызывают SuspendThread друг для друга Но ничего страшного из этого не выйдет, см. выше.

Все возможные проблемы SuspendThread документиррованы в MSDN:

Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread

Всё. Если обеспечить невозможность этого — можно использовать.

AA>И даже использование безопасности VirtualAlloc/Free по отношению к SuspendThread — это уже опора на implementation details конретной функции под конкретной версией конкретной чистой ос. В другой системе, даже с такой же ОС, эту функцию может похукать мега-твикер-оптимизатор, а шишки покатяться на вас .


Подозреваю, что демагогия Кто угодно может криво похукать что угодно, и ОС упадёт в BSOD.

GN>>Без SuspendThread некоторые вещи не возможны в принципе (например — вменяемый отладчик)

AA>Вот не надо, отладчик — это отдельный процесс

Прям таки обязательно — процесс? Вот цитата из MSDN о SuspendThread:

To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself.



AA> и то он не юзает SuspendThread, а юзает генерацию исключения (банальный int 3)


Остановился один из тредов на дебажном событии, что с остальными делать?

AA> в потоке созданном через CreateRemoteThread в удаленном процессе и далее — WaitForDebugEvent.


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

AA>WaitForSingleObject можно делать после проверки булевской переменной и не часто (я сам физик по образованию и потому прекрасно представляю себе что есть расчет траектории полета на марс , там будет куча редкоисполняемых мест куда мона всунуть этот вэйт, как и в любом другом алгоритме.


Марс и циклы — это частный случай. Даже с циклами, наверное, будет разница — 20 дней или 22 считать из-за постоянных WaitForSingleObject.

AA>Нет ну да вообще говоря поток выполняющий код типа for(;); мона относительно безопасно суспендить, но даже этого я бы не стал делать, мало ли что там компилер напихает , стандарт нигде не описыват что конкретно написанный код на С++ не вызовет какие нить функции синхронизации.


Откуда в C++ функции синхронизации взялись? Пока еще не вступил в силу C++09. Так что "какие нить функции" — целиком на совести разработчиков библиотеки. Подчеркну, что возможно реализовать эту библиотеку с поддержкой безопасного усыпления тредов. Точнее, когда сама библиотека не сможет оказаться источником проблем. А в своём коде пользователь и без тредов может такой каши наварить... это да.

AA>Вообще просто функция SuspendThread — одна из тех функций которые действительно не стоило делать в win32 api, думаю микрософтовские программеры это уже 100 раз поняли, но никуда не деться — обратную совместимость надо соблюдать.


ИМХО они думают: "It's not a bug, it's a feature" Даже привели в документации универсальный способ безпроблемного использования. Он потому такой и "через **", что универсальный
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: SuspendThread, ResumeThread для pthread
От: gear nuke  
Дата: 11.09.06 06:17
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Вообще просто функция SuspendThread — одна из тех функций которые действительно не стоило делать в win32 api, думаю микрософтовские программеры это уже 100 раз поняли, но никуда не деться — обратную совместимость надо соблюдать.


Проверил. Поставил на неё breakpoint. Explorer её вызывает и редактор от студии 2005 (экспресс) а так же Janus, судя по всему из .NET FrameWork
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[10]: SuspendThread, ResumeThread для pthread
От: Cyberax Марс  
Дата: 11.09.06 08:01
Оценка:
apple-antonovka wrote:
> C>Тут подробнее. Для каких целей? И чем тут помешает SuspendThread?
> для исполнения completeion routine асинхронных операций ввода-вывода
> например. Чем чревато — читайте мыше.
Вроде бы ничем не чревато. Ну не дойдут данные, и что?

>> > Кроме того многие АПИ функции документированно расширябельны —

>> > хуки, LSP, и конкретная их имплементация их никак не гарантируется.
> C>И что? Чем это отличается от вытеснения потока с хуком другим потоком?
> Не понимаю, причем тут вытеснение потоков.
В чем может быть проблема с хукнутым API и SuspendThread, которая не
проявится на установке приоритета idle и другом realtime-потоке?

> C>Мимо. Поток при обработке хука или работы в крит. секции может быть

> C>запросто вытеснен на неопределенное время другим потоком (например, если
> C>кто-то решил себе поставить realtime-приоритет) так как ядру это
> C>абсолютно фиолетово.
> Извините, но IRQL и приоритет потока вещи несколько разного гхм.. плана.
Причем здесь IRQL?

> Два — то что поток может быть вытеснен никто не спорит, он и будет

> вытестен если найдутся кандидаты. Речь о том что остановка потока в то
> время когда он исполняет некий вызов (системы, third-party library etc)
> чревата тем что пока замороженный поток будет находится внутри
> критической секции
Да. Но точно такая же ситуация возникнет, если я закручу
приоритет у другого процесса.

> (о который вы не знаете, для вас это просто вызов

> функции) и не позволит никакому другому потоку вашего процесса туда
> залезть (читайте, вызов любой функции той библиотеки другим потоком
> вашего процесса приведет к зависанию другого потока).
Это все решается контролем за тем, что используется потоком. Лично делал
систему на fibers+threads, в которой организовывался самодельный
scheduler. Никаких проблем не было.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[11]: SuspendThread - зло???
От: apple-antonovka  
Дата: 11.09.06 08:25
Оценка:
Дебаггер отдельные процесс, не имеющий в юзерспейсе никаких синхронизированных объектов с тем кого он дебагит. Поток в удаленном процессе создает windbg.

Спор перетекает в бесполезный флейм. Извините, но по должности я архитект и если увижу что какой то из программеров в моем проекте пишет одну из перечисленных в начале функий, я его настоятельно попрошу обойтись без нее. Скомпилируйте пример ниже чтоб все что я писал выше не было голословным. И учтите что константы подобраны для максимально быстрого и показательного проявления эффекта. Увеличтье слипы, поменяйте расположение маллоков и вы запросто можете добится того что код будет работать час, сутки и больше, но потом зависнет.

#include <stdlib.h>
#include <process.h>
#include <windows.h>

void __cdecl thread(void *p)
{
for(;)
{
void *p=malloc(0x100000);
Sleep(1);
free(p);
}
}

int main(int argc, char* argv[])
{
HANDLE h = (HANDLE)_beginthread(thread,0,NULL);

for(;;)
{
printf("[%08x] I'm still alive!\n",::GetTickCount());
SuspendThread(h);
void *p=malloc(0x100000);
free(p);
ResumeThread(h);
Sleep(1);
}

return 0;
}




Следующий пример отлично иллюстрирует дедлок в системной функции, по кр мере на моей системе (ХР/СП2). Зависшую консольную апликуху даже Ctrl+C не берет

#include <stdlib.h>
#include <process.h>
#include <windows.h>

void __cdecl thread(void *p)
{
    for(;;)
    {
        ::DeleteFile("foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo1");
    }
}

int main(int argc, char* argv[])
{
    HANDLE h = (HANDLE)_beginthread(thread,0,NULL);
    
    for(;;)
    {
        printf("[%08x] I'm still alive!\n", ::GetTickCount());
        ::SuspendThread(h);
        ::DeleteFile("foooooooooooooooooooooooooooooooooooooooooooooooooooooooooo2");
        ::ResumeThread(h);
        ::Sleep(0);
    }
    
    return 0;
}


И даже так (дедлок в CRT):
#include <stdlib.h>
#include <process.h>
#include <windows.h>

void __cdecl thread(void *p)
{
    for(;;)
    {
        printf("[%08x] I'm still alive too!\n",
            ::GetTickCount());
    }
}

int main(int argc, char* argv[])
{
    HANDLE h = (HANDLE)_beginthread(thread,0,NULL);
    
    for(;;)
    {
        SuspendThread(h);
        printf("[%08x] I'm still alive!\n",
            ::GetTickCount());
        ResumeThread(h);
        Sleep(0);
    }
    
    return 0;
}
Re[12]: SuspendThread - зло???
От: gear nuke  
Дата: 11.09.06 10:37
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Дебаггер отдельные процесс, не имеющий в юзерспейсе никаких синхронизированных объектов с тем кого он дебагит.


Давайте не будем обобщать. Во-первых, процесс в виндовсе не является исполняемой сущностью, а во-вторых никто не запрещает сделать поток-debigger в адресном пространстве отлаживаемого процесса. В MSDN про это прямо написано.

AA>Поток в удаленном процессе создает windbg.


Можно указать этот дополнительный тред на картинке:

?

AA>Спор перетекает в бесполезный флейм.


Ну да, это как "goto — вселенское зло".

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


Ваши корпоративные соглашения о продакшн коде могут запрещать такое использовать. Но технически это все вполне осуществимо и работает прямо сейчас в продуктах
Автор: gear nuke
Дата: 11.09.06
другой компании [размеры шварца поскипаны].

AA>Скомпилируйте пример ниже чтоб все что я писал выше не было голословным.


[]

Извините, не вижу смысла компилировать код с (намеренными?) ошибками (про которые написано в MSDN). Может быть следует убрать в треде printf() ?
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[13]: SuspendThread - зло???
От: apple-antonovka  
Дата: 11.09.06 11:55
Оценка:
GN>Давайте не будем обобщать. Во-первых, процесс в виндовсе не является исполняемой сущностью, а во-вторых никто не запрещает сделать поток-debigger в адресном пространстве отлаживаемого процесса. В MSDN про это прямо написано.
Причем тут это? (Признак флеймера — использование общеизвестных истин в качестве "доказательств", тогда как они никакой логической связи к этому не имеют)

AA>>Поток в удаленном процессе создает windbg.


GN>Можно указать этот дополнительный тред на картинке:

GN>
GN>?
use Attach to active process плз. Когда windbg стартует новый процесс он его стартует сразу суспендед


GN>Извините, не вижу смысла компилировать код с (намеренными?) ошибками (про которые написано в MSDN).

Отличная отмазка. Ошибка в первом фрагменте была изза того что код я сразу запостил без тега [code] и глупые графические смайлики сожрали все После чего просто не заметил пропущенного в исправленном варианте.

GN>Может быть следует убрать в треде printf() ?

В первых двух вариантах — не поможет. В третьем — поможет, но в третьем варианте в нем вся фича.

Вы флеймер, я с флеймерами разговоров не веду
Re[3]: SuspendThread, ResumeThread для pthread
От: apple-antonovka  
Дата: 11.09.06 12:08
Оценка:
А>В общем-то да, только как ты вытесняющую многозадачность без этой ошибки эволюции сделаешь
Многозадачностью и запуском/остановок в любом месте userspace кода должно заниматься ядро. А не другой юзерспейс код.
Почему — см http://www.rsdn.ru/Forum/Message.aspx?mid=2103250&amp;only=1
Автор: apple-antonovka
Дата: 11.09.06
Re[14]: SuspendThread - зло???
От: gear nuke  
Дата: 11.09.06 20:30
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

GN>>Давайте не будем обобщать. Во-первых, процесс в виндовсе не является исполняемой сущностью, а во-вторых никто не запрещает сделать поток-debigger в адресном пространстве отлаживаемого процесса. В MSDN про это прямо написано.

AA>Причем тут это?

Напомню ход обсуждения:
GN>>>>Без SuspendThread некоторые вещи не возможны в принципе (например — вменяемый отладчик)
AA>>>Вот не надо, отладчик — это отдельный процесс
GN>>Прям таки обязательно — процесс? Вот цитата из MSDN о SuspendThread:
GN>>

To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself.

AA>Дебаггер отдельные процесс, не имеющий в юзерспейсе никаких синхронизированных объектов с тем кого он дебагит.

AA>(Признак флеймера — использование общеизвестных истин в качестве "доказательств", тогда как они никакой логической связи к этому не имеют)



Пожалуйста, не подменяйте понятия. Я всего лишь настойчиво пытаюсь повторить общеизвестную истину "дебаггер — не обязательно отдельный процесс", которую Вы старательно игнорируете Моё "во-первых" написано для того, что бы мы тут еще и процессы не начали синхронизировать.

AA>>>Поток в удаленном процессе создает windbg.


GN>>Можно указать этот дополнительный тред на картинке:

GN>>
GN>>?
AA>use Attach to active process плз.

О, спасибо! Точно, при аттаче создает дополнительный тред. И 5 раз сработал breakpoint на SuspendThread в процессе WinDbg

AA>Когда windbg стартует новый процесс он его стартует сразу суспендед


Это не так. WinDbg вызывает CreateProcessW с параметром dwCreationFlags == 0. После этого происходит вызов SuspendThread с хендлом != -2 (эту информацию я не придумал, а посмотрел в отладчике).

Нет необходимости создавать процесс и усыплённым тредом (см. MSDN о CREATE_PROCESS_DEBUG_EVENT)

Тепрь о том, зачем отладчику нужно усыплять треды. Это нужно никак не для замены "генерации исключения (банальный int 3)". Это нужно, что бы усыпить остальные треды, когда один вызвал debug event. Про это есть в MSDN (см. About Basic Debugging)

Writing the Debugger's Main Loop
The debugger uses the WaitForDebugEvent function at the beginning of its main loop. This function blocks the debugger until a debugging event occurs. When the debugging event occurs, the system suspends all threads in the process being debugged and notifies the debugger of the event.


GN>>Извините, не вижу смысла компилировать код с (намеренными?) ошибками (про которые написано в MSDN).

AA>Отличная отмазка. Ошибка в первом фрагменте была изза того что код я сразу запостил без тега [code] и глупые графические смайлики сожрали все После чего просто не заметил пропущенного в исправленном варианте.

Я не имел ввиду какие-либо опечатки.

GN>>Может быть следует убрать в треде printf() ?

AA>В первых двух вариантах — не поможет. В третьем — поможет, но в третьем варианте в нем вся фича.

Фича??? Это прямое нарушение документации:

Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread.

Поскольку printf использует общий ресурс, он обязательно скрывает механизмы синхронизаци. Получили что и хотели. То же и с malloc... да любой пример приведите — он будет нарушать этот пункт.

AA>Вы флеймер, я с флеймерами разговоров не веду


Угу. Защищаю "священную идею" — SuspendThread, ResumeThread, TerminateThread и отчасти ExitThread/_exitthread — НЕ чистое зло и ошибка эволюции.

Но ничего не пытаюсь Вам доказать. Хочу лишь показать другим, что примеры о вреде SuspendThread похожи вот на что:
int main()
{
  int * p = 0;
  *p++; // вывод: указатели - вселенское зло.
}
Да, вывод — это правда о указателях. Но не вся правда.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[12]: SuspendThread - зло???
От: Аноним  
Дата: 12.10.06 12:28
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

AA>Скомпилируйте пример ниже чтоб все что я писал выше не было голословным. И учтите что константы подобраны для максимально быстрого и показательного проявления эффекта. Увеличтье слипы, поменяйте расположение маллоков и вы запросто можете добится того что код будет работать час, сутки и больше, но потом зависнет.


AA>
AA>#include <stdlib.h>
AA>#include <process.h>
AA>#include <windows.h>

AA>void __cdecl thread(void *p)
AA>{
AA>for(;)
AA>{
AA>void *p=malloc(0x100000);
AA>Sleep(1);
AA>free(p);
AA>}
AA>}

AA>int main(int argc, char* argv[])
AA>{
AA>HANDLE h = (HANDLE)_beginthread(thread,0,NULL);

AA>for(;;)
AA>{
AA>printf("[%08x] I'm still alive!\n",::GetTickCount());
AA>SuspendThread(h);
AA>void *p=malloc(0x100000);
AA>free(p);
AA>ResumeThread(h);
AA>Sleep(1);
AA>}

AA>return 0;
AA>}
AA>


В этом примере, если используется многопоточная CRT (а однопоточную тут и вовсе использовать некорректно), ф-я malloc(), вызываемая из ф-ции thread() наступает на критическую секцию, после чего основной поток останавливает поток thread(), и вызвавает все тот же malloc(). естественно возникает дедлок. Ровно таже фигня и со всеми остальными примерами.

А вот это:
AA>Спор перетекает в бесполезный флейм. Извините, но по должности я архитект и если увижу что какой то из программеров в моем проекте пишет одну из перечисленных в начале функий, я его настоятельно попрошу обойтись без нее.
ничто иное, как понтокидательство, к делу относящееся весьма косвенно.
Re[13]: SuspendThread - зло???
От: Аноним  
Дата: 12.10.06 14:06
Оценка:
http://www.rsdn.ru/Forum/Message.aspx?mid=2100705&amp;only=1
Автор: apple-antonovka
Дата: 08.09.06
Re[8]: SuspendThread, ResumeThread для pthread
От: remark Россия http://www.1024cores.net/
Дата: 13.10.06 04:09
Оценка:
Здравствуйте, apple-antonovka, Вы писали:

А>>Упс... А можно ли поподробнее чем череват SuspendThread в системных библиотеках (каких???). Я что-то в этой жизни похоже пропустил. здесь я даже упоминания про SuspendThread не увидел (зрение — плохое, английский ещё хуже, а поиск ничего не дал ).

AA>Вообще говоря в любых. Многие API функции используют синхронизацию для thread-safe работы со своими внутренними структурами. memory manager тоже естественно использует дабы можно было одновременно из нескольких потоков выделять/освобождать память банальнымм malloc/free/new/delete. Если поток будет заморожен в тот момент когда он находится в синхронизироанном коде, любой другой поток при доступе к синхронизированными данным зависнет. Т.е.:
AA>Поток A вызывает malloc. malloc уходит в HeapAlloc во втором параметре которого нету флага HEAP_NO_SERIALIZE. HeapAlloc вызовет RtlAllocateHeap. RtlAllocateHeap завладеет какимто мутексом в недрах ntdll дабы сериализовать работу с кучей между потоками. И в тот момент как поток А будет ковыряться в куче выделяя память, поток Б ему сделает SuspendThread. Поток А останется замороженным на середине выделения памяти. Все. Любая попытка другого потока выделить/освободить память приведет к его ожиданию пока поток А освободит мутекс. А он его не освободит потому что он suspended. Прога повисла. Если бы вместо SuspendThread юзался бы TerminateThread то поток А был бы убит во время работы с кучей, мутекс бы освободился, но куча бы осталась в поврежденном состоянии и прога бы свалилась.
AA>Пример с памятью — это просто самый показательный, на самом деле многие апи функции чегото лочат. Иначе они не были бы thread-safe.

Всё это верно только для "старых" lock-based OC.

Вот это "Иначе они не были бы thread-safe" вообще имхо устаревшее мнение, не факт, что верно для всех функций даже для современных ОС, в т.ч. для Win. Т.к. они тоже потихоньку допирают до lock-free. Достаточно поглядеть на функцию InitializeSListHead. И thread-safe и без критических секций.

lock-free подход лишён многих недостатков традиционного lock-based и в т.ч. всего описанного выше, а также deallock'ов, priority inversion, control serialization, zero scalability и т.д.

Правда на данном этапе, что касается полностью lock-free ОС, это пока "университетские" разработки. Т.ч. сейчас SuspendThread() делать не надо


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[14]: SuspendThread - зло???
От: Аноним  
Дата: 13.10.06 09:07
Оценка:
А>http://www.rsdn.ru/Forum/Message.aspx?mid=2100705&amp;only=1
Автор: apple-antonovka
Дата: 08.09.06


я про это и говорю. понятно, что не сама malloc встает на лочку, а виндовая функция.
Re[15]: SuspendThread - зло???
От: Аноним  
Дата: 13.10.06 09:10
Оценка:
А>я про это и говорю. понятно, что не сама malloc встает на лочку, а виндовая функция.
Это зависит от реализации. Нельзя закладываться на реализацию. Поставьте STLPORT с SGI optimized allocator получите дедлок на уровне STL. Мыслите шире. SuspendThread управлет объектом (потоком) на том уровне на котором вы не имеете полного контроля над этим объектом из userspace.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.