From b42234247b9b020352e0fcbf7a62ca3816ed5119 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Mon, 30 Mar 2020 10:00:43 +0200 Subject: [PATCH] notifier: handle new aggregate flag Implements handling of new notifier aggregate flag. With this flag set the notifier will automatically use existing handle instead of creating a new one. It's helpful when we want to register only once for an event, but it's very hard to explicitly keep track of number of registrations. Signed-off-by: Tomasz Lauda --- src/include/sof/lib/notifier.h | 4 ++++ src/lib/notifier.c | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/include/sof/lib/notifier.h b/src/include/sof/lib/notifier.h index 25f40efd4..5d43f3e8e 100644 --- a/src/include/sof/lib/notifier.h +++ b/src/include/sof/lib/notifier.h @@ -8,6 +8,7 @@ #ifndef __SOF_LIB_NOTIFIER_H__ #define __SOF_LIB_NOTIFIER_H__ +#include #include #include #include @@ -17,6 +18,9 @@ #define NOTIFIER_TARGET_CORE_LOCAL NOTIFIER_TARGET_CORE_MASK(cpu_get_id()) #define NOTIFIER_TARGET_CORE_ALL_MASK 0xFFFFFFFF +/** \brief Notifier flags. */ +#define NOTIFIER_FLAG_AGGREGATE BIT(0) + enum notify_id { NOTIFIER_ID_CPU_FREQ = 0, /* struct clock_notify_data * */ NOTIFIER_ID_SSP_FREQ, /* struct clock_notify_data * */ diff --git a/src/lib/notifier.c b/src/lib/notifier.c index 317d35e45..f7319bc49 100644 --- a/src/lib/notifier.c +++ b/src/lib/notifier.c @@ -31,6 +31,7 @@ struct callback_handle { void *caller; void (*cb)(void *arg, enum notify_id, void *data); struct list_item list; + uint32_t num_registrations; }; int notifier_register(void *receiver, void *caller, enum notify_id type, @@ -42,6 +43,16 @@ int notifier_register(void *receiver, void *caller, enum notify_id type, assert(type >= NOTIFIER_ID_CPU_FREQ && type < NOTIFIER_ID_COUNT); + /* Find already registered event of this type */ + if (flags & NOTIFIER_FLAG_AGGREGATE && + !list_is_empty(¬ify->list[type])) { + handle = container_of((¬ify->list[type])->next, + struct callback_handle, list); + handle->num_registrations++; + + return 0; + } + handle = rzalloc(SOF_MEM_ZONE_SYS_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*handle)); @@ -53,6 +64,7 @@ int notifier_register(void *receiver, void *caller, enum notify_id type, handle->receiver = receiver; handle->caller = caller; handle->cb = cb; + handle->num_registrations = 1; list_item_prepend(&handle->list, ¬ify->list[type]); @@ -82,8 +94,10 @@ void notifier_unregister(void *receiver, void *caller, enum notify_id type) handle = container_of(wlist, struct callback_handle, list); if ((!receiver || handle->receiver == receiver) && (!caller || handle->caller == caller)) { - list_item_del(&handle->list); - rfree(handle); + if (!--handle->num_registrations) { + list_item_del(&handle->list); + rfree(handle); + } } } }