Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2020-2021 Project CHIP Authors
4 : * Copyright (c) 2018 Nest Labs, Inc.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : /**
20 : * @file
21 : * Provides an generic implementation of PlatformManager features
22 : * for use on Linux platforms.
23 : */
24 :
25 : #pragma once
26 :
27 : #include <platform/DeviceSafeQueue.h>
28 : #include <platform/internal/GenericPlatformManagerImpl.h>
29 :
30 : #include <fcntl.h>
31 : #include <sched.h>
32 : #include <sys/time.h>
33 : #include <unistd.h>
34 :
35 : #include <atomic>
36 : #include <pthread.h>
37 : #include <queue>
38 :
39 : namespace chip {
40 : namespace DeviceLayer {
41 : namespace Internal {
42 :
43 : /**
44 : * Provides a generic implementation of PlatformManager features that works on any OSAL platform.
45 : *
46 : * This template contains implementations of select features from the PlatformManager abstract
47 : * interface that are suitable for use on OSAL-based platforms. It is intended to be inherited
48 : * (directly or indirectly) by the PlatformManagerImpl class, which also appears as the template's
49 : * ImplClass parameter.
50 : */
51 : template <class ImplClass>
52 : class GenericPlatformManagerImpl_POSIX : public GenericPlatformManagerImpl<ImplClass>
53 : {
54 : protected:
55 : // OS-specific members (pthread)
56 : pthread_mutex_t mChipStackLock = PTHREAD_MUTEX_INITIALIZER;
57 :
58 : enum class State
59 : {
60 : kStopped = 0,
61 : kRunning = 1,
62 : kStopping = 2,
63 : };
64 :
65 : pthread_t mChipTask;
66 : bool mInternallyManagedChipTask = false;
67 : std::atomic<State> mState{ State::kStopped };
68 :
69 : #if !CHIP_SYSTEM_CONFIG_USE_LIBEV
70 : pthread_cond_t mEventQueueStoppedCond;
71 : pthread_mutex_t mStateLock;
72 :
73 : pthread_attr_t mChipTaskAttr;
74 : struct sched_param mChipTaskSchedParam;
75 : #endif
76 :
77 : #if CHIP_STACK_LOCK_TRACKING_ENABLED
78 : bool mChipStackIsLocked = false;
79 : pthread_t mChipStackLockOwnerThread;
80 : #endif
81 :
82 : // ===== Methods that implement the PlatformManager abstract interface.
83 :
84 : CHIP_ERROR
85 : _InitChipStack();
86 : void _LockChipStack();
87 : bool _TryLockChipStack();
88 : void _UnlockChipStack();
89 : CHIP_ERROR _PostEvent(const ChipDeviceEvent * event);
90 : void _RunEventLoop();
91 : CHIP_ERROR _StartEventLoopTask();
92 : CHIP_ERROR _StopEventLoopTask();
93 : CHIP_ERROR _StartChipTimer(System::Clock::Timeout duration);
94 : void _Shutdown();
95 :
96 : #if CHIP_STACK_LOCK_TRACKING_ENABLED
97 : bool _IsChipStackLockedByCurrentThread() const;
98 : #endif
99 :
100 : // ===== Methods available to the implementation subclass.
101 :
102 : private:
103 : // ===== Private members for use by this class only.
104 :
105 458 : inline ImplClass * Impl() { return static_cast<ImplClass *>(this); }
106 :
107 : #if CHIP_SYSTEM_CONFIG_USE_LIBEV
108 : static void _DispatchEventViaScheduleWork(System::Layer * aLayer, void * appState);
109 : #else
110 :
111 : DeviceSafeQueue mChipEventQueue;
112 : std::atomic<bool> mShouldRunEventLoop{ true };
113 : static void * EventLoopTaskMain(void * arg);
114 : #endif
115 : void ProcessDeviceEvents();
116 : };
117 :
118 : // Instruct the compiler to instantiate the template only when explicitly told to do so.
119 : extern template class GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>;
120 :
121 : #if CHIP_SYSTEM_CONFIG_USE_LIBEV
122 : // with external libev mainloop, this should be implemented externally to terminate the mainloop cleanly
123 : // (Note that there is a weak default implementation that just calls chipDie() when the external implementation is missing)
124 : extern void ExitExternalMainLoop();
125 : #endif
126 : } // namespace Internal
127 : } // namespace DeviceLayer
128 : } // namespace chip
|