power: unify lock states

unify critical_section and nxsem with pm_lock/pm_unlock

Signed-off-by: zhuyanlin <zhuyanlin1@xiaomi.com>
This commit is contained in:
zhuyanlin 2022-03-15 20:42:34 +08:00 committed by Xiang Xiao
parent e4b73d90d7
commit ae21df2ed3
10 changed files with 122 additions and 52 deletions

View File

@ -23,7 +23,7 @@
ifeq ($(CONFIG_PM),y)
CSRCS += pm_initialize.c pm_activity.c pm_changestate.c pm_checkstate.c
CSRCS += pm_register.c pm_unregister.c pm_autoupdate.c pm_governor.c
CSRCS += pm_register.c pm_unregister.c pm_autoupdate.c pm_governor.c pm_lock.c
# Governor implementations

View File

@ -235,7 +235,7 @@ static void governor_activity(int domain, int count)
{
/* Add the activity count to the accumulated counts. */
flags = enter_critical_section();
flags = pm_lock();
accum = (uint32_t)pdomstate->accum + count;
/* Make sure that we do not overflow the underlying representation */
@ -275,7 +275,7 @@ static void governor_activity(int domain, int count)
governor_update(domain, tmp);
}
leave_critical_section(flags);
pm_unlock(flags);
}
}
@ -476,7 +476,7 @@ static enum pm_state_e governor_checkstate(int domain)
* logic in governor_activity().
*/
flags = enter_critical_section();
flags = pm_lock();
/* Check the elapsed time. In periods of low activity, time slicing is
* controlled by IDLE loop polling; in periods of higher activity, time
@ -515,7 +515,7 @@ static enum pm_state_e governor_checkstate(int domain)
}
}
leave_critical_section(flags);
pm_unlock(flags);
return pdomstate->recommended;
}

View File

@ -123,7 +123,7 @@ static enum pm_state_e greedy_governor_checkstate(int domain)
* invoked, which modifies the stay count which we are about to read
*/
flags = enter_critical_section();
flags = pm_lock();
/* Find the lowest power-level which is not locked. */
@ -132,7 +132,7 @@ static enum pm_state_e greedy_governor_checkstate(int domain)
state++;
}
leave_critical_section(flags);
pm_unlock(flags);
/* Return the found state */

View File

@ -41,27 +41,6 @@
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Name: pm_lock
*
* Description:
* Lock the power management registry. NOTE: This function may return
* an error if a signal is received while what (errno == EINTR).
*
****************************************************************************/
#define pm_lock() nxsem_wait(&g_pmglobals.regsem);
/****************************************************************************
* Name: pm_unlock
*
* Description:
* Unlock the power management registry.
*
****************************************************************************/
#define pm_unlock() nxsem_post(&g_pmglobals.regsem);
/****************************************************************************
* Public Types
****************************************************************************/
@ -154,6 +133,26 @@ EXTERN struct pm_global_s g_pmglobals;
void pm_auto_updatestate(int domain);
/****************************************************************************
* Name: pm_lock
*
* Description:
* Lock the power management operation.
*
****************************************************************************/
irqstate_t pm_lock(void);
/****************************************************************************
* Name: pm_unlock
*
* Description:
* Unlock the power management operation.
*
****************************************************************************/
void pm_unlock(irqstate_t flags);
#undef EXTERN
#if defined(__cplusplus)
}

View File

@ -111,11 +111,11 @@ void pm_stay(int domain, enum pm_state_e state)
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
pdom = &g_pmglobals.domain[domain];
flags = enter_critical_section();
flags = pm_lock();
DEBUGASSERT(state < PM_COUNT);
DEBUGASSERT(pdom->stay[state] < UINT16_MAX);
pdom->stay[state]++;
leave_critical_section(flags);
pm_unlock(flags);
pm_auto_updatestate(domain);
}
@ -151,11 +151,11 @@ void pm_relax(int domain, enum pm_state_e state)
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
pdom = &g_pmglobals.domain[domain];
flags = enter_critical_section();
flags = pm_lock();
DEBUGASSERT(state < PM_COUNT);
DEBUGASSERT(pdom->stay[state] > 0);
pdom->stay[state]--;
leave_critical_section(flags);
pm_unlock(flags);
pm_auto_updatestate(domain);
}

View File

@ -109,9 +109,9 @@ void pm_auto_update(int domain, bool auto_update)
DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS);
pdom = &g_pmglobals.domain[domain];
flags = enter_critical_section();
flags = pm_lock();
pdom->auto_update = auto_update;
leave_critical_section(flags);
pm_unlock(flags);
}
#endif /* CONFIG_PM */

View File

@ -213,7 +213,7 @@ int pm_changestate(int domain, enum pm_state_e newstate)
* re-enabled.
*/
flags = enter_critical_section();
flags = pm_lock();
/* First, prepare the drivers for the state change. In this phase,
* drivers may refuse the state state change.
@ -249,7 +249,7 @@ int pm_changestate(int domain, enum pm_state_e newstate)
/* Restore the interrupt state */
leave_critical_section(flags);
pm_unlock(flags);
return ret;
}

75
drivers/power/pm_lock.c Normal file
View File

@ -0,0 +1,75 @@
/****************************************************************************
* drivers/power/pm_lock.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/power/pm.h>
#include <sched.h>
#include "pm.h"
#if defined(CONFIG_PM)
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: pm_lock
*
* Description:
* Lock the power management operation.
*
****************************************************************************/
irqstate_t pm_lock(void)
{
if (!up_interrupt_context() && !sched_idletask())
{
nxsem_wait_uninterruptible(&g_pmglobals.regsem);
}
return enter_critical_section();
}
/****************************************************************************
* Name: pm_unlock
*
* Description:
* Unlock the power management operation.
*
****************************************************************************/
void pm_unlock(irqstate_t flags)
{
leave_critical_section(flags);
if (!up_interrupt_context() && !sched_idletask())
{
nxsem_post(&g_pmglobals.regsem);
}
}
#endif /* CONFIG_PM */

View File

@ -56,20 +56,19 @@
int pm_register(FAR struct pm_callback_s *callbacks)
{
int ret;
irqstate_t flags;
DEBUGASSERT(callbacks);
/* Add the new entry to the end of the list of registered callbacks */
ret = pm_lock();
if (ret == OK)
{
dq_addlast(&callbacks->entry, &g_pmglobals.registry);
pm_unlock();
}
flags = pm_lock();
return ret;
dq_addlast(&callbacks->entry, &g_pmglobals.registry);
pm_unlock(flags);
return 0;
}
#endif /* CONFIG_PM */

View File

@ -55,20 +55,17 @@
int pm_unregister(FAR struct pm_callback_s *callbacks)
{
int ret;
irqstate_t flags;
DEBUGASSERT(callbacks);
/* Remove entry from the list of registered callbacks. */
ret = pm_lock();
if (ret == OK)
{
dq_rem(&callbacks->entry, &g_pmglobals.registry);
pm_unlock();
}
flags = pm_lock();
dq_rem(&callbacks->entry, &g_pmglobals.registry);
pm_unlock(flags);
return ret;
return 0;
}
#endif /* CONFIG_PM */