merge -c1477 trunk: Moved threads to kthread interface. stable-1.4
authorFlorian Pose <fp@igh-essen.com>
Thu, 02 Oct 2008 07:10:49 +0000
branchstable-1.4
changeset 1644 8174d9b2adaf
parent 1643 cf5a5c511408
child 1645 bbdaddf33131
merge -c1477 trunk: Moved threads to kthread interface.
NEWS
master/master.c
master/master.h
--- a/NEWS	Thu Oct 02 07:07:22 2008 +0000
+++ b/NEWS	Thu Oct 02 07:10:49 2008 +0000
@@ -6,6 +6,7 @@
 
 Changes since 1.4.0-rc2:
 
+* Ported the master thread to the kthread interface.
 * Added missing semaphore up() in an ioctl(). In rare cases, the master
   semaphore was not released.
 * Minor fix in 'slaves' command that fixed duplicate display of supported
--- a/master/master.c	Thu Oct 02 07:07:22 2008 +0000
+++ b/master/master.c	Thu Oct 02 07:10:49 2008 +0000
@@ -61,8 +61,8 @@
 
 void ec_master_clear_slave_configs(ec_master_t *);
 void ec_master_clear_domains(ec_master_t *);
-static int ec_master_idle_thread(ec_master_t *);
-static int ec_master_operation_thread(ec_master_t *);
+static int ec_master_idle_thread(void *);
+static int ec_master_operation_thread(void *);
 #ifdef EC_EOE
 void ec_master_eoe_run(unsigned long);
 #endif
@@ -122,6 +122,8 @@
     master->stats.output_jiffies = 0;
     master->frames_timed_out = 0;
 
+    master->thread = NULL;
+
 #ifdef EC_EOE
     init_timer(&master->eoe_timer);
     master->eoe_timer.function = ec_master_eoe_run;
@@ -310,16 +312,18 @@
  */
 int ec_master_thread_start(
         ec_master_t *master, /**< EtherCAT master */
-        int (*thread_func)(ec_master_t *) /**< thread function to start */
+        int (*thread_func)(void *), /**< thread function to start */
+        const char *name /**< Thread name. */
         )
 {
-    init_completion(&master->thread_can_terminate);
-    init_completion(&master->thread_exit);
-
-    EC_INFO("Starting master thread.\n");
-    if (!(master->thread_id = kernel_thread((int (*)(void *)) thread_func,
-                    master, CLONE_KERNEL)))
+    EC_INFO("Starting %s thread.\n", name);
+    master->thread = kthread_run(thread_func, master, name);
+    if (IS_ERR(master->thread)) {
+        EC_ERR("Failed to start master thread (error %i)!\n",
+                (int) PTR_ERR(master->thread));
+        master->thread = NULL;
         return -1;
+    }
     
     return 0;
 }
@@ -334,19 +338,16 @@
 {
     unsigned long sleep_jiffies;
     
-    if (!master->thread_id) {
-        EC_WARN("ec_master_thread_stop: Already finished!\n");
+    if (!master->thread) {
+        EC_WARN("ec_master_thread_stop(): Already finished!\n");
         return;
     }
 
     if (master->debug_level)
         EC_DBG("Stopping master thread.\n");
 
-    // wait until thread is ready to receive the SIGTERM
-    wait_for_completion(&master->thread_can_terminate);
-
-    kill_proc(master->thread_id, SIGTERM, 1);
-    wait_for_completion(&master->thread_exit);
+    kthread_stop(master->thread);
+    master->thread = NULL;
     EC_INFO("Master thread exited.\n");
 
     if (master->fsm_datagram.state != EC_DATAGRAM_SENT)
@@ -373,7 +374,8 @@
     master->cb_data = master;
 
     master->phase = EC_IDLE;
-    if (ec_master_thread_start(master, ec_master_idle_thread)) {
+    if (ec_master_thread_start(master, ec_master_idle_thread,
+                "EtherCAT-IDLE")) {
         master->phase = EC_ORPHANED;
         return -1;
     }
@@ -529,7 +531,8 @@
     }
 #endif
 
-    if (ec_master_thread_start(master, ec_master_idle_thread))
+    if (ec_master_thread_start(master, ec_master_idle_thread,
+                "EtherCAT-IDLE"))
         EC_WARN("Failed to restart master thread!\n");
 #ifdef EC_EOE
     ec_master_eoe_start(master);
@@ -823,13 +826,14 @@
 
 /** Master kernel thread function for IDLE phase.
  */
-static int ec_master_idle_thread(ec_master_t *master)
-{
-    daemonize("EtherCAT-IDLE");
-    allow_signal(SIGTERM);
-    complete(&master->thread_can_terminate);
-
-    while (!signal_pending(current)) {
+static int ec_master_idle_thread(void *priv_data)
+{
+    ec_master_t *master = (ec_master_t *) priv_data;
+
+    if (master->debug_level)
+        EC_DBG("Idle thread running.\n");
+
+    while (!kthread_should_stop()) {
         ec_datagram_output_stats(&master->fsm_datagram);
 
         // receive
@@ -841,7 +845,8 @@
             goto schedule;
 
         // execute master state machine
-        down(&master->master_sem);
+        if (down_interruptible(&master->master_sem))
+            break;
         ec_fsm_master_exec(&master->fsm);
         up(&master->master_sem);
 
@@ -861,23 +866,23 @@
         }
     }
     
-    master->thread_id = 0;
     if (master->debug_level)
         EC_DBG("Master IDLE thread exiting...\n");
-    complete_and_exit(&master->thread_exit, 0);
+    return 0;
 }
 
 /*****************************************************************************/
 
 /** Master kernel thread function for IDLE phase.
  */
-static int ec_master_operation_thread(ec_master_t *master)
-{
-    daemonize("EtherCAT-OP");
-    allow_signal(SIGTERM);
-    complete(&master->thread_can_terminate);
-
-    while (!signal_pending(current)) {
+static int ec_master_operation_thread(void *priv_data)
+{
+    ec_master_t *master = (ec_master_t *) priv_data;
+
+    if (master->debug_level)
+        EC_DBG("Operation thread running.\n");
+
+    while (!kthread_should_stop()) {
         ec_datagram_output_stats(&master->fsm_datagram);
         if (master->injection_seq_rt != master->injection_seq_fsm ||
                 master->fsm_datagram.state == EC_DATAGRAM_SENT ||
@@ -888,7 +893,8 @@
         ec_master_output_stats(master);
 
         // execute master state machine
-        down(&master->master_sem);
+        if (down_interruptible(&master->master_sem))
+            break;
         ec_fsm_master_exec(&master->fsm);
         up(&master->master_sem);
 
@@ -905,10 +911,9 @@
         }
     }
     
-    master->thread_id = 0;
     if (master->debug_level)
         EC_DBG("Master OP thread exiting...\n");
-    complete_and_exit(&master->thread_exit, 0);
+    return 0;
 }
 
 /*****************************************************************************/
@@ -1294,7 +1299,8 @@
     master->release_cb = master->ext_release_cb;
     master->cb_data = master->ext_cb_data;
     
-    if (ec_master_thread_start(master, ec_master_operation_thread)) {
+    if (ec_master_thread_start(master, ec_master_operation_thread,
+                "EtherCAT-OP")) {
         EC_ERR("Failed to start master thread!\n");
         return -1;
     }
--- a/master/master.h	Thu Oct 02 07:07:22 2008 +0000
+++ b/master/master.h	Thu Oct 02 07:10:49 2008 +0000
@@ -44,6 +44,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
+#include <linux/kthread.h>
 #include <asm/semaphore.h>
 
 #include "device.h"
@@ -134,15 +135,7 @@
     unsigned int frames_timed_out; /**< There were frame timeouts in the last
                                      call to ecrt_master_receive(). */
 
-    int thread_id; /**< Master thread PID. */
-    struct completion thread_can_terminate; /**< Thread termination completion
-                                              object. When stopping the
-                                              thread, it must be assured, that
-                                              it 'hears' a SIGTERM, therefore
-                                              the allow_singal() function must
-                                              have been called.
-                                             */
-    struct completion thread_exit; /**< Thread completion object. */
+    struct task_struct *thread; /**< Master thread. */
 
 #ifdef EC_EOE
     struct timer_list eoe_timer; /**< EoE timer object. */