Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / platform / FreeRTOS / GenericThreadStackManagerImpl_FreeRTOS.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2019 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *          Contains non-inline method definitions for the
23  *          GenericThreadStackManagerImpl_FreeRTOS<> template.
24  */
25
26 #ifndef GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP
27 #define GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP
28
29 #include <platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.h>
30 #include <platform/OpenThread/OpenThreadUtils.h>
31 #include <platform/ThreadStackManager.h>
32 #include <platform/internal/CHIPDeviceLayerInternal.h>
33 #include <support/CodeUtils.h>
34 #include <support/logging/CHIPLogging.h>
35
36 namespace chip {
37 namespace DeviceLayer {
38 namespace Internal {
39
40 // Fully instantiate the generic implementation class in whatever compilation unit includes this file.
41 template class GenericThreadStackManagerImpl_FreeRTOS<ThreadStackManagerImpl>;
42
43 template <class ImplClass>
44 CHIP_ERROR GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::DoInit(void)
45 {
46     CHIP_ERROR err   = CHIP_NO_ERROR;
47     mThreadStackLock = xSemaphoreCreateMutex();
48
49     if (mThreadStackLock == NULL)
50     {
51         ChipLogError(DeviceLayer, "Failed to create Thread stack lock");
52         ExitNow(err = CHIP_ERROR_NO_MEMORY);
53     }
54
55     mThreadTask = NULL;
56
57 exit:
58     return err;
59 }
60
61 template <class ImplClass>
62 CHIP_ERROR GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_StartThreadTask(void)
63 {
64     if (mThreadTask != NULL)
65     {
66         return CHIP_ERROR_INCORRECT_STATE;
67     }
68 #if defined(CHIP_CONFIG_FREERTOS_USE_STATIC_TASK) && CHIP_CONFIG_FREERTOS_USE_STATIC_TASK
69     mThreadTask = xTaskCreateStatic(ThreadTaskMain, CHIP_DEVICE_CONFIG_THREAD_TASK_NAME, ArraySize(mThreadStack), this,
70                                     CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY, mThreadStack, &mThreadTaskStruct);
71
72 #else
73     xTaskCreate(ThreadTaskMain, CHIP_DEVICE_CONFIG_THREAD_TASK_NAME,
74                 CHIP_DEVICE_CONFIG_THREAD_TASK_STACK_SIZE / sizeof(StackType_t), this, CHIP_DEVICE_CONFIG_THREAD_TASK_PRIORITY,
75                 &mThreadTask);
76 #endif
77
78     if (mThreadTask == NULL)
79     {
80         return CHIP_ERROR_NO_MEMORY;
81     }
82     return CHIP_NO_ERROR;
83 }
84
85 template <class ImplClass>
86 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_LockThreadStack(void)
87 {
88     xSemaphoreTake(mThreadStackLock, portMAX_DELAY);
89 }
90
91 template <class ImplClass>
92 bool GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_TryLockThreadStack(void)
93 {
94     return xSemaphoreTake(mThreadStackLock, 0) == pdTRUE;
95 }
96
97 template <class ImplClass>
98 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::_UnlockThreadStack(void)
99 {
100     xSemaphoreGive(mThreadStackLock);
101 }
102
103 template <class ImplClass>
104 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::SignalThreadActivityPending()
105 {
106     if (mThreadTask != NULL)
107     {
108         xTaskNotifyGive(mThreadTask);
109     }
110 }
111
112 template <class ImplClass>
113 BaseType_t GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::SignalThreadActivityPendingFromISR()
114 {
115     BaseType_t yieldRequired = pdFALSE;
116
117     if (mThreadTask != NULL)
118     {
119         vTaskNotifyGiveFromISR(mThreadTask, &yieldRequired);
120     }
121
122     return yieldRequired;
123 }
124
125 template <class ImplClass>
126 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::OnJoinerTimer(TimerHandle_t xTimer)
127 {
128     GenericThreadStackManagerImpl_FreeRTOS<ImplClass> * self =
129         static_cast<GenericThreadStackManagerImpl_FreeRTOS<ImplClass> *>(pvTimerGetTimerID(xTimer));
130
131     ChipLogDetail(DeviceLayer, "Thread joiner timer running");
132
133     if (xTaskGetTickCount() > self->mJoinerExpire || self->Impl()->IsThreadProvisioned())
134     {
135         ChipLogDetail(DeviceLayer, "Thread joiner timer stopped");
136
137         VerifyOrDie(pdPASS == xTimerStop(xTimer, portMAX_DELAY) && pdPASS == xTimerDelete(xTimer, portMAX_DELAY));
138     }
139     else if (!self->mJoinerStartPending)
140     {
141         ChipLogDetail(DeviceLayer, "Request Thread joiner start");
142
143         self->mJoinerStartPending = true;
144         self->Impl()->SignalThreadActivityPending();
145     }
146 }
147
148 template <class ImplClass>
149 void GenericThreadStackManagerImpl_FreeRTOS<ImplClass>::ThreadTaskMain(void * arg)
150 {
151     GenericThreadStackManagerImpl_FreeRTOS<ImplClass> * self =
152         static_cast<GenericThreadStackManagerImpl_FreeRTOS<ImplClass> *>(arg);
153
154     ChipLogDetail(DeviceLayer, "Thread task running");
155
156     // Try starting joiner within 15m.
157     self->mJoinerExpire = xTaskGetTickCount() + pdMS_TO_TICKS(15 * 60 * 1000);
158
159     TimerHandle_t joinerTimer = xTimerCreate("JoinerTimer", pdMS_TO_TICKS(10000), pdTRUE, self, &OnJoinerTimer);
160     VerifyOrDie(joinerTimer != NULL);
161     VerifyOrDie(pdPASS == xTimerStart(joinerTimer, portMAX_DELAY));
162
163     while (true)
164     {
165         self->Impl()->LockThreadStack();
166         self->Impl()->ProcessThreadActivity();
167         self->Impl()->UnlockThreadStack();
168
169         ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
170
171         if (self->mJoinerStartPending)
172         {
173             self->mJoinerStartPending = false;
174             self->Impl()->JoinerStart();
175         }
176     }
177 }
178
179 } // namespace Internal
180 } // namespace DeviceLayer
181 } // namespace chip
182
183 #endif // GENERIC_THREAD_STACK_MANAGER_IMPL_FREERTOS_IPP