📄 power.cxx
字号:
// the policy callback will be changed while the system is running, // but just in case somebody installs a null pointer between the // check and the call... void (*callback)(PowerController*, PowerMode, PowerMode, PowerMode, PowerMode) = __power_policy_callback; if (0 != callback) { (*callback)(controller, old_mode, controller->mode, desired_mode, controller->desired_mode); }}// power_doit() is responsible for a single iteration over the various controllers,// aborting if there is a global mode change during the current iteration. The// calling code, either power_thread_fn() or power_nothread_doit(), will take// care of the higher-level iterating while there is work to be done.//// If a global mode change has been requested then the order in which the controllers// are invoked is significant: front->back for lowering power modes, back->front for// a higher power mode. If there are individual changes to be processed then// arbitrarily front->back is used as well.static inline voidpower_doit(){ PowerController* controller; abort_mode_change = false; if (__power_desired_mode < __power_mode) { // The new mode is more active than the old one, so start with // the power controllers at the back of the table. for (controller = &(__POWER_END__) - 1; !abort_mode_change && (controller >= &(__POWER__[0])); controller--) { PowerMode desired_mode; cyg_bool change_this; #ifdef CYGPKG_POWER_THREAD // Read the desired_mode and change_this flags atomically. cyg_scheduler_lock(); desired_mode = controller->desired_mode; change_this = controller->change_this; cyg_scheduler_unlock();#else desired_mode = controller->desired_mode; change_this = controller->change_this;#endif // If this controller is not running at the desired mode, change it. if (desired_mode != controller->mode) { power_change_controller_mode(controller, desired_mode, change_this); } } } else { // __power_desired_mode >= __power_mode. // Either a global mode change to a less active mode, or // one or more individual controller changes. Other than // iterating in a different direction, the code is the same // as above. for (controller = &(__POWER__[0]); !abort_mode_change && (controller != &(__POWER_END__)); controller++) { PowerMode desired_mode; cyg_bool change_this; #ifdef CYGPKG_POWER_THREAD cyg_scheduler_lock(); desired_mode = controller->desired_mode; change_this = controller->change_this; cyg_scheduler_unlock();#else desired_mode = controller->desired_mode; change_this = controller->change_this;#endif if (desired_mode != controller->mode) { power_change_controller_mode(controller, desired_mode, change_this); } } } // All of the controllers have been invoked. If there have been no // intervening calls to power_set_mode() (which would have updated // abort_mode_change) then we must now be running at the desired // global mode. if (!abort_mode_change) { __power_mode = __power_desired_mode; }}#ifdef CYGPKG_POWER_THREADstatic voidpower_thread_fn(cyg_addrword_t param){ for (;;) { // Currently idle. Wait for a request to change power modes. cyg_semaphore_wait(&power_thread_action); power_doit(); }}#elsestatic inline voidpower_nothread_doit(){ power_todo_count++; if (!power_doing_it) { power_doing_it = true; do { power_doit(); } while (--power_todo_count > 0); power_doing_it = false; }}#endif// ----------------------------------------------------------------------------// The exported calls.extern "C" voidpower_set_controller_mode(PowerController* controller, PowerMode new_mode){#ifdef CYGPKG_POWER_THREAD cyg_scheduler_lock(); // Protect against concurrent calls#endif controller->desired_mode = new_mode; controller->change_this = true;#ifdef CYGPKG_POWER_THREAD cyg_scheduler_unlock(); cyg_semaphore_post(&power_thread_action);#else power_nothread_doit();#endif }extern "C" voidpower_set_mode(PowerMode new_mode){ PowerController* controller;#ifdef CYGPKG_POWER_THREAD cyg_scheduler_lock();#endif __power_desired_mode = new_mode; abort_mode_change = true; // Update each controller. Most importantly, clear the // "change_this" flag in every power controller. The net result is // that power_set_mode() overrides any power_set_controller_mode() // operations that have not yet been processed, but future // power_set_controller_mode() calls will have the desired effect. for (controller = &(__POWER__[0]); controller != &(__POWER_END__); controller++) { if (controller->attached) { controller->change_this = 0; controller->desired_mode = new_mode; } }#ifdef CYGPKG_POWER_THREAD cyg_scheduler_unlock(); cyg_semaphore_post(&power_thread_action);#else power_nothread_doit();#endif }// ----------------------------------------------------------------------------// Power management initialization. This gets called from// power_data.cxx using a prioritized constructors. Doing this way// minimizes the amount of data that is going to end up in libextras.a// and hence in the final executable, allowing linker garbage collection// to clean up as much as possible. The main operation here is to start// up a separate power management thread when configured to do so.//// If no separate thread is being used then no run-time initialization// is needed.#ifdef CYGPKG_POWER_THREADextern "C" voidpower_init(void){ cyg_semaphore_init(&power_thread_action, 0); cyg_thread_create(CYGNUM_POWER_THREAD_PRIORITY, &power_thread_fn, (cyg_addrword_t) 0, "Power management thread", power_thread_stack, CYGNUM_POWER_THREAD_STACKSIZE, &power_thread_handle, &power_thread ); cyg_thread_resume(power_thread_handle);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -