merge -c1477 trunk: Moved threads to kthread interface.
--- 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. */