Module: xenomai-forge
Branch: next
Commit: fb31526fe854b2178b73dd08c644551823bcd9a5
URL:    
http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=fb31526fe854b2178b73dd08c644551823bcd9a5

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu May 29 09:55:32 2014 +0200

cobalt/posix/sched: auto-cleanup SCHED_QUOTA groups on process exit

---

 kernel/cobalt/posix/init.c    |    3 ++
 kernel/cobalt/posix/process.h |    1 +
 kernel/cobalt/posix/sched.c   |   71 +++++++++++++++++++++++++++++++++--------
 kernel/cobalt/posix/sched.h   |   12 +++++++
 kernel/cobalt/posix/syscall.c |    2 ++
 5 files changed, 75 insertions(+), 14 deletions(-)

diff --git a/kernel/cobalt/posix/init.c b/kernel/cobalt/posix/init.c
index a78e31a..f36d210 100644
--- a/kernel/cobalt/posix/init.c
+++ b/kernel/cobalt/posix/init.c
@@ -48,6 +48,7 @@
 #include <linux/init.h>
 #include "internal.h"
 #include "thread.h"
+#include "sched.h"
 #include "cond.h"
 #include "mutex.h"
 #include "sem.h"
@@ -73,6 +74,7 @@ void cobalt_cleanup(void)
        cobalt_sem_pkg_cleanup();
        cobalt_cond_pkg_cleanup();
        cobalt_mutex_pkg_cleanup();
+       cobalt_sched_pkg_cleanup();
 }
 
 int __init cobalt_init(void)
@@ -83,6 +85,7 @@ int __init cobalt_init(void)
        if (ret)
                return ret;
 
+       cobalt_sched_pkg_init();
        cobalt_mutex_pkg_init();
        cobalt_sem_pkg_init();
        cobalt_cond_pkg_init();
diff --git a/kernel/cobalt/posix/process.h b/kernel/cobalt/posix/process.h
index 587d164..6da0a05 100644
--- a/kernel/cobalt/posix/process.h
+++ b/kernel/cobalt/posix/process.h
@@ -29,6 +29,7 @@ struct cobalt_kqueues {
        struct list_head threadq;
        struct list_head monitorq;
        struct list_head eventq;
+       struct list_head schedq;
 };
 
 struct cobalt_timer;
diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c
index a371818..7d36390 100644
--- a/kernel/cobalt/posix/sched.c
+++ b/kernel/cobalt/posix/sched.c
@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include "internal.h"
 #include "thread.h"
+#include "sched.h"
 #include "clock.h"
 #include <trace/events/cobalt-posix.h>
 
