#define MAX_WAIT_SECOND 5 /* second */
-struct sleep_wait {
+struct proc_info {
pid_t pid;
char comm[128];
- // int timeout;
- // int timer_id;
+ int killed;
};
-/* inactive: This list contains sleep waits added by AddSleepWait dbus method.
- * active: All entries of inactive list are moved to this list when sleep is requested.
- * Each one moves to inactive list on receiving ConfirmWait dbus method.
- * Sleep will be triggered when it becomes empty. */
-static GList *inactive;
-static GList *active;
+struct sleep_wait {
+ struct proc_info *pi;
+ int id;
+};
+
+static GList *proc_list;
+static GList *sleep_waiting;
static int max_wait_timer;
-static int current_sleep_id;
-static void switch_active_list(void)
+static void sleep_wait_done(void)
{
- GList *tmp;
- int n;
-
- n = g_list_length(active);
- if (n != 0)
- _W("Sleep wait remains in active list, %d", n);
+ if (max_wait_timer) {
+ g_source_remove(max_wait_timer);
+ max_wait_timer = 0;
+ }
- tmp = inactive;
- inactive = active;
- active = tmp;
-}
-
-static void request_wake_unlock(void)
-{
- device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL);
- device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, NULL);
+ device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
}
static gboolean max_wait_expired_cb(void *data)
{
struct sleep_wait *sw;
+ struct proc_info *pi;
GList *elem, *elem_next;
max_wait_timer = 0;
- /* force confirmation */
- if (g_list_length(active) != 0) {
- SYS_G_LIST_FOREACH_SAFE(active, elem, elem_next, sw) {
- if (kill(sw->pid, 0) != 0) {
- _D("Remove not existing sleep wait of pid=%d(%s)", sw->pid, sw->comm);
- active = g_list_remove(active, sw);
- free(sw);
- } else { /* move to inactive manually */
- _W("pid=%d(%s) hasn't comfirmed sleep wait", sw->pid, sw->comm);
- active = g_list_remove(active, sw);
- inactive = g_list_append(inactive, sw);
- }
- }
+ SYS_G_LIST_FOREACH_SAFE(sleep_waiting, elem, elem_next, sw) {
+ if (kill(sw->pi->pid, 0) != 0)
+ sw->pi->killed = 1;
+ else
+ _E("pid=%d(%s) hasn't confirmed sleep wait", sw->pi->pid, sw->pi->comm);
+ sleep_waiting = g_list_remove_link(sleep_waiting, elem);
+ g_list_free(elem);
+ free(sw);
}
- _D("Force wake unlock");
- request_wake_unlock();
-
- return G_SOURCE_REMOVE;
-}
-
-/* It returns
- * 0 if sleep_wait is found in inactive list,
- * -EBUSY if sleep_wait is found in active list,
- * -ESRCH if sleep_wait is not found in both list */
-static int find_sleep_wait(pid_t pid, struct sleep_wait **sw)
-{
- struct sleep_wait *ret = NULL;
- GList *elem;
-
- if (!sw)
- return -EINVAL;
-
- SYS_G_LIST_FOREACH(inactive, elem, ret) {
- if (ret->pid == pid) {
- *sw = ret;
- return 0;
+ SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) {
+ if (pi->killed) {
+ _D("Clean up not existing pid=%d(%s) from sleep wait", pi->pid, pi->comm);
+ proc_list = g_list_remove_link(proc_list, elem);
+ g_list_free(elem);
+ free(pi);
}
}
- SYS_G_LIST_FOREACH(active, elem, ret) {
- if (ret->pid == pid) {
- *sw = ret;
- return -EBUSY;
- }
- }
+ _D("Maximum sleep wait expired, timeout=%ds", MAX_WAIT_SECOND);
+ device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
- *sw = NULL;
- return -ESRCH;
+ return G_SOURCE_REMOVE;
}
int add_sleep_wait(pid_t pid)
{
- struct sleep_wait *sw;
- int ret;
+ struct proc_info *pi;
+ GList *elem;
- ret = find_sleep_wait(pid, &sw);
- if (ret == -ESRCH) { /* new node */
- sw = calloc(1, sizeof(struct sleep_wait));
- if (!sw)
- return -ENOMEM;
+ SYS_G_LIST_FOREACH(proc_list, elem, pi) {
+ if (pi->pid == pid)
+ return -EEXIST;
+ }
- sw->pid = pid;
- get_command(pid, sw->comm, sizeof(sw->comm));
- inactive = g_list_append(inactive, sw);
+ pi = calloc(1, sizeof(struct proc_info));
+ if (!pi)
+ return -ENOMEM;
- _D("pid=%d(%s) is added to sleep wait list", sw->pid, sw->comm);
- } else if (ret == 0 || ret == -EBUSY) {
- _D("pid=%d(%s) has already been added to sleep wait list", sw->pid, sw->comm);
- }
+ pi->pid = pid;
+ get_command(pid, pi->comm, sizeof(pi->comm));
+ SYS_G_LIST_APPEND(proc_list, pi);
- return ret;
+ return 0;
}
void remove_sleep_wait(pid_t pid)
{
- struct sleep_wait *sw = NULL;
- int retval;
-
- retval = find_sleep_wait(pid, &sw);
- if (retval == -ESRCH)
- return;
-
- if (sw) {
- _D("pid=%d(%s) requested removing sleep wait", sw->pid, sw->comm);
-
- /* remove from where it is contained */
- active = g_list_remove(active, sw);
- inactive = g_list_remove(inactive, sw);
-
- free(sw);
+ struct sleep_wait *sw;
+ struct proc_info *pi;
+ GList *elem, *elem_next;
- /* wake unlock when active becomes empty by this operation
- * during waiting sleep confirmations */
- if (max_wait_timer != 0 && g_list_length(active) == 0) {
- g_source_remove(max_wait_timer);
- max_wait_timer = 0;
+ SYS_G_LIST_FOREACH_SAFE(sleep_waiting, elem, elem_next, sw) {
+ if (sw->pi->pid == pid) {
+ sleep_waiting = g_list_remove_link(sleep_waiting, elem);
+ g_list_free(elem);
+ free(sw);
+ }
+ }
- _D("All sleep waits have been confirmed, wake unlock");
- request_wake_unlock();
+ SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) {
+ if (pi->pid == pid) {
+ sleep_waiting = g_list_remove_link(sleep_waiting, elem);
+ g_list_free(elem);
+ free(pi);
}
}
}
int confirm_sleep_wait(pid_t pid, int id)
{
struct sleep_wait *sw;
- int ret = 0;
-
- ret = find_sleep_wait(pid, &sw);
- if (ret == -ESRCH) {
- _E("pid=%d hasn't been added to sleep wait list", pid);
- return ret;
- }
-
- /* Multiple confirmation or
- * confirm request after MAX_WAIT_SECOND */
- if (ret == 0) {
- _D("pid=%d(%s) sleep wait has already been confirmed", sw->pid, sw->comm);
- return 0;
- }
+ GList *elem, *elem_next;
- if (id != current_sleep_id) {
- _E("Confirm mismatches sleep_id, current=%d, confirm=%d", current_sleep_id, id);
- return -EINVAL;
- }
+ SYS_G_LIST_FOREACH_SAFE(sleep_waiting, elem, elem_next, sw) {
+ if (sw->pi->pid == pid && sw->id == id) {
+ _D("pid=%d(%s) confirmed sleep id=%d", sw->pi->pid, sw->pi->comm, sw->id);
+ sleep_waiting = g_list_remove_link(sleep_waiting, elem);
+ g_list_free(elem);
+ free(sw);
- /* Move sw from active to inactive list.
- * Wake unlock if active becomes empty. */
- if (ret == -EBUSY) {
- active = g_list_remove(active, sw);
- inactive = g_list_append(inactive, sw);
- _D("pid=%d(%s) confirmed sleep wait", sw->pid, sw->comm);
-
- if (g_list_length(active) == 0) {
- /* remove max_wait_timer and wake unlock immediately */
- if (max_wait_timer) {
- g_source_remove(max_wait_timer);
- max_wait_timer = 0;
+ if (SYS_G_LIST_LENGTH(sleep_waiting) == 0) {
+ /* all sleep-waits are checked */
+ sleep_wait_done();
+ return 0;
}
-
- _D("All sleep waits have been confirmed, wake unlock");
- request_wake_unlock();
}
-
- return 0;
}
- /* fail */
- _E("Failed to confirm sleep wait, %d", ret);
-
- return ret;
+ return 0;
}
-void start_sleep_wait(int id)
+int start_sleep_wait(int id)
{
- if (max_wait_timer) {
- _E("Already sleep waiting");
- return;
- }
+ struct proc_info *pi;
+ struct sleep_wait *sw;
+ GList *elem;
+ int n_sleep_wait;
- switch_active_list();
+ /* create sleep_wait for every pid of proc_list */
+ SYS_G_LIST_FOREACH(proc_list, elem, pi) {
+ sw = calloc(1, sizeof(struct sleep_wait));
+ if (!sw)
+ continue;
- /* no need to defer sleep. wake unlock */
- if (g_list_length(active) == 0) {
- request_wake_unlock();
- return;
+ sw->pi = pi;
+ sw->id = id;
+ SYS_G_LIST_APPEND(sleep_waiting, sw);
}
- current_sleep_id = id;
+ n_sleep_wait = SYS_G_LIST_LENGTH(sleep_waiting);
+ if (n_sleep_wait == 0)
+ return 0;
+
+ /* reset timer */
+ if (max_wait_timer)
+ g_source_remove(max_wait_timer);
- _D("Sleep wait is triggered, maximum wait timeout=%ds", MAX_WAIT_SECOND);
+ _D("Sleep wait is triggered, expected number of confirmation=%d", n_sleep_wait);
max_wait_timer = g_timeout_add_seconds(MAX_WAIT_SECOND, max_wait_expired_cb, NULL);
+
+ return n_sleep_wait;
}
void stop_sleep_wait(void)
struct sleep_wait *sw;
GList *elem, *elem_next;
- if (max_wait_timer == 0)
- return;
-
- /* cancel sleep wait */
- g_source_remove(max_wait_timer);
- max_wait_timer = 0;
-
- _D("Wake locked during sleep wait, cancel all sleep waits");
+ if (max_wait_timer) {
+ g_source_remove(max_wait_timer);
+ max_wait_timer = 0;
+ }
- SYS_G_LIST_FOREACH_SAFE(active, elem, elem_next, sw) {
- if (kill(sw->pid, 0) != 0) {
- _D("Remove not existing sleep wait of %d(%s)", sw->pid, sw->comm);
- active = g_list_remove(active, sw);
- free(sw);
- } else { /* move to inactive manually */
- active = g_list_remove(active, sw);
- inactive = g_list_append(inactive, sw);
- }
+ SYS_G_LIST_FOREACH_SAFE(sleep_waiting, elem, elem_next, sw) {
+ sleep_waiting = g_list_remove_link(sleep_waiting, elem);
+ g_list_free(elem);
+ free(sw);
}
}