# HG changeset patch # User Florian Pose # Date 1222931449 0 # Node ID 8174d9b2adaf92afb0dadbe159a179400ba7a392 # Parent cf5a5c511408ef84314bc2c6f50af43f1262673a merge -c1477 trunk: Moved threads to kthread interface. diff -r cf5a5c511408 -r 8174d9b2adaf NEWS --- 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 diff -r cf5a5c511408 -r 8174d9b2adaf master/master.c --- 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; } diff -r cf5a5c511408 -r 8174d9b2adaf master/master.h --- 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 #include #include +#include #include #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. */