2 * Copyright (c) 2021 Project CHIP Authors
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
23 #include <support/CodeUtils.h>
24 #include <support/logging/CHIPLogging.h>
27 namespace DeviceLayer {
37 if (sem_init(&mSemaphore, 0 /* shared */, 0 /*value*/) != 0)
39 ChipLogError(DeviceLayer, "Failed to initialize semaphore.");
45 if (sem_destroy(&mSemaphore) != 0)
47 ChipLogError(DeviceLayer, "Failed to destroy semaphore.");
51 void Post() { sem_post(&mSemaphore); }
53 void Wait() { sem_wait(&mSemaphore); }
59 int PostSemaphore(Semaphore * semaphore)
65 class CallbackIndirection
68 CallbackIndirection(GSourceFunc f, void * a) : mCallback(f), mArgument(a) {}
70 void Wait() { mDoneSemaphore.Wait(); }
72 static int Callback(CallbackIndirection * self)
74 int result = self->mCallback(self->mArgument);
75 self->mDoneSemaphore.Post();
80 Semaphore mDoneSemaphore;
81 GSourceFunc mCallback;
87 MainLoop & MainLoop::Instance()
89 static MainLoop sMainLoop;
93 void * MainLoop::Thread(void * self)
95 MainLoop * loop = reinterpret_cast<MainLoop *>(self);
97 ChipLogDetail(DeviceLayer, "TRACE: Bluez mainloop starting %s", __func__);
98 g_main_loop_run(loop->mBluezMainLoop);
99 ChipLogDetail(DeviceLayer, "TRACE: Bluez mainloop stopping %s", __func__);
101 if (loop->mCleanup != nullptr)
103 ChipLogDetail(DeviceLayer, "TRACE: Executing cleanup %s", __func__);
104 loop->mCleanup(loop->mCleanupArgument);
110 CHIP_ERROR MainLoop::EnsureStarted()
112 if (mBluezMainLoop != nullptr)
114 return CHIP_NO_ERROR;
117 mBluezMainLoop = g_main_loop_new(nullptr, TRUE);
118 if (mBluezMainLoop == nullptr)
120 ChipLogError(DeviceLayer, "FAIL: memory alloc in %s", __func__);
121 return CHIP_ERROR_NO_MEMORY;
124 int pthreadErr = pthread_create(&mThread, nullptr, &MainLoop::Thread, reinterpret_cast<void *>(this));
125 int tmpErrno = errno;
128 ChipLogError(DeviceLayer, "FAIL: pthread_create (%s) in %s", strerror(tmpErrno), __func__);
129 g_free(mBluezMainLoop);
130 mBluezMainLoop = nullptr;
131 return CHIP_ERROR_INTERNAL;
136 GMainContext * context = g_main_loop_get_context(mBluezMainLoop);
137 VerifyOrDie(context != nullptr);
139 g_main_context_invoke(context, GSourceFunc(PostSemaphore), &semaphore);
143 return CHIP_NO_ERROR;
146 bool MainLoop::RunOnBluezThread(GSourceFunc callback, void * argument)
148 GMainContext * context = nullptr;
149 const char * msg = nullptr;
151 VerifyOrExit(mBluezMainLoop != nullptr, msg = "FAIL: NULL sBluezMainLoop");
152 VerifyOrExit(g_main_loop_is_running(mBluezMainLoop), msg = "FAIL: sBluezMainLoop not running");
154 context = g_main_loop_get_context(mBluezMainLoop);
155 VerifyOrExit(context != nullptr, msg = "FAIL: NULL main context");
156 g_main_context_invoke(context, callback, argument);
161 ChipLogDetail(DeviceLayer, "%s in %s", msg, __func__);
164 return msg == nullptr;
167 bool MainLoop::RunOnBluezThreadAndWait(GSourceFunc closure, void * argument)
169 CallbackIndirection indirection(closure, argument);
171 if (!Schedule(&CallbackIndirection::Callback, &indirection))
181 } // namespace Internal
182 } // namespace DeviceLayer
185 #endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE