diff --git a/src/bin/e_powersave.c b/src/bin/e_powersave.c index be622b577..03a1b91ea 100644 --- a/src/bin/e_powersave.c +++ b/src/bin/e_powersave.c @@ -8,9 +8,12 @@ struct _E_Powersave_Deferred_Action }; /* local subsystem functions */ +static void _e_powersave_sleeper_cb_dummy(void *data EINA_UNUSED, void *buffer EINA_UNUSED, unsigned int bytes EINA_UNUSED); static Eina_Bool _e_powersave_cb_deferred_timer(void *data); static void _e_powersave_mode_eval(void); static void _e_powersave_event_update_free(void *data EINA_UNUSED, void *event); +static void _e_powersave_event_change_send(E_Powersave_Mode mode); +static void _e_powersave_sleepers_wake(void); /* local subsystem globals */ E_API int E_EVENT_POWERSAVE_UPDATE = 0; @@ -19,7 +22,10 @@ static int walking_deferred_actions = 0; static Eina_List *deferred_actions = NULL; static Ecore_Timer *deferred_timer = NULL; static E_Powersave_Mode powersave_mode = E_POWERSAVE_MODE_LOW; +static E_Powersave_Mode powersave_mode_force = E_POWERSAVE_MODE_NONE; static double defer_time = 5.0; +static Eina_Bool powersave_force = EINA_FALSE; +static Eina_List *powersave_sleepers = NULL; /* externally accessible functions */ EINTERN int @@ -46,8 +52,8 @@ e_powersave_deferred_action_add(void (*func)(void *data), const void *data) if (!pa) return NULL; if (deferred_timer) ecore_timer_del(deferred_timer); deferred_timer = ecore_timer_loop_add(defer_time, - _e_powersave_cb_deferred_timer, - NULL); + _e_powersave_cb_deferred_timer, + NULL); pa->func = func; pa->data = data; deferred_actions = eina_list_append(deferred_actions, pa); @@ -80,41 +86,101 @@ e_powersave_deferred_action_del(E_Powersave_Deferred_Action *pa) E_API void e_powersave_mode_set(E_Powersave_Mode mode) { - E_Event_Powersave_Update *ev; - if (mode < e_config->powersave.min) mode = e_config->powersave.min; - else if (mode > e_config->powersave.max) - mode = e_config->powersave.max; + else if (mode > e_config->powersave.max) mode = e_config->powersave.max; + if (powersave_mode == mode) return; - printf("CHANGE PW SAVE MODE TO %i / %i\n", (int)mode, E_POWERSAVE_MODE_EXTREME); powersave_mode = mode; - ev = E_NEW(E_Event_Powersave_Update, 1); - ev->mode = mode; - ecore_event_add(E_EVENT_POWERSAVE_UPDATE, ev, _e_powersave_event_update_free, NULL); + if (powersave_force) return; + _e_powersave_event_change_send(powersave_mode); _e_powersave_mode_eval(); } E_API E_Powersave_Mode e_powersave_mode_get(void) { + if (powersave_force) return powersave_mode_force; return powersave_mode; } -E_API E_Powersave_Mode -e_powersave_mode_min_get(void) +E_API void +e_powersave_mode_force(E_Powersave_Mode mode) { - return e_config->powersave.min; + if (mode == powersave_mode_force) return; + powersave_force = EINA_TRUE; + powersave_mode_force = mode; + _e_powersave_event_change_send(powersave_mode_force); + _e_powersave_mode_eval(); } -E_API E_Powersave_Mode -e_powersave_mode_max_get(void) +E_API void +e_powersave_mode_unforce(void) { - return e_config->powersave.max; + if (!powersave_force) return; + powersave_force = EINA_FALSE; + if (powersave_mode_force != powersave_mode) + { + _e_powersave_event_change_send(powersave_mode); + _e_powersave_mode_eval(); + } + powersave_mode_force = E_POWERSAVE_MODE_NONE; +} + +E_API E_Powersave_Sleeper * +e_powersave_sleeper_new(void) +{ + Ecore_Pipe *pipe; + + pipe = ecore_pipe_add(_e_powersave_sleeper_cb_dummy, NULL); + powersave_sleepers = eina_list_append(powersave_sleepers, pipe); + return (E_Powersave_Sleeper *)pipe; +} + +E_API void +e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper) +{ + Ecore_Pipe *pipe = (Ecore_Pipe *)sleeper; + + if (!pipe) return; + powersave_sleepers = eina_list_remove(powersave_sleepers, pipe); + ecore_pipe_del(pipe); +} + +E_API void +e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval) +{ + Ecore_Pipe *pipe = (Ecore_Pipe *)sleeper; + double tim, now; + + if (!pipe) return; + if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) tim = 3600; + else tim = (double)poll_interval / 8.0; + now = ecore_time_get(); + tim = fmod(now, tim); + ecore_pipe_wait(pipe, 1, tim); } /* local subsystem functions */ +static void +_e_powersave_sleepers_wake(void) +{ + Ecore_Pipe *pipe; + Eina_List *l; + char buf[1] = { 1 }; + + EINA_LIST_FOREACH(powersave_sleepers, l, pipe) + { + ecore_pipe_write(pipe, buf, 1); + } +} + +static void +_e_powersave_sleeper_cb_dummy(void *data EINA_UNUSED, void *buffer EINA_UNUSED, unsigned int bytes EINA_UNUSED) +{ +} + static Eina_Bool _e_powersave_cb_deferred_timer(void *data EINA_UNUSED) { @@ -135,8 +201,12 @@ static void _e_powersave_mode_eval(void) { double t = 0.0; + E_Powersave_Mode mode; - switch (powersave_mode) + if (powersave_force) mode = powersave_mode_force; + else mode = powersave_mode; + + switch (mode) { case E_POWERSAVE_MODE_NONE: t = e_config->powersave.none; /* time to defer "power expensive" activities */ @@ -158,6 +228,10 @@ _e_powersave_mode_eval(void) t = e_config->powersave.extreme; break; + case E_POWERSAVE_MODE_FREEZE: + t = 3600; + break; + default: return; break; @@ -166,8 +240,8 @@ _e_powersave_mode_eval(void) { if (deferred_timer) ecore_timer_del(deferred_timer); deferred_timer = ecore_timer_loop_add(defer_time, - _e_powersave_cb_deferred_timer, - NULL); + _e_powersave_cb_deferred_timer, + NULL); defer_time = t; } } @@ -178,3 +252,15 @@ _e_powersave_event_update_free(void *data EINA_UNUSED, void *event) free(event); } +static void +_e_powersave_event_change_send(E_Powersave_Mode mode) +{ + E_Event_Powersave_Update *ev; + + printf("CHANGE PW SAVE MODE TO %i / %i\n", + (int)mode, E_POWERSAVE_MODE_EXTREME); + ev = E_NEW(E_Event_Powersave_Update, 1); + ev->mode = mode; + ecore_event_add(E_EVENT_POWERSAVE_UPDATE, ev, _e_powersave_event_update_free, NULL); + _e_powersave_sleepers_wake(); +} diff --git a/src/bin/e_powersave.h b/src/bin/e_powersave.h index 97791a4d3..1cf20678a 100644 --- a/src/bin/e_powersave.h +++ b/src/bin/e_powersave.h @@ -6,11 +6,13 @@ typedef enum _E_Powersave_Mode E_POWERSAVE_MODE_LOW, E_POWERSAVE_MODE_MEDIUM, E_POWERSAVE_MODE_HIGH, - E_POWERSAVE_MODE_EXTREME + E_POWERSAVE_MODE_EXTREME, + E_POWERSAVE_MODE_FREEZE } E_Powersave_Mode; typedef struct _E_Powersave_Deferred_Action E_Powersave_Deferred_Action; typedef struct _E_Event_Powersave_Update E_Event_Powersave_Update; +typedef struct _E_Powersave_Sleeper E_Powersave_Sleeper; #else #ifndef E_POWERSAVE_H @@ -31,6 +33,12 @@ E_API E_Powersave_Deferred_Action *e_powersave_deferred_action_add(void (*func) E_API void e_powersave_deferred_action_del(E_Powersave_Deferred_Action *pa); E_API void e_powersave_mode_set(E_Powersave_Mode mode); E_API E_Powersave_Mode e_powersave_mode_get(void); +E_API void e_powersave_mode_force(E_Powersave_Mode mode); +E_API void e_powersave_mode_unforce(void); +E_API E_Powersave_Sleeper *e_powersave_sleeper_new(void); +E_API void e_powersave_sleeper_free(E_Powersave_Sleeper *sleeper); +// the below function is INTENDED to be called from a thread +E_API void e_powersave_sleeper_sleep(E_Powersave_Sleeper *sleeper, int poll_interval); /* FIXME: in the powersave system add things like pre-loading entire files * int memory for pre-caching to avoid disk spinup, when in an appropriate diff --git a/src/modules/cpufreq/e_mod_main.c b/src/modules/cpufreq/e_mod_main.c index e18959797..d5251acd1 100644 --- a/src/modules/cpufreq/e_mod_main.c +++ b/src/modules/cpufreq/e_mod_main.c @@ -1154,7 +1154,9 @@ _cpufreq_event_cb_powersave(void *data EINA_UNUSED, int type, void *event) break; } + // fallthrough is intended case E_POWERSAVE_MODE_EXTREME: + default: if (has_powersave) _cpufreq_set_governor("powersave"); break; @@ -1281,6 +1283,7 @@ typedef struct _Thread_Config Thread_Config; struct _Thread_Config { int interval; + E_Powersave_Sleeper *sleeper; }; static void @@ -1298,9 +1301,8 @@ _cpufreq_cb_frequency_check_main(void *data, Ecore_Thread *th) else _cpufreq_status_free(status); if (ecore_thread_check(th)) break; - usleep((1000000.0 / 8.0) * (double)thc->interval); + e_powersave_sleeper_sleep(thc->sleeper, thc->interval); } - free(thc); } static void @@ -1360,6 +1362,15 @@ _cpufreq_cb_frequency_check_notify(void *data EINA_UNUSED, } } +static void +_cpufreq_cb_frequency_check_done(void *data, + Ecore_Thread *th EINA_UNUSED) +{ + Thread_Config *thc = data; + e_powersave_sleeper_free(thc->sleeper); + free(thc); +} + void _cpufreq_poll_interval_update(void) { @@ -1374,10 +1385,13 @@ _cpufreq_poll_interval_update(void) if (thc) { thc->interval = cpufreq_config->poll_interval; + thc->sleeper = e_powersave_sleeper_new(); cpufreq_config->frequency_check_thread = ecore_thread_feedback_run(_cpufreq_cb_frequency_check_main, _cpufreq_cb_frequency_check_notify, - NULL, NULL, thc, EINA_TRUE); + _cpufreq_cb_frequency_check_done, + _cpufreq_cb_frequency_check_done, + thc, EINA_TRUE); } e_config_save_queue(); } diff --git a/src/modules/temperature/e_mod_main.c b/src/modules/temperature/e_mod_main.c index 61f6f1872..5e76d5919 100644 --- a/src/modules/temperature/e_mod_main.c +++ b/src/modules/temperature/e_mod_main.c @@ -57,6 +57,7 @@ _temperature_thread_free(Tempthread *tth) #ifdef HAVE_EEZE EINA_LIST_FREE(tth->tempdevs, s) eina_stringshare_del(s); #endif + e_powersave_sleeper_free(tth->sleeper); free(tth->extn); free(tth); } @@ -328,7 +329,11 @@ _temperature_check_main(void *data, Ecore_Thread *th) temp = temperature_tempget_get(tth); if (ptemp != temp) ecore_thread_feedback(th, (void *)((long)temp)); ptemp = temp; - usleep((1000000.0 / 8.0) * (double)tth->poll_interval); + e_powersave_sleeper_sleep(tth->sleeper, tth->poll_interval); + if (e_powersave_mode_get() == E_POWERSAVE_MODE_FREEZE) + usleep((1000000.0 / 800.0) * (double)tth->poll_interval); + else + usleep((1000000.0 / 8.0) * (double)tth->poll_interval); if (ecore_thread_check(th)) break; } } @@ -361,6 +366,7 @@ temperature_face_update_config(Config_Face *inst) tth->poll_interval = inst->poll_interval; tth->sensor_type = inst->sensor_type; tth->inst = inst; + tth->sleeper = e_powersave_sleeper_new(); if (inst->sensor_name) tth->sensor_name = eina_stringshare_add(inst->sensor_name); diff --git a/src/modules/temperature/e_mod_main.h b/src/modules/temperature/e_mod_main.h index 52077405c..b9cf67187 100644 --- a/src/modules/temperature/e_mod_main.h +++ b/src/modules/temperature/e_mod_main.h @@ -42,6 +42,7 @@ struct _Tempthread const char *sensor_name; const char *sensor_path; void *extn; + E_Powersave_Sleeper *sleeper; #ifdef HAVE_EEZE Eina_List *tempdevs; #endif