diff --git a/src/posix/main.c b/src/posix/main.c index dd027668d..6c26b2824 100644 --- a/src/posix/main.c +++ b/src/posix/main.c @@ -28,9 +28,13 @@ #include -#include +#include "openthread-core-config.h" +#include "platform-posix.h" + +#include #include #include +#include #include #ifdef __linux__ #include @@ -97,8 +101,28 @@ int main(int argc, char *argv[]) while (true) { + otSysMainloopContext mainloop; + otTaskletsProcess(instance); - otSysProcessDrivers(instance); + + FD_ZERO(&mainloop.mReadFdSet); + FD_ZERO(&mainloop.mWriteFdSet); + FD_ZERO(&mainloop.mErrorFdSet); + + mainloop.mMaxFd = -1; + mainloop.mTimeout.tv_sec = 10; + mainloop.mTimeout.tv_usec = 0; + + otSysMainloopUpdate(instance, &mainloop); + if (otSysMainloopPoll(&mainloop) >= 0) + { + otSysMainloopProcess(instance, &mainloop); + } + else if (errno != EINTR) + { + perror("select"); + exit(OT_EXIT_FAILURE); + } } otInstanceFinalize(instance); diff --git a/src/posix/platform/openthread-system.h b/src/posix/platform/openthread-system.h index 26dbc107c..9eb10d12a 100644 --- a/src/posix/platform/openthread-system.h +++ b/src/posix/platform/openthread-system.h @@ -72,16 +72,49 @@ void otSysInitNetif(otInstance *aInstance); */ void otSysDeinit(void); +/** + * This structure represents a context for a select() based mainloop. + * + */ +typedef struct otSysMainloopContext +{ + fd_set mReadFdSet; ///< The read file descriptors. + fd_set mWriteFdSet; ///< The write file descriptors. + fd_set mErrorFdSet; ///< The error file descriptors. + int mMaxFd; ///< The max file descriptor. + struct timeval mTimeout; ///< The timeout. +} otSysMainloopContext; + +/** + * This function updates the file descriptor sets with file descriptors used by OpenThread drivers. + * + * @param[in] aInstance The OpenThread instance structure. + * @param[inout] aMainloop A pointer to the mainloop context. + * + */ +void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop); + +/** + * This function polls OpenThread's mainloop. + * + * @param[inout] aMainloop A pointer to the mainloop context. + * + * @returns value returned from select(). + * + */ +int otSysMainloopPoll(otSysMainloopContext *aMainloop); + /** * This function performs all platform-specific processing for OpenThread's example applications. * * @note This function is not called by the OpenThread library. Instead, the system/RTOS should call this function * in the main loop when processing OpenThread's drivers is most appropriate. * - * @param[in] aInstance The OpenThread instance structure. + * @param[in] aInstance The OpenThread instance structure. + * @param[in] aMainloop A pointer to the mainloop context. * */ -void otSysProcessDrivers(otInstance *aInstance); +void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); /** * This function is called whenever platform drivers needs processing. diff --git a/src/posix/platform/platform-posix.h b/src/posix/platform/platform-posix.h index 81b63cf01..12c9f03e7 100644 --- a/src/posix/platform/platform-posix.h +++ b/src/posix/platform/platform-posix.h @@ -200,7 +200,7 @@ void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMax * @param[in] aWriteFdSet A pointer to the write file descriptors. * */ -void platformRadioProcess(otInstance *aInstance, fd_set *aReadFdSet, fd_set *aWriteFdSet); +void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet); /** * This function initializes the random number service used by OpenThread. diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index 989dc05ee..53974e1b6 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -1455,7 +1455,7 @@ void platformRadioUpdateFdSet(fd_set *aReadFdSet, fd_set *aWriteFdSet, int *aMax sRadioSpinel.UpdateFdSet(*aReadFdSet, *aWriteFdSet, *aMaxFd, *aTimeout); } -void platformRadioProcess(otInstance *aInstance, fd_set *aReadFdSet, fd_set *aWriteFdSet) +void platformRadioProcess(otInstance *aInstance, const fd_set *aReadFdSet, const fd_set *aWriteFdSet) { sRadioSpinel.Process(*aReadFdSet, *aWriteFdSet); OT_UNUSED_VARIABLE(aInstance); diff --git a/src/posix/platform/system.c b/src/posix/platform/system.c index 84bb47b7d..7faea1cef 100644 --- a/src/posix/platform/system.c +++ b/src/posix/platform/system.c @@ -35,7 +35,6 @@ #include "platform-posix.h" #include -#include #include #include #include @@ -49,6 +48,8 @@ #include #include +#include "openthread-system.h" + uint64_t gNodeId = 0; static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) @@ -213,53 +214,50 @@ static int trySelect(fd_set *aReadFdSet, fd_set *aWriteFdSet, fd_set *aErrorFdSe } #endif // OPENTHREAD_POSIX_VIRTUAL_TIME -void otSysProcessDrivers(otInstance *aInstance) +void otSysMainloopUpdate(otInstance *aInstance, otSysMainloopContext *aMainloop) { - fd_set readFdSet; - fd_set writeFdSet; - fd_set errorFdSet; - struct timeval timeout; - int maxFd = -1; - int rval; - - FD_ZERO(&readFdSet); - FD_ZERO(&writeFdSet); - FD_ZERO(&errorFdSet); - - platformAlarmUpdateTimeout(&timeout); - platformUartUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd); + platformAlarmUpdateTimeout(&aMainloop->mTimeout); + platformUartUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, + &aMainloop->mMaxFd); #if OPENTHREAD_ENABLE_PLATFORM_UDP - platformUdpUpdateFdSet(aInstance, &readFdSet, &maxFd); + platformUdpUpdateFdSet(aInstance, &aMainloop->mReadFdSet, &aMainloop->mMaxFd); #endif #if OPENTHREAD_ENABLE_PLATFORM_NETIF - platformNetifUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd); + platformNetifUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, + &aMainloop->mMaxFd); #endif #if OPENTHREAD_POSIX_VIRTUAL_TIME - otSimUpdateFdSet(&readFdSet, &writeFdSet, &errorFdSet, &maxFd, &timeout); + otSimUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, &aMainloop->mMaxFd, + &aMainloop->mTimeout); #else - platformRadioUpdateFdSet(&readFdSet, &writeFdSet, &maxFd, &timeout); + platformRadioUpdateFdSet(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mMaxFd, &aMainloop->mTimeout); #endif if (otTaskletsArePending(aInstance)) { - timeout.tv_sec = 0; - timeout.tv_usec = 0; + aMainloop->mTimeout.tv_sec = 0; + aMainloop->mTimeout.tv_usec = 0; } +} + +int otSysMainloopPoll(otSysMainloopContext *aMainloop) +{ + int rval; #if OPENTHREAD_POSIX_VIRTUAL_TIME - if (timerisset(&timeout)) + if (timerisset(&aMainloop->mTimeout)) { // Make sure there are no data ready in UART - rval = trySelect(&readFdSet, &writeFdSet, &errorFdSet, maxFd); + rval = trySelect(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, aMainloop->mMaxFd); if (rval == 0) { bool noWrite = true; // If there are write requests, the device is supposed to wake soon - for (int i = 0; i < maxFd + 1; ++i) + for (int i = 0; i < aMainloop->mMaxFd + 1; ++i) { - if (FD_ISSET(i, &writeFdSet)) + if (FD_ISSET(i, &aMainloop->mWriteFdSet)) { noWrite = false; break; @@ -268,38 +266,36 @@ void otSysProcessDrivers(otInstance *aInstance) if (noWrite) { - otSimSendSleepEvent(&timeout); + otSimSendSleepEvent(&aMainloop->mTimeout); } - rval = select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, NULL); - assert(rval > 0); + rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, + &aMainloop->mErrorFdSet, NULL); } } else #endif { - rval = select(maxFd + 1, &readFdSet, &writeFdSet, &errorFdSet, &timeout); + rval = select(aMainloop->mMaxFd + 1, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet, + &aMainloop->mTimeout); } - if ((rval < 0) && (errno != EINTR)) - { - perror("select"); - exit(OT_EXIT_FAILURE); - } - else if (rval >= 0) - { + return rval; +} + +void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop) +{ #if OPENTHREAD_POSIX_VIRTUAL_TIME - otSimProcess(aInstance, &readFdSet, &writeFdSet, &errorFdSet); + otSimProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet); #else - platformRadioProcess(aInstance, &readFdSet, &writeFdSet); + platformRadioProcess(aInstance, &aMainloop->mReadFdSet, &aMainloop->mWriteFdSet); #endif - platformUartProcess(&readFdSet, &writeFdSet, &errorFdSet); - platformAlarmProcess(aInstance); + platformUartProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet); + platformAlarmProcess(aInstance); #if OPENTHREAD_ENABLE_PLATFORM_NETIF - platformNetifProcess(&readFdSet, &writeFdSet, &errorFdSet); + platformNetifProcess(&aMainloop->mReadFdSet, &aMainloop->mWriteFdSet, &aMainloop->mErrorFdSet); #endif #if OPENTHREAD_ENABLE_PLATFORM_UDP - platformUdpProcess(aInstance, &readFdSet); + platformUdpProcess(aInstance, &aMainloop->mReadFdSet); #endif - } }