Module: xenomai-3
Branch: master
Commit: 507c4d17abef6feeeb1538c6e28b442fb27c57c4
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=507c4d17abef6feeeb1538c6e28b442fb27c57c4

Author: Philippe Gerum <r...@xenomai.org>
Date:   Thu Sep 17 00:30:06 2015 +0200

cobalt/posix/sched: add support for sched_setscheduler(2)

---

 .../arch/x86/include/asm/xenomai/syscall32-table.h |    1 +
 kernel/cobalt/posix/sched.c                        |   54 ++++++++++++++++++++
 kernel/cobalt/posix/sched.h                        |   13 +++++
 kernel/cobalt/posix/syscall32.c                    |   22 +++++++-
 kernel/cobalt/posix/syscall32.h                    |    7 +++
 kernel/cobalt/posix/thread.c                       |   42 ++++++---------
 kernel/cobalt/posix/thread.h                       |   13 +++--
 kernel/cobalt/trace/cobalt-posix.h                 |   32 ++++++++++++
 8 files changed, 152 insertions(+), 32 deletions(-)

diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h 
b/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h
index 1dce4e7..53aa131 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/syscall32-table.h
@@ -48,6 +48,7 @@ __COBALT_CALL32x_THUNK(mq_notify)
 __COBALT_CALL32emu_THUNK(sched_weightprio)
 __COBALT_CALL32emu_THUNK(sched_setconfig_np)
 __COBALT_CALL32emu_THUNK(sched_getconfig_np)
+__COBALT_CALL32emu_THUNK(sched_setscheduler_ex)
 __COBALT_CALL32emu_THUNK(timer_create)
 __COBALT_CALL32x_THUNK(timer_create)
 __COBALT_CALL32emu_THUNK(timer_settime)
diff --git a/kernel/cobalt/posix/sched.c b/kernel/cobalt/posix/sched.c
index be2e441..ff4fdc9 100644
--- a/kernel/cobalt/posix/sched.c
+++ b/kernel/cobalt/posix/sched.c
@@ -731,6 +731,60 @@ COBALT_SYSCALL(sched_weightprio, current,
        return __cobalt_sched_weightprio(policy, &param_ex);
 }
 
+int cobalt_sched_setscheduler_ex(pid_t pid,
+                                int policy,
+                                const struct sched_param_ex *param_ex,
+                                __u32 __user *u_winoff,
+                                int __user *u_promoted)
+{
+       struct cobalt_local_hkey hkey;
+       struct cobalt_thread *thread;
+       int ret, promoted = 0;
+       spl_t s;
+
+       trace_cobalt_sched_setscheduler(pid, policy, param_ex);
+
+       if (pid) {
+               xnlock_get_irqsave(&nklock, s);
+               thread = cobalt_thread_find(pid);
+               xnlock_put_irqrestore(&nklock, s);
+       } else
+               thread = cobalt_current_thread();
+
+       if (thread == NULL) {
+               if (u_winoff == NULL)
+                       return -ESRCH;
+                       
+               thread = cobalt_thread_shadow(current, &hkey, u_winoff);
+               if (IS_ERR(thread))
+                       return PTR_ERR(thread);
+
+               promoted = 1;
+       }
+
+       ret = __cobalt_thread_setschedparam_ex(thread, policy, param_ex);
+       if (ret)
+               return ret;
+
+       return cobalt_copy_to_user(u_promoted, &promoted, sizeof(promoted));
+}
+
+COBALT_SYSCALL(sched_setscheduler_ex, conforming,
+              (pid_t pid,
+               int policy,
+               const struct sched_param_ex __user *u_param,
+               __u32 __user *u_winoff,
+               int __user *u_promoted))
+{
+       struct sched_param_ex param_ex;
+
+       if (cobalt_copy_from_user(&param_ex, u_param, sizeof(param_ex)))
+               return -EFAULT;
+
+       return cobalt_sched_setscheduler_ex(pid, policy, &param_ex,
+                                           u_winoff, u_promoted);
+}
+
 void cobalt_sched_reclaim(struct cobalt_process *process)
 {
        struct cobalt_resources *p = &process->resources;
diff --git a/kernel/cobalt/posix/sched.h b/kernel/cobalt/posix/sched.h
index ae7b618..4ccef3c 100644
--- a/kernel/cobalt/posix/sched.h
+++ b/kernel/cobalt/posix/sched.h
@@ -57,6 +57,12 @@ ssize_t __cobalt_sched_getconfig_np(int cpu, int policy,
                                                          void __user 
*u_config, size_t u_len,
                                                          const union 
sched_config *config,
                                                          size_t len));
+int cobalt_sched_setscheduler_ex(pid_t pid,
+                                int policy,
+                                const struct sched_param_ex *param_ex,
+                                __u32 __user *u_winoff,
+                                int __user *u_promoted);
+
 struct xnsched_class *
 cobalt_sched_policy_param(union xnsched_policy_param *param,
                          int u_policy, const struct sched_param_ex *param_ex,
@@ -82,6 +88,13 @@ COBALT_SYSCALL_DECL(sched_getconfig_np,
                     union sched_config __user *u_config,
                     size_t len));
 
