2 * Copyright (c) 2021, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
31 * This file implements the Task Runner that executes tasks on the mainloop.
34 #include "common/task_runner.hpp"
41 #include "common/code_utils.hpp"
45 TaskRunner::TaskRunner(void)
49 // We do not handle failures when creating a pipe, simply die.
50 VerifyOrDie(pipe(mEventFd) != -1, strerror(errno));
52 flags = fcntl(mEventFd[kRead], F_GETFL, 0);
53 VerifyOrDie(fcntl(mEventFd[kRead], F_SETFL, flags | O_NONBLOCK) != -1, strerror(errno));
54 flags = fcntl(mEventFd[kWrite], F_GETFL, 0);
55 VerifyOrDie(fcntl(mEventFd[kWrite], F_SETFL, flags | O_NONBLOCK) != -1, strerror(errno));
58 TaskRunner::~TaskRunner(void)
60 if (mEventFd[kRead] != -1)
62 close(mEventFd[kRead]);
65 if (mEventFd[kWrite] != -1)
67 close(mEventFd[kWrite]);
68 mEventFd[kWrite] = -1;
72 void TaskRunner::Post(const Task<void> &aTask)
77 void TaskRunner::UpdateFdSet(otSysMainloopContext &aMainloop)
79 FD_SET(mEventFd[kRead], &aMainloop.mReadFdSet);
80 aMainloop.mMaxFd = std::max(mEventFd[kRead], aMainloop.mMaxFd);
83 void TaskRunner::Process(const otSysMainloopContext &aMainloop)
85 if (FD_ISSET(mEventFd[kRead], &aMainloop.mReadFdSet))
89 // Read any data in the pipe.
90 while (read(mEventFd[kRead], &n, sizeof(n)) == sizeof(n))
98 void TaskRunner::PushTask(const Task<void> &aTask)
101 const uint8_t kOne = 1;
102 std::lock_guard<std::mutex> _(mTaskQueueMutex);
104 mTaskQueue.emplace(aTask);
107 rval = write(mEventFd[kWrite], &kOne, sizeof(kOne));
108 } while (rval == -1 && errno == EINTR);
110 VerifyOrExit(rval == -1);
112 // Critical error happens, simply die.
113 VerifyOrDie(errno == EAGAIN || errno == EWOULDBLOCK, strerror(errno));
115 // We are blocked because there are already data (written by other concurrent callers in
116 // different threads) in the pipe, and the mEventFd[kRead] should be readable now.
117 otbrLog(OTBR_LOG_WARNING, "failed to write fd %d: %s", mEventFd[kWrite], strerror(errno));
123 void TaskRunner::PopTasks(void)
129 // The braces here are necessary for auto-releasing of the mutex.
131 std::lock_guard<std::mutex> _(mTaskQueueMutex);
133 if (!mTaskQueue.empty())
135 task = std::move(mTaskQueue.front());