Module: xenomai-3
Branch: wip/prioceil
Commit: 38df524a0479ae30cf1bb96e1054544eb21d7759
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=38df524a0479ae30cf1bb96e1054544eb21d7759

Author: Philippe Gerum <r...@xenomai.org>
Date:   Sat Feb 27 18:52:35 2016 +0100

drivers/testing: rtdm: add actor task device

This is for unit testing in task context. The actor task performs
simple test requests issued by userland.

---

 include/rtdm/uapi/testing.h       |    5 ++
 kernel/drivers/testing/rtdmtest.c |  169 +++++++++++++++++++++++++++++++------
 2 files changed, 147 insertions(+), 27 deletions(-)

diff --git a/include/rtdm/uapi/testing.h b/include/rtdm/uapi/testing.h
index 710bea8..76da5ee 100644
--- a/include/rtdm/uapi/testing.h
+++ b/include/rtdm/uapi/testing.h
@@ -83,6 +83,7 @@ struct rttst_swtest_error {
 
 #define RTTST_RTDM_NORMAL_CLOSE                0
 #define RTTST_RTDM_DEFER_CLOSE_CONTEXT 1
+#define RTTST_RTDM_START_STOP_TASK     2
 
 #define RTIOC_TYPE_TESTING             RTDM_CLASS_TESTING
 
@@ -141,6 +142,10 @@ struct rttst_swtest_error {
 
 #define RTTST_RTIOC_RTDM_DEFER_CLOSE \
        _IOW(RTIOC_TYPE_TESTING, 0x40, __u32)
+
+#define RTTST_RTIOC_RTDM_ACTOR_GET_CPU \
+       _IOR(RTIOC_TYPE_TESTING, 0x41, __u32)
+  
 /** @} */
 
 #endif /* !_RTDM_UAPI_TESTING_H */
diff --git a/kernel/drivers/testing/rtdmtest.c 
b/kernel/drivers/testing/rtdmtest.c
index c5224d0..5c705e6 100644
--- a/kernel/drivers/testing/rtdmtest.c
+++ b/kernel/drivers/testing/rtdmtest.c
@@ -17,7 +17,6 @@
  */
 
 #include <linux/module.h>
-
 #include <rtdm/driver.h>
 #include <rtdm/testing.h>
 
@@ -26,28 +25,38 @@ MODULE_AUTHOR("Jan Kiszka <jan.kis...@web.de>");
 MODULE_VERSION("0.1.0");
 MODULE_LICENSE("GPL");
 
-struct rtdm_test_context {
+struct rtdm_basic_context {
        rtdm_timer_t close_timer;
        unsigned long close_counter;
        unsigned long close_deferral;
 };
 
+struct rtdm_actor_context {
+       rtdm_task_t actor_task;
+       unsigned int request;
+       rtdm_event_t run;
+       rtdm_event_t done;
+       union {
+               __u32 cpu;
+       } args;
+};
+
 static void close_timer_proc(rtdm_timer_t *timer)
 {
-       struct rtdm_test_context *ctx =
-               container_of(timer, struct rtdm_test_context, close_timer);
+       struct rtdm_basic_context *ctx =
+               container_of(timer, struct rtdm_basic_context, close_timer);
 
        if (ctx->close_counter != 1)
-               printk(KERN_ERR
+               printk(XENO_ERR
                       "rtdmtest: %s: close_counter is %lu, should be 1!\n",
                       __FUNCTION__, ctx->close_counter);
 
        rtdm_fd_unlock(rtdm_private_to_fd(ctx));
 }
 
-static int rtdm_test_open(struct rtdm_fd *fd, int oflags)
+static int rtdm_basic_open(struct rtdm_fd *fd, int oflags)
 {
-       struct rtdm_test_context *ctx = rtdm_fd_to_private(fd);
+       struct rtdm_basic_context *ctx = rtdm_fd_to_private(fd);
 
        rtdm_timer_init(&ctx->close_timer, close_timer_proc,
                        "rtdm close test");
@@ -57,16 +66,16 @@ static int rtdm_test_open(struct rtdm_fd *fd, int oflags)
        return 0;
 }
 
-static void rtdm_test_close(struct rtdm_fd *fd)
+static void rtdm_basic_close(struct rtdm_fd *fd)
 {
-       struct rtdm_test_context *ctx = rtdm_fd_to_private(fd);
+       struct rtdm_basic_context *ctx = rtdm_fd_to_private(fd);
 
        ctx->close_counter++;
 
        switch (ctx->close_deferral) {
        case RTTST_RTDM_DEFER_CLOSE_CONTEXT:
                if (ctx->close_counter != 2) {
-                       printk(KERN_ERR
+                       printk(XENO_ERR
                               "rtdmtest: %s: close_counter is %lu, "
                               "should be 2!\n",
                               __FUNCTION__, ctx->close_counter);
@@ -78,10 +87,10 @@ static void rtdm_test_close(struct rtdm_fd *fd)
        rtdm_timer_destroy(&ctx->close_timer);
 }
 
-static int
-rtdm_test_ioctl(struct rtdm_fd *fd, unsigned int request, void __user *arg)
+static int rtdm_basic_ioctl(struct rtdm_fd *fd,
+                           unsigned int request, void __user *arg)
 {
-       struct rtdm_test_context *ctx = rtdm_fd_to_private(fd);
+       struct rtdm_basic_context *ctx = rtdm_fd_to_private(fd);
        int err = 0;
 
        switch (request) {
@@ -94,7 +103,6 @@ rtdm_test_ioctl(struct rtdm_fd *fd, unsigned int request, 
void __user *arg)
                                        RTDM_TIMERMODE_RELATIVE);
                }
                break;
-
        default:
                err = -ENOTTY;
        }
@@ -102,30 +110,137 @@ rtdm_test_ioctl(struct rtdm_fd *fd, unsigned int 
request, void __user *arg)
        return err;
 }
 
-static struct rtdm_driver rtdmtest_driver = {
-       .profile_info           = RTDM_PROFILE_INFO(rtdmtest,
+static void actor_handler(void *arg)
+{
+       struct rtdm_actor_context *ctx = arg;
+       int ret;
+
+       for (;;) {
+               if (rtdm_task_should_stop())
+                       return;
+
+               ret = rtdm_event_wait(&ctx->run);
+               if (ret)
+                       break;
+
+               switch (ctx->request) {
+               case RTTST_RTIOC_RTDM_ACTOR_GET_CPU:
+                       ctx->args.cpu = task_cpu(current);
+                       break;
+               default:
+                       printk(XENO_ERR "rtdmtest: bad request code %d\n",
+                              ctx->request);
+               }
+
+               rtdm_event_signal(&ctx->done);
+       }
+}
+
+static int rtdm_actor_open(struct rtdm_fd *fd, int oflags)
+{
+       struct rtdm_actor_context *ctx = rtdm_fd_to_private(fd);
+
+       rtdm_event_init(&ctx->run, 0);
+       rtdm_event_init(&ctx->done, 0);
+
+       return rtdm_task_init(&ctx->actor_task, "rtdm_actor",
+                             actor_handler, ctx,
+                             RTDM_TASK_LOWEST_PRIORITY, 0);
+}
+
+static void rtdm_actor_close(struct rtdm_fd *fd)
+{
+       struct rtdm_actor_context *ctx = rtdm_fd_to_private(fd);
+
+       rtdm_task_destroy(&ctx->actor_task);
+       rtdm_event_destroy(&ctx->run);
+       rtdm_event_destroy(&ctx->done);
+}
+
+#define ACTION_TIMEOUT 50000000ULL /* 50 ms timeout on action */
+
+static int run_action(struct rtdm_actor_context *ctx, unsigned int request)
+{
+       rtdm_toseq_t toseq;
+
+       rtdm_toseq_init(&toseq, ACTION_TIMEOUT);
+       ctx->request = request;
+       rtdm_event_signal(&ctx->run);
+       /*
+        * XXX: The handshake mechanism is not bullet-proof against
+        * -EINTR received when waiting for the done event. Hopefully
+        * we won't restart/start a request while the action task has
+        * not yet completed the previous one we stopped waiting for
+        * abruptly.
+        */
+       return rtdm_event_timedwait(&ctx->done, ACTION_TIMEOUT, &toseq);
+}
+
+static int rtdm_actor_ioctl(struct rtdm_fd *fd,
+                           unsigned int request, void __user *arg)
+{
+       struct rtdm_actor_context *ctx = rtdm_fd_to_private(fd);
+       int ret;
+
+       switch (request) {
+       case RTTST_RTIOC_RTDM_ACTOR_GET_CPU:
+               ctx->args.cpu = (__u32)-EINVAL;
+               ret = run_action(ctx, request);
+               if (ret)
+                       break;
+               ret = rtdm_safe_copy_to_user(fd, arg, &ctx->args.cpu,
+                                            sizeof(ctx->args.cpu));
+               break;
+       default:
+               ret = -ENOTTY;
+       }
+
+       return ret;
+}
+      
+static struct rtdm_driver rtdm_basic_driver = {
+       .profile_info           = RTDM_PROFILE_INFO(rtdm_test_basic,
                                                    RTDM_CLASS_TESTING,
                                                    RTDM_SUBCLASS_RTDMTEST,
                                                    RTTST_PROFILE_VER),
        .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
        .device_count           = 2,
-       .context_size           = sizeof(struct rtdm_test_context),
+       .context_size           = sizeof(struct rtdm_basic_context),
+       .ops = {
+               .open           = rtdm_basic_open,
+               .close          = rtdm_basic_close,
+               .ioctl_rt       = rtdm_basic_ioctl,
+               .ioctl_nrt      = rtdm_basic_ioctl,
+       },
+};
+
+static struct rtdm_driver rtdm_actor_driver = {
+       .profile_info           = RTDM_PROFILE_INFO(rtdm_test_actor,
+                                                   RTDM_CLASS_TESTING,
+                                                   RTDM_SUBCLASS_RTDMTEST,
+                                                   RTTST_PROFILE_VER),
+       .device_flags           = RTDM_NAMED_DEVICE | RTDM_EXCLUSIVE,
+       .device_count           = 1,
+       .context_size           = sizeof(struct rtdm_actor_context),
        .ops = {
-               .open           = rtdm_test_open,
-               .close          = rtdm_test_close,
-               .ioctl_rt       = rtdm_test_ioctl,
-               .ioctl_nrt      = rtdm_test_ioctl,
+               .open           = rtdm_actor_open,
+               .close          = rtdm_actor_close,
+               .ioctl_rt       = rtdm_actor_ioctl,
        },
 };
 
-static struct rtdm_device device[2] = {
+static struct rtdm_device device[3] = {
        [0 ... 1] = {
-               .driver = &rtdmtest_driver,
+               .driver = &rtdm_basic_driver,
                .label = "rtdm%d",
+       },
+       [2] = {
+               .driver = &rtdm_actor_driver,
+               .label = "rtdmx",
        }
 };
 
-static int __init __rtdm_test_init(void)
+static int __init rtdm_test_init(void)
 {
        int i, ret;
 
@@ -146,7 +261,7 @@ fail:
        return ret;
 }
 
-static void __exit __rtdm_test_exit(void)
+static void __exit rtdm_test_exit(void)
 {
        int i;
 
@@ -154,5 +269,5 @@ static void __exit __rtdm_test_exit(void)
                rtdm_dev_unregister(device + i);
 }
 
-module_init(__rtdm_test_init);
-module_exit(__rtdm_test_exit);
+module_init(rtdm_test_init);
+module_exit(rtdm_test_exit);


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

Reply via email to