Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / ot-br-posix / repo / src / common / task_runner.cpp
1 /*
2  *    Copyright (c) 2021, The OpenThread Authors.
3  *    All rights reserved.
4  *
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.
15  *
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.
27  */
28
29 /**
30  * @file
31  * This file implements the Task Runner that executes tasks on the mainloop.
32  */
33
34 #include "common/task_runner.hpp"
35
36 #include <algorithm>
37
38 #include <fcntl.h>
39 #include <unistd.h>
40
41 #include "common/code_utils.hpp"
42
43 namespace otbr {
44
45 TaskRunner::TaskRunner(void)
46 {
47     int flags;
48
49     // We do not handle failures when creating a pipe, simply die.
50     VerifyOrDie(pipe(mEventFd) != -1, strerror(errno));
51
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));
56 }
57
58 TaskRunner::~TaskRunner(void)
59 {
60     if (mEventFd[kRead] != -1)
61     {
62         close(mEventFd[kRead]);
63         mEventFd[kRead] = -1;
64     }
65     if (mEventFd[kWrite] != -1)
66     {
67         close(mEventFd[kWrite]);
68         mEventFd[kWrite] = -1;
69     }
70 }
71
72 void TaskRunner::Post(const Task<void> &aTask)
73 {
74     PushTask(aTask);
75 }
76
77 void TaskRunner::UpdateFdSet(otSysMainloopContext &aMainloop)
78 {
79     FD_SET(mEventFd[kRead], &aMainloop.mReadFdSet);
80     aMainloop.mMaxFd = std::max(mEventFd[kRead], aMainloop.mMaxFd);
81 }
82
83 void TaskRunner::Process(const otSysMainloopContext &aMainloop)
84 {
85     if (FD_ISSET(mEventFd[kRead], &aMainloop.mReadFdSet))
86     {
87         uint8_t n;
88
89         // Read any data in the pipe.
90         while (read(mEventFd[kRead], &n, sizeof(n)) == sizeof(n))
91         {
92         }
93
94         PopTasks();
95     }
96 }
97
98 void TaskRunner::PushTask(const Task<void> &aTask)
99 {
100     ssize_t                     rval;
101     const uint8_t               kOne = 1;
102     std::lock_guard<std::mutex> _(mTaskQueueMutex);
103
104     mTaskQueue.emplace(aTask);
105     do
106     {
107         rval = write(mEventFd[kWrite], &kOne, sizeof(kOne));
108     } while (rval == -1 && errno == EINTR);
109
110     VerifyOrExit(rval == -1);
111
112     // Critical error happens, simply die.
113     VerifyOrDie(errno == EAGAIN || errno == EWOULDBLOCK, strerror(errno));
114
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));
118
119 exit:
120     return;
121 }
122
123 void TaskRunner::PopTasks(void)
124 {
125     while (true)
126     {
127         Task<void> task;
128
129         // The braces here are necessary for auto-releasing of the mutex.
130         {
131             std::lock_guard<std::mutex> _(mTaskQueueMutex);
132
133             if (!mTaskQueue.empty())
134             {
135                 task = std::move(mTaskQueue.front());
136                 mTaskQueue.pop();
137             }
138             else
139             {
140                 break;
141             }
142         }
143
144         task();
145     }
146 }
147
148 } // namespace otbr