/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "bt_lock.h" #include "system/passert.h" #include "portmacro.h" // NOTE: The s_bt_lock is the global Bluetooth lock that is used by the firmware // *and* by Bluetopia. It gets handed to Bluetopia using bt_lock_get() in // BTPSKRNL.c when Bluetopia is initialized. The firmware uses this lock to // protect Bluetooth-related state that is read and written from the Bluetooth // callback task (PebbleTask_BTCallback) and other tasks. If we created our // own mutex for this purpose, we would encounter dead-lock situations. // For example: // Task1: Bluetopia code -> grabs BT stack lock -> Pebble callback -> grabs pebble mutex // Task2: Pebble code -> grabs pebble mutex -> calls into Bluetopia -> tries to grab BT stack lock static PebbleRecursiveMutex *s_bt_lock; void bt_lock_init(void) { // Never free'd. PBL_ASSERTN(!s_bt_lock); s_bt_lock = mutex_create_recursive(); } PebbleRecursiveMutex *bt_lock_get(void) { return s_bt_lock; } void bt_lock(void) { register uint32_t LR __asm ("lr"); uint32_t myLR = LR; mutex_lock_recursive_with_timeout_and_lr(s_bt_lock, portMAX_DELAY, myLR); } void bt_unlock(void) { mutex_unlock_recursive(s_bt_lock); } void bt_lock_assert_held(bool is_held) { mutex_assert_recursive_held_by_curr_task(s_bt_lock, is_held); } bool bt_lock_is_held(void) { return mutex_is_owned_recursive(s_bt_lock); }