информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Страшный баг в WindowsВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Phrack #70/0x46 
 Возможно, Facebook наступил на... 
 50 лет электронной почте 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Не совсем так. Я постараюсь далее показать на цифрах... 22.08.08 09:17  Число просмотров: 2103
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 22.08.08 09:28  Количество правок: 2
<"чистая" ссылка>
> > Нет не сильно, но теоретически дольше.
> Даже не теоретически, а реально дольше. Но это такие
> копейки по сравнению с остальным, что даже говорить как-то.

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

> Это в простом случае. А вот такой момент: в одном потоке ты
> вызываешь WSARecv с синхронным завершением (и логикой
> обработки сразу), и одновременно в другом у тебя
> срабатывает GetQueuedCompletionStatus на этот приход. Что
> делать?

А сам-то что думаешь, что делать? Давай на минуту отвлечёмся от темы топика. Пусть, как я написал в реализации функции read (DWORD bytes_to_read) (см. в начале нитки), все запросы обрабатываются, как асинхронные (т.е имеем стандартное решение, когда количество полученных байт берётся из OVEPLAPPED::InternalHigh по завершению ::GetQueuedCompletionStatus(...), и нет этой ). Пусть мы имеем 4CPU и число конкурерентных потоков разрешённых использовать IOCP - 8. Тогда с большой вероятностью два или более потока (на разных CPU) могут одновременно обрабатывать разные pending issue из очереди IOCP для одно и того же сокета вне всякой последовательности:

1) Клиент посылает пакеты 1Mb + 1 Mb + ...
2) Драйвер получил данные (0.5Mb) и поместил issue в очередь IOCP
3) Поток 1 получил данные (0.5Mb) на ::GetQueuedCompletionStatus(...), начал обработку и .... произошло переключение контекста потока. Ужос !
4) Драйвер получил данные (0.3Mb) и поместил issue в очередь IOCP
5) Поток 8 получил данные (0.3Mb) на ::GetQueuedCompletionStatus(...), начал обработку и .... с радостью продолжил поломав при этом последовательность байт (поток 1 ещё не закончил или даже не начинал). Ужос !
6) Потоки 2,3,4,5,6,7 такого натворят, что только держись.

Чтобы прекратить это безобразие, я бы сделал так (кстати это решает вопрос, что делать, если во время синхронной обработки придёт завершение pending I/O):
static DWORD WINAPI worker_thread_proc(LPVOID lParam)
{
	Socket_overlapped_acceptor& acceptor =reinterpret_cast<Socket_overlapped_acceptorgt;(lParam);
	DWORD num_bytes = 0;
	ULONG_PTR comp_key = 0;
	OVERLAPPED* poverlapped = NULL;


	while ( false == acceptor.m_exit_pool_thread_flag /* in addition to ::PostQueuedCompletionStatus(m_completion_port, 0, CK_EXIT_THREAD, NULL) for all the threads*/)
	{
		BOOL fOk = ::GetQueuedCompletionStatus(acceptor.m_completion_port, &num_bytes, &comp_key, &poverlapped, IOCP_TIMEOUT);

		if(fOk)
		{
			...
			...
			if (comp_key == CK_READ)
			{
				bool queue_next_overlapped_request = true;
				_ASSERT(poverlapped);
				Client_proxy_connector* connector = static_cast<Client_proxy_connector*>(poverlapped);
				Lock lock(&connector->m_cs);

				do
				{

					// Call of the function "connector->read()" returns false, if there has been an I/O error.
					// Read operation returns true in two cases:
					//	- socket connector has read all the data requested (reading is completed).
					//	- socket connector has partially read data; there are some data left (I/O pending).

					if(false == connector->read(CONNECTOR_PACKET_SIZE))
					{
						LOG("Failed reading data from the connector.");
						acceptor.release_client(connector);
						break;
					}
					else if(true == connector->is_io_completed() )
					{
						if (connector->is_on_command())
						{
							// The command is OK. Proceed the command and read next one.

						}
						else
						{
							LOG("Error: invalid command.");
							acceptor.release_client(connector);
							break;
						}
					}
					else
					{
						// IO pending. Wait for IO completion on ::GetQueuedCompletionStatus(...)
						queue_next_overlapped_request = false;
					}
				}
				while (true == queue_next_overlapped_request);
			}
			...
			...
		}
		else
		{
			// TO DO on error
		}
	}
	return (0);
}

---

Поправь, если я не прав.

> В общем не ломай голову над несуществующей проблемой :)

Немного поломаю що :( Я не могу кансельнуть дубликаты issues на IOCP для операций которые завершились синхронно. ::CancelIo((HANDLE) m_socket) не помогает.
<programming> Поиск 








Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2021 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach