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 implementation of the PlatformManager object. 22 : */ 23 : 24 : #pragma once 25 : 26 : #include <condition_variable> 27 : #include <mutex> 28 : 29 : #include <platform/PlatformManager.h> 30 : #include <platform/internal/GenericPlatformManagerImpl_POSIX.h> 31 : 32 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 33 : #include <gio/gio.h> 34 : #endif 35 : 36 : namespace chip { 37 : namespace DeviceLayer { 38 : 39 : /** 40 : * Concrete implementation of the PlatformManager singleton object for Linux platforms. 41 : */ 42 : class PlatformManagerImpl final : public PlatformManager, public Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl> 43 : { 44 : // Allow the PlatformManager interface class to delegate method calls to 45 : // the implementation methods provided by this class. 46 : friend PlatformManager; 47 : 48 : // Allow the generic implementation base class to call helper methods on 49 : // this class. 50 : #ifndef DOXYGEN_SHOULD_SKIP_THIS 51 : friend Internal::GenericPlatformManagerImpl_POSIX<PlatformManagerImpl>; 52 : #endif 53 : 54 : public: 55 : // ===== Platform-specific members that may be accessed directly by the application. 56 : 57 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 58 : 59 : /** 60 : * @brief Invoke a function on the Matter GLib context. 61 : * 62 : * If execution of the function will have to be scheduled on other thread, 63 : * this call will block the current thread until the function is executed. 64 : * 65 : * @param[in] function The function to call. 66 : * @param[in] userData User data to pass to the function. 67 : * @returns The result of the function. 68 : */ 69 : template <typename T> 70 : CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData) 71 : { 72 : return _GLibMatterContextInvokeSync((CHIP_ERROR(*)(void *)) func, (void *) userData); 73 : } 74 : 75 : unsigned int GLibMatterContextAttachSource(GSource * source) 76 : { 77 : VerifyOrDie(mGLibMainLoop != nullptr); 78 : return g_source_attach(source, g_main_loop_get_context(mGLibMainLoop)); 79 : } 80 : 81 : #endif 82 : 83 : System::Clock::Timestamp GetStartTime() { return mStartTime; } 84 : 85 : private: 86 : // ===== Methods that implement the PlatformManager abstract interface. 87 : 88 : CHIP_ERROR _InitChipStack(); 89 : void _Shutdown(); 90 : 91 : // ===== Members for internal use by the following friends. 92 : 93 : friend PlatformManager & PlatformMgr(); 94 : friend PlatformManagerImpl & PlatformMgrImpl(); 95 : friend class Internal::BLEManagerImpl; 96 : 97 : System::Clock::Timestamp mStartTime = System::Clock::kZero; 98 : 99 : static PlatformManagerImpl sInstance; 100 : 101 : #if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 102 : 103 : struct GLibMatterContextInvokeData 104 : { 105 : CHIP_ERROR (*mFunc)(void *); 106 : void * mFuncUserData; 107 : CHIP_ERROR mFuncResult; 108 : // Sync primitives to wait for the function to be executed 109 : std::condition_variable mDoneCond; 110 : bool mDone = false; 111 : }; 112 : 113 : /** 114 : * @brief Invoke a function on the Matter GLib context. 115 : * 116 : * @note This function does not provide type safety for the user data. Please, 117 : * use the GLibMatterContextInvokeSync() template function instead. 118 : */ 119 : CHIP_ERROR _GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData); 120 : 121 : // XXX: Mutex for guarding access to glib main event loop callback indirection 122 : // synchronization primitives. This is a workaround to suppress TSAN warnings. 123 : // TSAN does not know that from the thread synchronization perspective the 124 : // g_source_attach() function should be treated as pthread_create(). Memory 125 : // access to shared data before the call to g_source_attach() without mutex 126 : // is not a race condition - the callback will not be executed on glib main 127 : // event loop thread before the call to g_source_attach(). 128 : std::mutex mGLibMainLoopCallbackIndirectionMutex; 129 : 130 : GMainLoop * mGLibMainLoop = nullptr; 131 : GThread * mGLibMainLoopThread = nullptr; 132 : 133 : #endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 134 : }; 135 : 136 : /** 137 : * Returns the public interface of the PlatformManager singleton object. 138 : * 139 : * chip applications should use this to access features of the PlatformManager object 140 : * that are common to all platforms. 141 : */ 142 6691775 : inline PlatformManager & PlatformMgr() 143 : { 144 6691775 : return PlatformManagerImpl::sInstance; 145 : } 146 : 147 : /** 148 : * Returns the platform-specific implementation of the PlatformManager singleton object. 149 : * 150 : * chip applications can use this to gain access to features of the PlatformManager 151 : * that are specific to the platform. 152 : */ 153 : inline PlatformManagerImpl & PlatformMgrImpl() 154 : { 155 : return PlatformManagerImpl::sInstance; 156 : } 157 : 158 : } // namespace DeviceLayer 159 : } // namespace chip