Skip to content

Commit 1089718

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Assert that the Matter stack lock is held while reading/writing attributes (#15152)
* Assert that the Matter stack lock is held while reading/writing attributes. Several changes here: 1) Add an assert that when attributes are being read/written the Matter stack lock is held, so the read/write does not race with interaction model messages touching the attribute store. 2) Implement the Matter stack lock assertion bits on FreeRTOS. 3) Add FreeRTOS to the set of configurations that actually enable Matter stack lock assertions. 4) For the configurations that enable the assertions, change the default behavior from "log" to "fatal", so we actually notice the * Remove stray debugging log. * Make p6 and qpg CI compile. * Also assert in MatterReportingAttributeChangeCallback.
1 parent c36657e commit 1089718

File tree

12 files changed

+71
-2
lines changed

12 files changed

+71
-2
lines changed

config/qpg/chip-gn/args.gni

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ qpg_cc = "arm-none-eabi-gcc"
3232
qpg_cxx = "arm-none-eabi-g++"
3333
chip_mdns = "platform"
3434

35+
# Disable lock tracking, since our FreeRTOS configuration does not set
36+
# INCLUDE_xSemaphoreGetMutexHolder
37+
chip_stack_lock_tracking = "none"
38+
3539
chip_project_config_include_dirs =
3640
[ "//examples/platform/qpg/project_include/" ]
3741
chip_project_config_include = "<CHIPProjectConfig.h>"

examples/all-clusters-app/p6/args.gni

+6
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ import("${chip_root}/src/platform/P6/args.gni")
1818

1919
p6_target_project =
2020
get_label_info(":all_clusters_app_sdk_sources", "label_no_toolchain")
21+
22+
declare_args() {
23+
# Disable lock tracking, since our FreeRTOS configuration does not set
24+
# INCLUDE_xSemaphoreGetMutexHolder
25+
chip_stack_lock_tracking = "none"
26+
}

examples/lighting-app/p6/args.gni

+6
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ import("${chip_root}/src/platform/P6/args.gni")
1818

1919
p6_target_project =
2020
get_label_info(":lighting_app_sdk_sources", "label_no_toolchain")
21+
22+
declare_args() {
23+
# Disable lock tracking, since our FreeRTOS configuration does not set
24+
# INCLUDE_xSemaphoreGetMutexHolder
25+
chip_stack_lock_tracking = "none"
26+
}

examples/lighting-app/qpg/args.gni

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ qpg_sdk_target = get_label_info(":sdk", "label_no_toolchain")
2020

2121
declare_args() {
2222
chip_enable_ota_requestor = true
23+
24+
# Disable lock tracking, since our FreeRTOS configuration does not set
25+
# INCLUDE_xSemaphoreGetMutexHolder
26+
chip_stack_lock_tracking = "none"
2327
}
2428

2529
pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"

examples/lock-app/p6/args.gni

+6
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@ import("${chip_root}/src/platform/P6/args.gni")
1818

1919
p6_target_project =
2020
get_label_info(":lock_app_sdk_sources", "label_no_toolchain")
21+
22+
declare_args() {
23+
# Disable lock tracking, since our FreeRTOS configuration does not set
24+
# INCLUDE_xSemaphoreGetMutexHolder
25+
chip_stack_lock_tracking = "none"
26+
}

examples/lock-app/qpg/args.gni

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ qpg_sdk_target = get_label_info(":sdk", "label_no_toolchain")
2020

2121
declare_args() {
2222
chip_enable_ota_requestor = true
23+
24+
# Disable lock tracking, since our FreeRTOS configuration does not set
25+
# INCLUDE_xSemaphoreGetMutexHolder
26+
chip_stack_lock_tracking = "none"
2327
}
2428

2529
pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"

examples/persistent-storage/qpg/args.gni

+6
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,9 @@ import("//build_overrides/chip.gni")
1717
import("${chip_root}/examples/platform/qpg/args.gni")
1818
qpg_sdk_target = get_label_info(":sdk", "label_no_toolchain")
1919
chip_enable_openthread = false
20+
21+
declare_args() {
22+
# Disable lock tracking, since our FreeRTOS configuration does not set
23+
# INCLUDE_xSemaphoreGetMutexHolder
24+
chip_stack_lock_tracking = "none"
25+
}

src/app/util/attribute-storage.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
#include <app/util/attribute-storage.h>
4848
#include <lib/support/CodeUtils.h>
4949
#include <lib/support/logging/CHIPLogging.h>
50+
#include <platform/LockTracker.h>
5051

