summaryrefslogtreecommitdiffstats
path: root/mnsl/mns_alm.c
diff options
context:
space:
mode:
Diffstat (limited to 'mnsl/mns_alm.c')
-rw-r--r--mnsl/mns_alm.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/mnsl/mns_alm.c b/mnsl/mns_alm.c
new file mode 100644
index 0000000..5c5e76d
--- /dev/null
+++ b/mnsl/mns_alm.c
@@ -0,0 +1,277 @@
+/*
+ * MOST NetServices "Light" V3.2.7.0.1796 MultiInstance Patch
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * You may also obtain this software under a propriety license from Microchip.
+ * Please contact Microchip for further information.
+ *
+ */
+
+/*!
+ * \file
+ * \brief Implementation of the API locking manager.
+ *
+ * \cond MNS_INTERNAL_DOC
+ * \addtogroup G_ALM
+ * @{
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* Includes */
+/*------------------------------------------------------------------------------------------------*/
+#include "mns_alm.h"
+#include "mns_misc.h"
+
+/*------------------------------------------------------------------------------------------------*/
+/* Internal constant */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Interval for garbage collection */
+static const uint16_t ALM_GARBAGE_COLLECTOR_INTERVAL = 2600U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
+
+/*------------------------------------------------------------------------------------------------*/
+/* Internal prototypes */
+/*------------------------------------------------------------------------------------------------*/
+static void Alm_HandleInternalErrors(void *self, void *error_code_ptr);
+static void Alm_GarbageCollector(void *self);
+static bool Alm_CheckRegisteredApi(void *current_alm_ptr, void *alm_inst_ptr);
+static void Alm_StartTimeout(CApiLockingManager *self);
+static void Alm_ClearTimeout(CApiLockingManager *self);
+static bool Alm_SearchLockedApi(void *current_alm_ptr, void *alm_inst_ptr);
+static void Alm_ResetRegisteredApis(CApiLockingManager *self);
+static bool Alm_ResetApi(void *current_alm_ptr, void *alm_inst_ptr);
+
+/*------------------------------------------------------------------------------------------------*/
+/* Implementation of class CApiLockingManager */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Constructor of the API locking manager class.
+ * \param self Instance pointer
+ * \param tm_ptr Reference to timer management instance
+ * \param eh_ptr Reference to event handler instance
+ * \param mns_inst_id MOST NetServices instance ID
+ */
+void Alm_Ctor(CApiLockingManager *self,
+ CTimerManagement *tm_ptr,
+ CEventHandler *eh_ptr,
+ uint8_t mns_inst_id)
+{
+ MISC_MEM_SET(self, 0, sizeof(*self));
+ T_Ctor(&self->garbage_collector);
+ self->tm_ptr = tm_ptr;
+ self->eh_ptr = eh_ptr;
+ self->mns_inst_id = mns_inst_id;
+
+ /* Observe internal errors and events */
+ Mobs_Ctor(&self->internal_error_obs, self, EH_M_TERMINATION_EVENTS, &Alm_HandleInternalErrors);
+ Eh_AddObsrvInternalEvent(self->eh_ptr, &self->internal_error_obs);
+}
+
+/*! \brief Handles internal errors and events
+ * \param self Instance pointer
+ * \param error_code_ptr Reference to reported error code
+ */
+static void Alm_HandleInternalErrors(void *self, void *error_code_ptr)
+{
+ CApiLockingManager *self_ = (CApiLockingManager *)self;
+ MISC_UNUSED(error_code_ptr);
+
+ Tm_ClearTimer(self_->tm_ptr, &self_->garbage_collector); /* Clear timeout */
+ Alm_ResetRegisteredApis(self_); /* Reset all registered APIs */
+}
+
+/*! \brief Checks for API locking timeouts. This method is the callback function of timer
+ * \c garbage_collector.
+ * \param self Instance pointer
+ */
+static void Alm_GarbageCollector(void *self)
+{
+ CApiLockingManager *self_ = (CApiLockingManager *)self;
+ (void)Dl_Foreach(&self_->api_list, &Alm_CheckRegisteredApi, self_);
+}
+
+/*! \brief This method is used by Alm_GarbageCollector() to process each registered API.
+ * \param current_alm_ptr Reference to the current API
+ * \param alm_inst_ptr Instance of the API locking manager
+ * \return \c false to process all registered APIs
+ */
+static bool Alm_CheckRegisteredApi(void *current_alm_ptr, void *alm_inst_ptr)
+{
+ CApiLockingManager *self = (CApiLockingManager *)alm_inst_ptr;
+ CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr;
+ MISC_UNUSED(self);
+
+ if(alm_ptr_->timeout_mask != 0U)
+ {
+ Alm_ModuleMask_t tmp_mask = 1U;
+ while(alm_ptr_->timeout_mask != 0U)
+ {
+ if(tmp_mask == (tmp_mask & alm_ptr_->timeout_mask))
+ {
+ Ssub_Notify(&alm_ptr_->subject, &tmp_mask, false);
+ alm_ptr_->method_mask &= ~tmp_mask;
+ alm_ptr_->timeout_mask &= ~tmp_mask;
+ }
+ tmp_mask <<= 1;
+ }
+ Alm_ClearTimeout(self);
+ }
+ if(alm_ptr_->method_mask != 0U)
+ {
+ alm_ptr_->timeout_mask = alm_ptr_->method_mask;
+ }
+ return false;
+}
+
+/*! \brief Registers a new API locking object.
+ * \param self Instance pointer
+ * \param al_ptr Reference to the API to register
+ */
+void Alm_RegisterApi(CApiLockingManager *self, CApiLocking *al_ptr)
+{
+ Dl_InsertTail(&self->api_list, &al_ptr->node);
+ Dln_SetData(&al_ptr->node, al_ptr);
+ al_ptr->alm_ptr = self;
+}
+
+/*! \brief Starts the garbage collecting timer.
+ * \param self Instance pointer
+ */
+static void Alm_StartTimeout(CApiLockingManager *self)
+{
+ if(T_IsTimerInUse(&self->garbage_collector) == false)
+ {
+ Tm_SetTimer(self->tm_ptr,
+ &self->garbage_collector,
+ &Alm_GarbageCollector,
+ self,
+ ALM_GARBAGE_COLLECTOR_INTERVAL,
+ ALM_GARBAGE_COLLECTOR_INTERVAL);
+ }
+}
+
+/*! \brief Clears the garbage collecting timer. The timer is clear if no API locking flag is
+ * currently pending.
+ * \param self Instance pointer
+ */
+static void Alm_ClearTimeout(CApiLockingManager *self)
+{
+ if(NULL == Dl_Foreach(&self->api_list, &Alm_SearchLockedApi, self))
+ {
+ Tm_ClearTimer(self->tm_ptr, &self->garbage_collector);
+ }
+}
+
+/*! \brief Used by Alm_ClearTimeout() to check if at least one registered API is locked.
+ * \param current_alm_ptr Reference to the current API locking object
+ * \param alm_inst_ptr Instance of the API locking manager
+ * \return \c true if a locked API was found, otherwise \c false
+ */
+static bool Alm_SearchLockedApi(void *current_alm_ptr, void *alm_inst_ptr)
+{
+ CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr;
+ bool ret_val = false;
+ MISC_UNUSED(alm_inst_ptr);
+
+ if(alm_ptr_->method_mask != 0U)
+ {
+ ret_val = true;
+ }
+ return ret_val;
+}
+
+/*! \brief Resets all registered APIs. Called if an internal error has been occurred.
+ * \param self Instance pointer
+ */
+static void Alm_ResetRegisteredApis(CApiLockingManager *self)
+{
+ (void)Dl_Foreach(&self->api_list, &Alm_ResetApi, self);
+}
+
+/*! \brief Used by Alm_ResetRegisteredApis() to reset all registered APIs.
+ * \param current_alm_ptr Reference to the current API locking object
+ * \param alm_inst_ptr Instance of the API locking manager
+ * \return \c false (process all registered APIs)
+ */
+static bool Alm_ResetApi(void *current_alm_ptr, void *alm_inst_ptr)
+{
+ CApiLocking *alm_ptr_ = (CApiLocking *)current_alm_ptr;
+ MISC_UNUSED(alm_inst_ptr);
+
+ alm_ptr_->method_mask = 0U;
+ alm_ptr_->timeout_mask = 0U;
+
+ return false;
+}
+
+/*------------------------------------------------------------------------------------------------*/
+/* Implementation of class CApiLocking */
+/*------------------------------------------------------------------------------------------------*/
+/*! \brief Constructor of the API locking class.
+ * \param self Instance pointer
+ * \param obs_ptr Observer to signal locked API methods
+ * \param mns_inst_id MOST NetServices instance ID
+ */
+void Al_Ctor(CApiLocking *self, CSingleObserver *obs_ptr, uint8_t mns_inst_id)
+{
+ MISC_MEM_SET(self, 0, sizeof(*self));
+ self->mns_inst_id = mns_inst_id;
+ Dln_Ctor(&self->node, NULL);
+ if(obs_ptr != NULL)
+ {
+ Ssub_Ctor(&self->subject, self->mns_inst_id);
+ (void)Ssub_AddObserver(&self->subject, obs_ptr);
+ }
+}
+
+/*! \brief Locks the given API method.
+ * \param self Instance pointer
+ * \param method Bitmask of method to lock
+ * \return \c true if the API has been locked successfully
+ * \return \c false if the API was already locked
+ */
+bool Al_Lock(CApiLocking *self, Alm_ModuleMask_t method)
+{
+ bool ret_val = false;
+ if((self->method_mask & method) == 0U)
+ {
+ ret_val = true;
+ self->method_mask |= method;
+ self->timeout_mask &= ~method;
+ Alm_StartTimeout(self->alm_ptr);
+ }
+ return ret_val;
+}
+
+/*! \brief Releases the lock of the given API method.
+ * \param self Instance pointer
+ * \param method Bitmask of method to lock
+ */
+void Al_Release(CApiLocking *self, Alm_ModuleMask_t method)
+{
+ self->method_mask &= ~method;
+ self->timeout_mask &= ~method;
+ Alm_ClearTimeout(self->alm_ptr);
+}
+
+/*!
+ * @}
+ * \endcond
+ */
+
+/*------------------------------------------------------------------------------------------------*/
+/* End of file */
+/*------------------------------------------------------------------------------------------------*/
+