+COBALT_SYSCALL_DECL(sched_setscheduler_ex,
+                   (pid_t pid,
+                    int policy,
+                    const struct sched_param_ex *param_ex,
+                    __u32 __user *u_winoff,
+                    int __user *u_promoted));
+
 void cobalt_sched_reclaim(struct cobalt_process *process);
 
 #endif /* !_COBALT_POSIX_SCHED_H */
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index b3ce8a7..fda93a9 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -67,8 +67,8 @@ COBALT_SYSCALL32emu(thread_setschedparam_ex, conforming,
        if (ret)
                return ret;
 
-       return __cobalt_thread_setschedparam_ex(pth, policy, &param_ex,
-                                               u_winoff, u_promoted);
+       return cobalt_thread_setschedparam_ex(pth, policy, &param_ex,
+                                             u_winoff, u_promoted);
 }
 
 COBALT_SYSCALL32emu(thread_getschedparam_ex, current,
@@ -430,6 +430,24 @@ COBALT_SYSCALL32emu(sched_getconfig_np, conformin,
                                           sys32_fetch_config, 
sys32_put_config);
 }
 
+COBALT_SYSCALL32emu(sched_setscheduler_ex, conforming,
+                   (compat_pid_t pid,
+                    int policy,
+                    const struct compat_sched_param_ex __user *u_param_ex,
+                    __u32 __user *u_winoff,
+                    int __user *u_promoted))
+{
+       struct sched_param_ex param_ex;
+       int ret;
+
+       ret = sys32_get_param_ex(policy, &param_ex, u_param_ex);
+       if (ret)
+               return ret;
+
+       return cobalt_sched_setscheduler_ex(pid, policy, &param_ex,
+                                           u_winoff, u_promoted);
+}
+
 COBALT_SYSCALL32emu(timer_create, current,
                    (clockid_t clock,
                     const struct compat_sigevent __user *u_sev,
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index f31448e..045e6be 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -114,6 +114,13 @@ COBALT_SYSCALL32emu_DECL(sched_getconfig_np,
                          union compat_sched_config __user *u_config,
                          size_t len));
 
+COBALT_SYSCALL32emu_DECL(sched_setscheduler_ex,
+                        (compat_pid_t pid,
+                         int policy,
+                         const struct compat_sched_param_ex __user *u_param,
+                         __u32 __user *u_winoff,
+                         int __user *u_promoted));
+
 COBALT_SYSCALL32emu_DECL(timer_create,
                         (clockid_t clock,
                          const struct compat_sigevent __user *u_sev,
diff --git a/kernel/cobalt/posix/thread.c b/kernel/cobalt/posix/thread.c
index 00397fc..0fe2088 100644
--- a/kernel/cobalt/posix/thread.c
+++ b/kernel/cobalt/posix/thread.c
@@ -239,9 +239,8 @@ struct xnthread_personality *cobalt_thread_finalize(struct 
xnthread *zombie)
        return NULL;
 }
 
-static inline int
-pthread_setschedparam_ex(struct cobalt_thread *thread,
-                        int policy, const struct sched_param_ex *param_ex)
+int __cobalt_thread_setschedparam_ex(struct cobalt_thread *thread, int policy,
+                                    const struct sched_param_ex *param_ex)
 {
        struct xnsched_class *sched_class;
        union xnsched_policy_param param;
@@ -452,11 +451,11 @@ static inline int pthread_setmode_np(int clrmask, int 
setmask, int *mode_r)
        return 0;
 }
 
-int __cobalt_thread_setschedparam_ex(unsigned long pth,
-                                    int policy,
-                                    const struct sched_param_ex *param_ex,
-                                    __u32 __user *u_winoff,
-                                    int __user *u_promoted)
+int cobalt_thread_setschedparam_ex(unsigned long pth,
+                                  int policy,
+                                  const struct sched_param_ex *param_ex,
+                                  __u32 __user *u_winoff,
+                                  int __user *u_promoted)
 {
        struct cobalt_local_hkey hkey;
        struct cobalt_thread *thread;
@@ -467,7 +466,10 @@ int __cobalt_thread_setschedparam_ex(unsigned long pth,
        trace_cobalt_pthread_setschedparam(pth, policy, param_ex);
 
        thread = thread_lookup(&hkey);
-       if (thread == NULL && u_winoff) {
+       if (thread == NULL) {
+               if (u_winoff == NULL)
+                       return -ESRCH;
+                       
                thread = cobalt_thread_shadow(current, &hkey, u_winoff);
                if (IS_ERR(thread))
                        return PTR_ERR(thread);
@@ -475,23 +477,13 @@ int __cobalt_thread_setschedparam_ex(unsigned long pth,
                promoted = 1;
        }
 
-       if (thread)
-               ret = pthread_setschedparam_ex(thread, policy, param_ex);
-       else
-               ret = -EPERM;
-
-       if (ret == 0 &&
-           cobalt_copy_to_user(u_promoted, &promoted, sizeof(promoted)))
-               ret = -EFAULT;
+       ret = __cobalt_thread_setschedparam_ex(thread, policy, param_ex);
+       if (ret)
+               return ret;
 
-       return ret;
+       return cobalt_copy_to_user(u_promoted, &promoted, sizeof(promoted));
 }
 
-/*
- * NOTE: there is no cobalt_thread_setschedparam syscall defined by
- * the Cobalt ABI. Useland changes scheduling parameters only via the
- * extended cobalt_thread_setschedparam_ex syscall.
- */
 COBALT_SYSCALL(thread_setschedparam_ex, conforming,
               (unsigned long pth,
                int policy,
@@ -504,8 +496,8 @@ COBALT_SYSCALL(thread_setschedparam_ex, conforming,
        if (cobalt_copy_from_user(&param_ex, u_param, sizeof(param_ex)))
                return -EFAULT;
 
-       return __cobalt_thread_setschedparam_ex(pth, policy, &param_ex,
-                                               u_winoff, u_promoted);
+       return cobalt_thread_setschedparam_ex(pth, policy, &param_ex,
+                                             u_winoff, u_promoted);
 }
 
 int __cobalt_thread_getschedparam_ex(unsigned long pth,
diff --git a/kernel/cobalt/posix/thread.h b/kernel/cobalt/posix/thread.h
index ffdf612..1894774 100644
--- a/kernel/cobalt/posix/thread.h
+++ b/kernel/cobalt/posix/thread.h
@@ -122,11 +122,14 @@ int __cobalt_thread_create(unsigned long pth, int policy,
                           struct sched_param_ex __user *u_param,
                           int xid, __u32 __user *u_winoff);
 
-int __cobalt_thread_setschedparam_ex(unsigned long pth,
-                                    int policy,
-                                    const struct sched_param_ex *param_ex,
-                                    __u32 __user *u_winoff,
-                                    int __user *u_promoted);
+int __cobalt_thread_setschedparam_ex(struct cobalt_thread *thread, int policy,
+                                    const struct sched_param_ex *param_ex);
+
+int cobalt_thread_setschedparam_ex(unsigned long pth,
+                                  int policy,
+                                  const struct sched_param_ex *param_ex,
+                                  __u32 __user *u_winoff,
+                                  int __user *u_promoted);
 
 int __cobalt_thread_getschedparam_ex(unsigned long pth,
                                     int __user *u_policy,
diff --git a/kernel/cobalt/trace/cobalt-posix.h 
b/kernel/cobalt/trace/cobalt-posix.h
index 2382615..9c2ae22 100644
--- a/kernel/cobalt/trace/cobalt-posix.h
+++ b/kernel/cobalt/trace/cobalt-posix.h
@@ -156,6 +156,32 @@ DECLARE_EVENT_CLASS(cobalt_posix_schedparam,
        )
 );
 
+DECLARE_EVENT_CLASS(cobalt_posix_scheduler,
+       TP_PROTO(pid_t pid, int policy,
+                const struct sched_param_ex *param_ex),
+       TP_ARGS(pid, policy, param_ex),
+
+       TP_STRUCT__entry(
+               __field(pid_t, pid)
+               __field(int, policy)
+               __dynamic_array(char, param_ex, sizeof(struct sched_param_ex))
+       ),
+
+       TP_fast_assign(
+               __entry->pid = pid;
+               __entry->policy = policy;
+               memcpy(__get_dynamic_array(param_ex), param_ex, 
sizeof(*param_ex));
+       ),
+
+       TP_printk("pid=%d policy=%d(%s) param={ %s }",
+                 __entry->pid, __entry->policy,
+                 cobalt_print_sched_policy(__entry->policy),
+                 cobalt_print_sched_params(__entry->policy,
+                                           (struct sched_param_ex *)
+                                           __get_dynamic_array(param_ex))
+       )
+);
+
 DECLARE_EVENT_CLASS(cobalt_void,
        TP_PROTO(int dummy),
        TP_ARGS(dummy),
@@ -368,6 +394,12 @@ TRACE_EVENT(cobalt_sched_get_config,
                  __entry->rlen)
 );
 
+DEFINE_EVENT(cobalt_posix_scheduler, cobalt_sched_setscheduler,
+       TP_PROTO(pid_t pid, int policy,
+                const struct sched_param_ex *param_ex),
+       TP_ARGS(pid, policy, param_ex)
+);
+
 DECLARE_EVENT_CLASS(cobalt_posix_prio_bound,
        TP_PROTO(int policy, int prio),
        TP_ARGS(policy, prio),


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

Reply via email to