enum pm_state_e pm_checkstate(int domain) { FAR struct pm_domain_s *pdom; clock_t now, elapsed; irqstate_t flags; int index; /* Get a convenience pointer to minimize all of the indexing */ DEBUGASSERT(domain >= 0 && domain < CONFIG_PM_NDOMAINS); pdom = &g_pmglobals.domain[domain]; /* Check for the end of the current time slice. This must be performed * with interrupts disabled so that it does not conflict with the similar * logic in pm_activity(). */ flags = enter_critical_section(); /* Check the elapsed time. In periods of low activity, time slicing is * controlled by IDLE loop polling; in periods of higher activity, time * slicing is controlled by driver activity. In either case, the duration * of the time slice is only approximate; during times of heavy activity, * time slices may be become longer and the activity level may be over- * estimated. */ now = clock_systimer(); elapsed = now - pdom->stime; if (elapsed >= TIME_SLICE_TICKS) { int16_t accum; /* Sample the count, reset the time and count, and assess the PM * state. This is an atomic operation because interrupts are * still disabled. */ accum = pdom->accum; pdom->stime = now; pdom->accum = 0; (void)pm_update(domain, accum, elapsed); } /* Consider the possible power state lock here */ for (index = 0; index < pdom->recommended; index++) { if (pdom->stay[index] != 0) { pdom->recommended = index; break; } } leave_critical_section(flags); return pdom->recommended; }
enum pm_state_e pm_checkstate(void) { uint32_t now; irqstate_t flags; /* Check for the end of the current time slice. This must be performed * with interrupts disabled so that it does not conflict with the similar * logic in pm_activity(). */ flags = irqsave(); /* Check the elapsed time. In periods of low activity, time slicing is * controlled by IDLE loop polling; in periods of higher activity, time * slicing is controlled by driver activity. In either case, the duration * of the time slice is only approximate; during times of heavy activity, * time slices may be become longer and the activity level may be over- * estimated. */ now = clock_systimer(); if (now - g_pmglobals.stime >= TIME_SLICE_TICKS) { int16_t accum; /* Sample the count, reset the time and count, and assess the PM * state. This is an atomic operation because interrupts are * still disabled. */ accum = g_pmglobals.accum; g_pmglobals.stime = now; g_pmglobals.accum = 0; /* Reassessing the PM state may require some computation. However, * the work will actually be performed on a worker thread at a user- * controlled priority. */ (void)pm_update(accum); } irqrestore(flags); /* Return the recommended state. Assuming that we are called from the * IDLE thread at the lowest priority level, any updates scheduled on the * worker thread above should have already been peformed and the recommended * state should be current: */ return g_pmglobals.recommended; }
void pm_activity(int priority) { uint32_t now; uint32_t accum; irqstate_t flags; /* Just increment the activity count in the current time slice. The priority * is simply the number of counts that are added. */ if (priority > 0) { /* Add the priority to the accumulated counts in a critical section. */ flags = irqsave(); accum = (uint32_t)g_pmglobals.accum + priority; /* Make sure that we do not overflow the underlying uint16_t representation */ if (accum > INT16_MAX) { accum = INT16_MAX; } /* Save the updated count */ g_pmglobals.accum = (int16_t)accum; /* Check the elapsed time. In periods of low activity, time slicing is * controlled by IDLE loop polling; in periods of higher activity, time * slicing is controlled by driver activity. In either case, the duration * of the time slice is only approximate; during times of heavy activity, * time slices may be become longer and the activity level may be over- * estimated. */ now = clock_systimer(); if (now - g_pmglobals.stime >= TIME_SLICE_TICKS) { int16_t tmp; /* Sample the count, reset the time and count, and assess the PM * state. This is an atomic operation because interrupts are * still disabled. */ tmp = g_pmglobals.accum; g_pmglobals.stime = now; g_pmglobals.accum = 0; /* Reassessing the PM state may require some computation. However, * the work will actually be performed on a worker thread at a user- * controlled priority. */ (void)pm_update(tmp); } irqrestore(flags); } }