5152
#include <app-common/zap-generated/attribute-type.h>
5253
#include <app-common/zap-generated/callback.h>
@@ -549,6 +550,8 @@ bool emAfMatchAttribute(const EmberAfCluster * cluster, const EmberAfAttributeMe
549550
EmberAfStatus emAfReadOrWriteAttribute(EmberAfAttributeSearchRecord * attRecord, const EmberAfAttributeMetadata ** metadata,
550551
uint8_t * buffer, uint16_t readLength, bool write)
551552
{
553+
assertChipStackLockedByCurrentThread();
554+
552555
uint16_t attributeOffsetIndex = 0;
553556

554557
for (uint8_t ep = 0; ep < emberAfEndpointCount(); ep++)

src/app/util/ember-compatibility-functions.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <lib/support/CodeUtils.h>
4343
#include <lib/support/SafeInt.h>
4444
#include <lib/support/TypeTraits.h>
45+
#include <platform/LockTracker.h>
4546
#include <protocols/interaction_model/Constants.h>
4647

4748
#include <app-common/zap-generated/att-storage.h>
@@ -1029,6 +1030,10 @@ void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clust
10291030

10301031
void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
10311032
{
1033+
// Attribute writes have asserted this already, but this assert should catch
1034+
// applications notifying about changes from their end.
1035+
assertChipStackLockedByCurrentThread();
1036+
10321037
ClusterInfo info;
10331038
info.mClusterId = clusterId;
10341039
info.mAttributeId = attributeId;

src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,27 @@ void GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_UnlockChipStack(void)
104104
xSemaphoreGive(mChipStackLock);
105105
}
106106

107+
#if CHIP_STACK_LOCK_TRACKING_ENABLED
108+
template <class ImplClass>
109+
bool GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_IsChipStackLockedByCurrentThread() const
110+
{
111+
// We can't check for INCLUDE_xTaskGetCurrentTaskHandle because it's often
112+
// _not_ set, but xTaskGetCurrentTaskHandle works anyway because
113+
// configUSE_MUTEXES is set. So in practice, xTaskGetCurrentTaskHandle can
114+
// be assumed to be available here.
115+
#if INCLUDE_xSemaphoreGetMutexHolder != 1
116+
#error Must either set INCLUDE_xSemaphoreGetMutexHolder = 1 in FreeRTOSConfig.h or set chip_stack_lock_tracking = "none" in Matter gn configuration.
117+
#endif
118+
// If we have not started our event loop yet, return true because in that
119+
// case we can't be racing against the (not yet started) event loop.
120+
//
121+
// Similarly, if mChipStackLock has not been created yet, might as well
122+
// return true.
123+
return (mEventLoopTask == nullptr) || (mChipStackLock == nullptr) ||
124+
(xSemaphoreGetMutexHolder(mChipStackLock) == xTaskGetCurrentTaskHandle());
125+
}
126+
#endif // CHIP_STACK_LOCK_TRACKING_ENABLED
127+
107128
template <class ImplClass>
108129
CHIP_ERROR GenericPlatformManagerImpl_FreeRTOS<ImplClass>::_PostEvent(const ChipDeviceEvent * event)
109130
{

src/include/platform/internal/GenericPlatformManagerImpl_FreeRTOS.h

+4
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ class GenericPlatformManagerImpl_FreeRTOS : public GenericPlatformManagerImpl<Im
7878
CHIP_ERROR _StartChipTimer(System::Clock::Timeout duration);
7979
CHIP_ERROR _Shutdown(void);
8080

81+
#if CHIP_STACK_LOCK_TRACKING_ENABLED
82+
bool _IsChipStackLockedByCurrentThread() const;
83+
#endif // CHIP_STACK_LOCK_TRACKING_ENABLED
84+
8185
// ===== Methods available to the implementation subclass.
8286

8387
void PostEventFromISR(const ChipDeviceEvent * event, BaseType_t & yieldRequired);

src/platform/BUILD.gn

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ if (chip_device_platform != "none") {
6969

7070
if (chip_stack_lock_tracking == "auto") {
7171
if (chip_device_platform == "linux" || chip_device_platform == "tizen" ||
72-
chip_device_platform == "android") {
72+
chip_device_platform == "android" || current_os == "freertos") {
7373
# TODO: should be fatal for development. Change once bugs are fixed
74-
chip_stack_lock_tracking = "log"
74+
chip_stack_lock_tracking = "fatal"
7575
} else {
7676
# TODO: may want to enable at least logging for embedded to find bugs
7777
# this needs tuning depending on how many resources various platforms have

0 commit comments

Comments
 (0)