Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / include / platform / internal / GenericPlatformManagerImpl_Zephyr.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *
5  *    Licensed under the Apache License, Version 2.0 (the "License");
6  *    you may not use this file except in compliance with the License.
7  *    You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *    Unless required by applicable law or agreed to in writing, software
12  *    distributed under the License is distributed on an "AS IS" BASIS,
13  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *    See the License for the specific language governing permissions and
15  *    limitations under the License.
16  */
17
18 /**
19  *    @file
20  *          Contains non-inline method definitions for the
21  *          GenericPlatformManagerImpl_Zephyr<> template.
22  */
23
24 #ifndef GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP
25 #define GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP
26
27 #include <platform/PlatformManager.h>
28 #include <platform/internal/CHIPDeviceLayerInternal.h>
29 #include <platform/internal/GenericPlatformManagerImpl_Zephyr.h>
30
31 // Include the non-inline definitions for the GenericPlatformManagerImpl<> template,
32 // from which the GenericPlatformManagerImpl_Zephyr<> template inherits.
33 #include <platform/internal/GenericPlatformManagerImpl.cpp>
34
35 #include <system/SystemLayer.h>
36
37 #define DEFAULT_MIN_SLEEP_PERIOD (60 * 60 * 24 * 30) // Month [sec]
38
39 namespace chip {
40 namespace DeviceLayer {
41 namespace Internal {
42
43 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
44 template class GenericPlatformManagerImpl_Zephyr<PlatformManagerImpl>;
45
46 template <class ImplClass>
47 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_InitChipStack(void)
48 {
49     CHIP_ERROR err = CHIP_NO_ERROR;
50
51     k_mutex_init(&mChipStackLock);
52
53     k_msgq_init(&mChipEventQueue, reinterpret_cast<char *>(&mChipEventRingBuffer), sizeof(ChipDeviceEvent),
54                 CHIP_DEVICE_CONFIG_MAX_EVENT_QUEUE_SIZE);
55
56     // Call up to the base class _InitChipStack() to perform the bulk of the initialization.
57     err = GenericPlatformManagerImpl<ImplClass>::_InitChipStack();
58     SuccessOrExit(err);
59
60 exit:
61     return err;
62 }
63
64 template <class ImplClass>
65 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_LockChipStack(void)
66 {
67     k_mutex_lock(&mChipStackLock, K_FOREVER);
68 }
69
70 template <class ImplClass>
71 bool GenericPlatformManagerImpl_Zephyr<ImplClass>::_TryLockChipStack(void)
72 {
73     return k_mutex_lock(&mChipStackLock, K_NO_WAIT) == 0;
74 }
75
76 template <class ImplClass>
77 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_UnlockChipStack(void)
78 {
79     k_mutex_unlock(&mChipStackLock);
80 }
81
82 template <class ImplClass>
83 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_StartChipTimer(uint32_t aMilliseconds)
84 {
85     // Let SystemLayer.PrepareSelect() handle timers.
86     return CHIP_NO_ERROR;
87 }
88
89 template <class ImplClass>
90 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_Shutdown(void)
91 {
92     return CHIP_ERROR_NOT_IMPLEMENTED;
93 }
94
95 template <class ImplClass>
96 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_PostEvent(const ChipDeviceEvent * event)
97 {
98     // For some reasons mentioned in https://github.com/zephyrproject-rtos/zephyr/issues/22301
99     // k_msgq_put takes `void*` instead of `const void*`. Nonetheless, it should be safe to
100     // const_cast here and there are components in Zephyr itself which do the same.
101     if (k_msgq_put(&mChipEventQueue, const_cast<ChipDeviceEvent *>(event), K_NO_WAIT) == 0)
102         SystemLayer.WakeSelect(); // Trigger wake select on CHIP thread
103     else
104         ChipLogError(DeviceLayer, "Failed to post event to CHIP Platform event queue");
105 }
106
107 template <class ImplClass>
108 void GenericPlatformManagerImpl_Zephyr<ImplClass>::ProcessDeviceEvents()
109 {
110     ChipDeviceEvent event;
111
112     while (k_msgq_get(&mChipEventQueue, &event, K_NO_WAIT) == 0)
113         Impl()->DispatchEvent(&event);
114 }
115
116 template <class ImplClass>
117 void GenericPlatformManagerImpl_Zephyr<ImplClass>::SysUpdate()
118 {
119     FD_ZERO(&mReadSet);
120     FD_ZERO(&mWriteSet);
121     FD_ZERO(&mErrorSet);
122     mMaxFd = 0;
123
124     // Max out this duration and let CHIP set it appropriately.
125     mNextTimeout.tv_sec  = DEFAULT_MIN_SLEEP_PERIOD;
126     mNextTimeout.tv_usec = 0;
127
128     if (SystemLayer.State() == System::kLayerState_Initialized)
129     {
130         SystemLayer.PrepareSelect(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet, mNextTimeout);
131     }
132
133     if (InetLayer.State == InetLayer::kState_Initialized)
134     {
135         InetLayer.PrepareSelect(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet, mNextTimeout);
136     }
137 }
138
139 template <class ImplClass>
140 void GenericPlatformManagerImpl_Zephyr<ImplClass>::SysProcess()
141 {
142     Impl()->UnlockChipStack();
143     int selectRes = select(mMaxFd + 1, &mReadSet, &mWriteSet, &mErrorSet, &mNextTimeout);
144     Impl()->LockChipStack();
145
146     if (selectRes < 0)
147     {
148         ChipLogError(DeviceLayer, "select failed: %s\n", ErrorStr(System::MapErrorPOSIX(errno)));
149         return;
150     }
151
152     if (SystemLayer.State() == System::kLayerState_Initialized)
153     {
154         SystemLayer.HandleSelectResult(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet);
155     }
156
157     if (InetLayer.State == InetLayer::kState_Initialized)
158     {
159         InetLayer.HandleSelectResult(mMaxFd, &mReadSet, &mWriteSet, &mErrorSet);
160     }
161
162     ProcessDeviceEvents();
163 }
164
165 template <class ImplClass>
166 void GenericPlatformManagerImpl_Zephyr<ImplClass>::_RunEventLoop(void)
167 {
168     Impl()->LockChipStack();
169
170     while (true)
171     {
172         SysUpdate();
173         SysProcess();
174     }
175
176     Impl()->UnlockChipStack();
177 }
178
179 template <class ImplClass>
180 void GenericPlatformManagerImpl_Zephyr<ImplClass>::EventLoopTaskMain(void * thisPtr, void *, void *)
181 {
182     ChipLogDetail(DeviceLayer, "CHIP task running");
183     static_cast<GenericPlatformManagerImpl_Zephyr<ImplClass> *>(thisPtr)->Impl()->RunEventLoop();
184 }
185
186 template <class ImplClass>
187 CHIP_ERROR GenericPlatformManagerImpl_Zephyr<ImplClass>::_StartEventLoopTask(void)
188 {
189     const auto tid = k_thread_create(&mChipThread, mChipThreadStack, K_THREAD_STACK_SIZEOF(mChipThreadStack), EventLoopTaskMain,
190                                      this, nullptr, nullptr, CHIP_DEVICE_CONFIG_CHIP_TASK_PRIORITY, 0, K_NO_WAIT);
191
192 #ifdef CONFIG_THREAD_NAME
193     k_thread_name_set(tid, CHIP_DEVICE_CONFIG_CHIP_TASK_NAME);
194 #else
195     IgnoreUnusedVariable(tid);
196 #endif
197
198     return CHIP_NO_ERROR;
199 }
200
201 } // namespace Internal
202 } // namespace DeviceLayer
203 } // namespace chip
204
205 #endif // GENERIC_PLATFORM_MANAGER_IMPL_ZEPHYR_CPP