@@ -369,7 +370,9 @@ int do_quota_config(int cpu, const union sched_config 
*config, size_t len)
 {
        int ret = -ESRCH, quota_percent, quota_peak_percent, quota_sum;
        const struct __sched_config_quota *p = &config->quota;
+       struct cobalt_sched_group *group;
        struct xnsched_quota_group *tg;
+       struct cobalt_kqueues *kq;
        struct xnsched *sched;
        spl_t s;
 
@@ -377,16 +380,20 @@ int do_quota_config(int cpu, const union sched_config 
*config, size_t len)
                return -EINVAL;
 
        if (p->op == sched_quota_add) {
-               tg = xnmalloc(sizeof(*tg));
-               if (tg == NULL)
+               group = xnmalloc(sizeof(*group));
+               if (group == NULL)
                        return -ENOMEM;
+               tg = &group->quota;
+               kq = cobalt_kqueues(0);
                xnlock_get_irqsave(&nklock, s);
                sched = xnsched_struct(cpu);
                ret = xnsched_quota_create_group(tg, sched, &quota_sum);
-               xnlock_put_irqrestore(&nklock, s);
-               if (ret)
-                       xnfree(tg);
-               else {
+               if (ret) {
+                       xnlock_put_irqrestore(&nklock, s);
+                       xnfree(group);
+               } else {
+                       list_add(&group->next, &kq->schedq);
+                       xnlock_put_irqrestore(&nklock, s);
                        ret = __xn_safe_copy_to_user(p->add.tgid_r, &tg->tgid,
                                                     sizeof(tg->tgid));
                        if (ret == 0 && p->sum_r)
@@ -400,18 +407,22 @@ int do_quota_config(int cpu, const union sched_config 
*config, size_t len)
                xnlock_get_irqsave(&nklock, s);
                sched = xnsched_struct(cpu);
                tg = xnsched_quota_find_group(sched, p->remove.tgid);
-               if (tg) {
-                       ret = xnsched_quota_destroy_group(tg, &quota_sum);
+               if (tg == NULL) {
+                       xnlock_put_irqrestore(&nklock, s);
+                       return ret;
+               }
+               group = container_of(tg, struct cobalt_sched_group, quota);
+               ret = xnsched_quota_destroy_group(tg, &quota_sum);
+               if (ret) {
                        xnlock_put_irqrestore(&nklock, s);
-                       if (ret == 0) {
-                               xnfree(tg);
-                               if (p->sum_r)
-                                       ret = __xn_safe_copy_to_user(p->sum_r, 
&quota_sum,
-                                                                    
sizeof(quota_sum));
-                       }
                        return ret;
                }
+               list_del(&group->next);
                xnlock_put_irqrestore(&nklock, s);
+               xnfree(group);
+               if (p->sum_r)
+                       ret = __xn_safe_copy_to_user(p->sum_r, &quota_sum,
+                                                    sizeof(quota_sum));
                return ret;
        }
 
@@ -691,4 +702,36 @@ int cobalt_sched_weighted_prio(int policy,
        return prio + sched_class->weight;
 }
 
+void cobalt_sched_cleanup(struct cobalt_kqueues *q)
+{
+       struct cobalt_sched_group *group;
+       int quota_sum;
+       spl_t s;
+
+       xnlock_get_irqsave(&nklock, s);
+
+       for (;;) {
+               if (list_empty(&q->schedq))
+                       break;
+
+               group = list_get_entry(&q->schedq, struct cobalt_sched_group, 
next);
+               xnsched_quota_destroy_group(&group->quota, &quota_sum);
+               xnlock_put_irqrestore(&nklock, s);
+               xnfree(group);
+               xnlock_get_irqsave(&nklock, s);
+       }
+
+       xnlock_put_irqrestore(&nklock, s);
+}
+
+void cobalt_sched_pkg_init(void)
+{
+       INIT_LIST_HEAD(&cobalt_global_kqueues.schedq);
+}
+
+void cobalt_sched_pkg_cleanup(void)
+{
+       cobalt_sched_cleanup(&cobalt_global_kqueues);
+}
+
 /*@}*/
diff --git a/kernel/cobalt/posix/sched.h b/kernel/cobalt/posix/sched.h
index 81e481f..2cf2325 100644
--- a/kernel/cobalt/posix/sched.h
+++ b/kernel/cobalt/posix/sched.h
@@ -18,8 +18,14 @@
 #ifndef _COBALT_POSIX_SCHED_H
 #define _COBALT_POSIX_SCHED_H
 
+#include <linux/list.h>
 #include <cobalt/kernel/sched.h>
 
+struct cobalt_sched_group {
+       struct xnsched_quota_group quota;
+       struct list_head next;
+};
+
 struct xnsched_class *
 cobalt_sched_policy_param(union xnsched_policy_param *param,
                          int u_policy, const struct sched_param_ex *param_ex,
@@ -44,4 +50,10 @@ ssize_t cobalt_sched_getconfig_np(int cpu,
                                  union sched_config __user *u_config,
                                  size_t len);
 
+void cobalt_sched_cleanup(struct cobalt_kqueues *q);
+
+void cobalt_sched_pkg_init(void);
+
+void cobalt_sched_pkg_cleanup(void);
+
 #endif /* !_COBALT_POSIX_SCHED_H */
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 5271509..6e83415 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -59,6 +59,7 @@ static void *cobalt_process_attach(void)
        INIT_LIST_HEAD(&cc->kqueues.threadq);
        INIT_LIST_HEAD(&cc->kqueues.monitorq);
        INIT_LIST_HEAD(&cc->kqueues.eventq);
+       INIT_LIST_HEAD(&cc->kqueues.schedq);
        INIT_LIST_HEAD(&cc->sigwaiters);
        xntree_init(&cc->usems);
        bitmap_fill(cc->timers_map, CONFIG_XENO_OPT_NRTIMERS);
@@ -77,6 +78,7 @@ static void cobalt_process_detach(void *arg)
        cobalt_mutexq_cleanup(&cc->kqueues);
        cobalt_condq_cleanup(&cc->kqueues);
        cobalt_eventq_cleanup(&cc->kqueues);
+       cobalt_sched_cleanup(&cc->kqueues);
 
        kfree(cc);
 }


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to