power: remove templock timeout
[platform/core/system/deviced.git] / plugins / iot-headless / power / sleep-wait.c
index d6c1d48..85bfd3d 100644 (file)
 
 #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);
                }
        }
 }
@@ -160,72 +115,56 @@ void remove_sleep_wait(pid_t pid)
 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)
@@ -233,23 +172,14 @@ 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);
        }
 }