diff --git a/rts/IOManager.c b/rts/IOManager.c index 383b042a00f7051b17b75e491a5deee645ed08f2..69fcdc2d9c74c964d88176f28668b467075fd000 100644 --- a/rts/IOManager.c +++ b/rts/IOManager.c @@ -467,6 +467,59 @@ setIOManagerControlFd(uint32_t cap_no USED_IF_THREADS, int fd USED_IF_THREADS) { } #endif + +bool anyPendingTimeoutsOrIO(CapIOManager *iomgr USED_IF_NOT_THREADS) +{ + switch (iomgr_type) { +#if defined(IOMGR_ENABLED_SELECT) + case IO_MANAGER_SELECT: + return (iomgr->blocked_queue_hd != END_TSO_QUEUE) + || (iomgr->sleeping_queue != END_TSO_QUEUE); +#endif + +#if defined(IOMGR_ENABLED_WIN32_LEGACY) + case IO_MANAGER_WIN32_LEGACY: + return (iomgr->blocked_queue_hd != END_TSO_QUEUE); +#endif + + /* For the purpose of the scheduler, the threaded I/O managers never have + pending I/O or timers. Of course in reality they do, but they're + managed via other primitives that the scheduler can see into (threads, + MVars and foreign blocking calls). + */ +#if defined(IOMGR_ENABLED_MIO_POSIX) + case IO_MANAGER_MIO_POSIX: + return false; +#endif + +#if defined(IOMGR_ENABLED_MIO_WIN32) + case IO_MANAGER_MIO_WIN32: + return false; +#endif + +#if defined(IOMGR_ENABLED_WINIO) +#if defined(THREADED_RTS) + /* As above, the threaded variants never have pending I/O or timers */ + case IO_MANAGER_WINIO: + return false; +#else + case IO_MANAGER_WINIO: + return false; + /* FIXME: But what is this? The WinIO I/O manager *also* returns false + in the non-threaded case! This is *totally bogus*! In the + non-threaded RTS the scheduler expects to be able to poll for IO. + The fact that this gives a wrong and useless answer for WinIO is + probably the cause of the complication in the scheduler with having + to call awaitCompletedTimeoutsOrIO() in multiple places (on Windows, + non-threaded). + */ +#endif +#endif + default: + barf("anyPendingTimeoutsOrIO not implemented"); + } +} + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn" diff --git a/rts/IOManager.h b/rts/IOManager.h index 55d6239b5d458e0566d97a42299d7f3aeaecec50..62be167d6eaf00db69c0e07a10941b0724342549 100644 --- a/rts/IOManager.h +++ b/rts/IOManager.h @@ -301,7 +301,7 @@ void appendToIOBlockedQueue(Capability *cap, StgTSO *tso); * This is used by the scheduler as part of deadlock-detection, and the * "context switch as often as possible" test. */ -INLINE_HEADER bool anyPendingTimeoutsOrIO(CapIOManager *iomgr); +bool anyPendingTimeoutsOrIO(CapIOManager *iomgr); #if !defined(THREADED_RTS) @@ -332,40 +332,4 @@ void awaitEvent(Capability *cap, bool wait); #define USED_IF_THREADS_AND_NOT_MINGW32 STG_UNUSED #endif -/* ----------------------------------------------------------------------------- - * INLINE functions... private from here on down. - * - * Some of these hooks are performance sensitive so parts of them are - * implemented here so they can be inlined. - * ----------------------------------------------------------------------------- - */ - -INLINE_HEADER bool anyPendingTimeoutsOrIO(CapIOManager *iomgr USED_IF_NOT_THREADS) -{ -#if defined(THREADED_RTS) - /* For the purpose of the scheduler, the threaded I/O managers never have - pending I/O or timers. Of course in reality they do, but they're - managed via other primitives that the scheduler can see into (threads, - MVars and foreign blocking calls). - */ - return false; -#else -#if defined(mingw32_HOST_OS) - /* The MIO I/O manager uses the blocked_queue, while the WinIO does not. - Note: the latter fact makes this test useless for the WinIO I/O manager, - and is the probable cause of the complication in the scheduler with - having to call awaitEvent in multiple places. - - None of the Windows I/O managers use the sleeping_queue - */ - return (iomgr->blocked_queue_hd != END_TSO_QUEUE); -#else - /* The select() I/O manager uses the blocked_queue and the sleeping_queue. - */ - return (iomgr->blocked_queue_hd != END_TSO_QUEUE) - || (iomgr->sleeping_queue != END_TSO_QUEUE); -#endif -#endif -} - #include "EndPrivate.h"