Exemplo n.º 1
0
static int port__poll(port_state_t* port_state,
                      struct epoll_event* epoll_events,
                      OVERLAPPED_ENTRY* iocp_events,
                      DWORD maxevents,
                      DWORD timeout) {
  DWORD completion_count;

  if (port__update_events(port_state) < 0)
    return -1;

  port_state->active_poll_count++;

  LeaveCriticalSection(&port_state->lock);

  BOOL r = GetQueuedCompletionStatusEx(port_state->iocp,
                                       iocp_events,
                                       maxevents,
                                       &completion_count,
                                       timeout,
                                       FALSE);

  EnterCriticalSection(&port_state->lock);

  port_state->active_poll_count--;

  if (!r)
    return_map_error(-1);

  return port__feed_events(
      port_state, epoll_events, iocp_events, completion_count);
}
Exemplo n.º 2
0
Arquivo: core.c Projeto: Kitware/CMake
static void uv__poll(uv_loop_t* loop, DWORD timeout) {
  BOOL success;
  uv_req_t* req;
  OVERLAPPED_ENTRY overlappeds[128];
  ULONG count;
  ULONG i;
  int repeat;
  uint64_t timeout_time;

  timeout_time = loop->time + timeout;

  for (repeat = 0; ; repeat++) {
    success = GetQueuedCompletionStatusEx(loop->iocp,
                                          overlappeds,
                                          ARRAY_SIZE(overlappeds),
                                          &count,
                                          timeout,
                                          FALSE);

    if (success) {
      for (i = 0; i < count; i++) {
        /* Package was dequeued, but see if it is not a empty package
         * meant only to wake us up.
         */
        if (overlappeds[i].lpOverlapped) {
          req = uv_overlapped_to_req(overlappeds[i].lpOverlapped);
          uv_insert_pending_req(loop, req);
        }
      }

      /* Some time might have passed waiting for I/O,
       * so update the loop time here.
       */
      uv_update_time(loop);
    } else if (GetLastError() != WAIT_TIMEOUT) {
      /* Serious error */
      uv_fatal_error(GetLastError(), "GetQueuedCompletionStatusEx");
    } else if (timeout > 0) {
      /* GetQueuedCompletionStatus can occasionally return a little early.
       * Make sure that the desired timeout target time is reached.
       */
      uv_update_time(loop);
      if (timeout_time > loop->time) {
        timeout = (DWORD)(timeout_time - loop->time);
        /* The first call to GetQueuedCompletionStatus should return very
         * close to the target time and the second should reach it, but
         * this is not stated in the documentation. To make sure a busy
         * loop cannot happen, the timeout is increased exponentially
         * starting on the third round.
         */
        timeout += repeat ? (1 << (repeat - 1)) : 0;
        continue;
      }
    }
    break;
  }
}
Exemplo n.º 3
0
void Dispatcher::yield() {
  assert(GetCurrentThreadId() == threadId);
  for (;;) {
    LARGE_INTEGER frequency;
    LARGE_INTEGER ticks;
    QueryPerformanceCounter(&ticks);
    QueryPerformanceFrequency(&frequency);
    uint64_t currentTime = ticks.QuadPart / (frequency.QuadPart / 1000);
    auto timerContextPair = timers.begin();
    auto end = timers.end();
    while (timerContextPair != end && timerContextPair->first <= currentTime) {
      timerContextPair->second->interruptProcedure = nullptr;
      pushContext(timerContextPair->second);
      timerContextPair = timers.erase(timerContextPair);
    }

    OVERLAPPED_ENTRY entries[16];
    ULONG actual = 0;
    if (GetQueuedCompletionStatusEx(completionPort, entries, 16, &actual, 0, TRUE) == TRUE) {
      assert(actual > 0);
      for (ULONG i = 0; i < actual; ++i) {
        if (entries[i].lpOverlapped == reinterpret_cast<LPOVERLAPPED>(remoteSpawnOverlapped)) {
          EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection));
          assert(remoteNotificationSent);
          assert(!remoteSpawningProcedures.empty());
          do {
            spawn(std::move(remoteSpawningProcedures.front()));
            remoteSpawningProcedures.pop();
          } while (!remoteSpawningProcedures.empty());

          remoteNotificationSent = false;
          LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection));
          continue;
        }

        NativeContext* context = reinterpret_cast<DispatcherContext*>(entries[i].lpOverlapped)->context;
        context->interruptProcedure = nullptr;
        pushContext(context);
      }
    } else {
      DWORD lastError = GetLastError();
      if (lastError == WAIT_TIMEOUT) {
        break;
      } else if (lastError != WAIT_IO_COMPLETION) {
        throw std::runtime_error("Dispatcher::yield, GetQueuedCompletionStatusEx failed, " + errorMessage(lastError));
      }
    }
  }

  if (firstResumingContext != nullptr) {
    pushContext(currentContext);
    dispatch();
  }
}
void
worker_thread_impl::loop( )
{
  ++data.number_threads;
  try {
    this_wthread = (thr_queue::worker_thread*) ( this );
    coroutine master_cor;
    global_thread_pool::after_yield_f after_yield_f;
    master_coroutine = &master_cor;
    after_yield      = &after_yield_f;

    OVERLAPPED_ENTRY olapped_entry;

    auto wait_cond = [&] {
      while ( true ) {
        auto wait_time = data.shutting_down ? 0 : INFINITE;
        ULONG removed_entries;
        auto wait_iocp =
          GetQueuedCompletionStatusEx( data.iocp, &olapped_entry, 1, &removed_entries, wait_time, true );
        if ( !wait_iocp ) {
          auto err = GetLastError( );
          if ( err == WAIT_IO_COMPLETION ) {
            continue;
          } else {
            if ( err != WAIT_TIMEOUT ) {
              LOG( ) << "GetQueuedCompletionStatus: " << err;
            }
            return false;
          }
        } else {
          break;
        }
      }
      return true;
    };

    do {
      if ( olapped_entry.lpCompletionKey != data.queue_completionkey ) {
        handle_io_operation( olapped_entry );
      } else {
        do_work( );
      }
    } while ( wait_cond( ) );
  } catch ( std::exception& e ) {
    LOG( ) << "caught when worker thread was stopping: " << e.what( );
  }
  --data.number_threads;
  get_internals( ).stopped = true;
}
Exemplo n.º 5
0
int SelEpolKqEvPrt::getEvents()
{
	int numEvents = -1;
	#if defined(USE_WIN_IOCP)
		#ifdef OS_MINGW_W64
			IOOverlappedEntry entries[64];
			ULONG nEvents = 0;
			if(!GetQueuedCompletionStatusEx(iocpPort,
						(OVERLAPPED_ENTRY*)entries,
						64,
	                    &nEvents,
						(DWORD)this->timeoutMilis,
						FALSE)) {
				int errCd = WSAGetLastError();
				if(errCd != WAIT_TIMEOUT)
				{
					std::cout << "Error occurred during GetQueuedCompletionStatusEx " << WSAGetLastError() << std::endl;
				}
	           	return -1;
	        }
			psocks.clear();
			for(long i = 0; i < (long)nEvents; i++) {
				DWORD qty;
				DWORD flags;
				if(WSAGetOverlappedResult(entries[i].o->sock, (LPWSAOVERLAPPED)entries[i].o, &qty, FALSE, &flags))
				{
					psocks.push_back(entries[i].o);
				}
			}
			return (int)psocks.size();
		#else
			OVERLAPPED       *pOverlapped = NULL;
			IOOperation *lpContext = NULL;
			DWORD            dwBytesTransfered = 0;
			BOOL bReturn = GetQueuedCompletionStatus(iocpPort,
								&dwBytesTransfered,
								(LPDWORD)&lpContext,
								&pOverlapped,
								(DWORD)this->timeoutMilis);
			if (FALSE == bReturn)
			{
				return -1;
			}
			IOOperation* iops = (IOOperation*)lpContext;
			psocks.clear();
			psocks.push_back(iops);
			return 1;
		#endif
	#elif defined(USE_MINGW_SELECT)
		readfds = master;
		if(timeoutMilis>1)
		{
			struct timeval tv;
			tv.tv_sec = (timeoutMilis/1000);
			tv.tv_usec = (timeoutMilis%1000)*1000;
			numEvents = select(fdMax+1, &readfds, NULL, NULL, &tv);
		}
		else
		{
			numEvents = select(fdMax+1, &readfds, NULL, NULL, NULL);
		}
		if(numEvents==-1)
		{
			perror("select()");
		}
		else
		{
			if(fdMax>0)
				return fdMax+1;
		}
	#elif defined(USE_SELECT)
		for (int var = 0; var < fdsetSize; ++var) {
			readfds[var] = master[var];
		}
		if(timeoutMilis>1)
		{
			struct timeval tv;
			tv.tv_sec = (timeoutMilis/1000);
			tv.tv_usec = (timeoutMilis%1000)*1000;
			numEvents = select(fdMax+1, readfds, NULL, NULL, &tv);
		}
		else
		{
			numEvents = select(fdMax+1, readfds, NULL, NULL, NULL);
		}
		if(numEvents==-1)
		{
			perror("select()");
		}
		else
		{
			if(fdMax>0)
				return fdMax+1;
		}
	#elif defined USE_EPOLL
		int ccfds = curfds;
		if(curfds<=0) {
			ccfds = 1;
		}
		numEvents = epoll_wait(epoll_handle, events, ccfds+1, timeoutMilis);
	#elif defined USE_KQUEUE
		if(timeoutMilis>1)
		{
			struct timespec tv;
			tv.tv_sec = (timeoutMilis/1000);
			tv.tv_nsec = (timeoutMilis%1000)*1000000;
			numEvents = kevent(kq, NULL, 0, evlist, MAXDESCRIPTORS, &tv);
		}
		else
		{
			numEvents = kevent(kq, NULL, 0, evlist, MAXDESCRIPTORS, NULL);
		}
	#elif defined USE_DEVPOLL
		struct dvpoll pollit;
		pollit.dp_timeout = timeoutMilis;
		pollit.dp_nfds = curfds;
		pollit.dp_fds = polled_fds;
		numEvents = ioctl(dev_poll_fd, DP_POLL, &pollit);
	#elif defined USE_EVPORT
		uint_t nevents, wevents = 0;
		if(timeoutMilis>1)
		{
			struct timespec tv
			tv.tv_sec = (timeoutMilis/1000);
			tv.tv_nsec = (timeoutMilis%1000)*1000000;
			//uint_t num = 0;
			if (port_getn(port, evlist, 0, &wevents, &tv) < 0) return 0;
			if (0 == wevents) wevents = 1;
			nevents = wevents;
			if (port_getn(port, evlist, (uint_t) MAXDESCRIPTORS, &nevents, &tv) < 0) return 0;
		}
		else
		{
			//uint_t num = 0;
			if (port_getn(port, evlist, 0, &wevents, NULL) < 0) return 0;
Exemplo n.º 6
0
void Dispatcher::dispatch() {
  assert(GetCurrentThreadId() == threadId);
  NativeContext* context;
  for (;;) {
    if (firstResumingContext != nullptr) {
      context = firstResumingContext;
      firstResumingContext = context->next;

      assert(context->inExecutionQueue);
      context->inExecutionQueue = false;
      
      break;
    }

    LARGE_INTEGER frequency;
    LARGE_INTEGER ticks;
    QueryPerformanceCounter(&ticks);
    QueryPerformanceFrequency(&frequency);
    uint64_t currentTime = ticks.QuadPart / (frequency.QuadPart / 1000);
    auto timerContextPair = timers.begin();
    auto end = timers.end();
    while (timerContextPair != end && timerContextPair->first <= currentTime) {
      pushContext(timerContextPair->second);
      timerContextPair = timers.erase(timerContextPair);
    }

    if (firstResumingContext != nullptr) {
      context = firstResumingContext;
      firstResumingContext = context->next;

      assert(context->inExecutionQueue);
      context->inExecutionQueue = false;

      break;
    }

    DWORD timeout = timers.empty() ? INFINITE : static_cast<DWORD>(std::min(timers.begin()->first - currentTime, static_cast<uint64_t>(INFINITE - 1)));
    OVERLAPPED_ENTRY entry;
    ULONG actual = 0;
    if (GetQueuedCompletionStatusEx(completionPort, &entry, 1, &actual, timeout, TRUE) == TRUE) {
      if (entry.lpOverlapped == reinterpret_cast<LPOVERLAPPED>(remoteSpawnOverlapped)) {
        EnterCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection));
        assert(remoteNotificationSent);
        assert(!remoteSpawningProcedures.empty());
        do {
          spawn(std::move(remoteSpawningProcedures.front()));
          remoteSpawningProcedures.pop();
        } while (!remoteSpawningProcedures.empty());

        remoteNotificationSent = false;
        LeaveCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection));
        continue;
      }

      context = reinterpret_cast<DispatcherContext*>(entry.lpOverlapped)->context;
      break;
    }

    DWORD lastError = GetLastError();
    if (lastError == WAIT_TIMEOUT) {
      continue;
    }

    if (lastError != WAIT_IO_COMPLETION) {
      throw std::runtime_error("Dispatcher::dispatch, GetQueuedCompletionStatusEx failed, " + errorMessage(lastError));
    }
  }

  if (context != currentContext) {
    currentContext = context;
    SwitchToFiber(context->fiber);
  }
}
Exemplo n.º 7
0
NET_API int
net_wait(struct net_service* service, int timeout)
{
    int ret;
    int err;
    struct iocp_data* ov_data;
    PULONG_PTR data;
    DWORD bytes;
    int cnt;

#if _WIN32_WINNT >= 0x0600
    ULONG ulCount;
    ULONG ulNR;
    ULONG i;
    OVERLAPPED_ENTRY entries[32];

    cnt = 0;

    ulCount = sizeof(entries) / sizeof(OVERLAPPED_ENTRY);
    ulNR = 0;

    ov_data = 0;
    data = 0;
    bytes = 0;
    err = 0;
    while(1)
    {
        ret = GetQueuedCompletionStatusEx(service->net_service_fd, entries, ulCount, &ulNR, timeout, 0);
        err = net_get_error();
        if (err == WAIT_TIMEOUT)
        {
            err = 0;
        }
        if (!ret)
        {
            if (err)
            {
                return -err;
            }
            return cnt;
        }

        for (i = 0; i < ulNR; ++i)
        {
            ov_data = (struct iocp_data*)entries[i].lpOverlapped;
            bytes = entries[i].dwNumberOfBytesTransferred;
            if (ov_data)
            {
                switch(ov_data->op_type)
                {
                case OP_NET_ACCEPT:
                    handle_accept(service, ret, err, (struct accept_session*)ov_data);
                    break;
                case OP_NET_READ:
                    handle_read(service, ret, err, (struct read_session*)ov_data, bytes);
                    break;
                case OP_NET_WRITE:
                    handle_write(service, ret, err, (struct write_session*)ov_data, bytes);
                    break;
                case OP_NET_CONNECT:
                    handle_connect(service, ret, err, (struct connect_session *)ov_data, bytes);
                    break;
                }
            }
        }
        cnt += (int)ulNR;
    }
    return cnt;

#else
    cnt = 0;

    while(1)
    {
        ret = GetQueuedCompletionStatus(service->net_service_fd, &bytes, (PULONG_PTR) &data, (LPOVERLAPPED*)&ov_data, timeout);
        err = 0;
        if (!ret)
        {
            err = net_get_error();
        }

        if (err == WAIT_TIMEOUT)
        {
            err = 0;
        }
        if(!ov_data)
        {
            if(err)
            {
                return -err;
            }
            return cnt;
        }
        else
        {
            switch(ov_data->op_type)
            {
            case OP_NET_ACCEPT:
                handle_accept(service, ret, err, (struct accept_session*)ov_data);
                break;
            case OP_NET_READ:
                handle_read(service, ret, err, (struct read_session*)ov_data, bytes);
                break;
            case OP_NET_WRITE:
                handle_write(service, ret, err, (struct write_session*)ov_data, bytes);
                break;
            case OP_NET_CONNECT:
                handle_connect(service, ret, err, (struct connect_session *)ov_data, bytes);
                break;
            }
        }
        cnt += 1;
    }
    return cnt;
#endif
}