master: added 'run_on_cpu' module parameter to bind kthreads to a cpu

When you use isolcpus to isolate a cpu for the realtime task, as well
as assiging all relevant interrupts to this cpu, it makes sense to
also bind the EtherCAT-OP / EtherCAT-IDLE task to this cpu to reduce
the cache misses and avoid data migration between cores. Therefore
a parameter 'run_on_cpu' is added, that takes the cpu number (same as
in isolcpus, not a smp_affinity mask). If unset, will bind to any cpu
and will be migratable.

The reason to put this into the kernel module is, that the thread is
created during runtime, i.e. when the userspace program is starting
the ethercat master. It would be rather hacky, to find the pid of the
EtherCAT-xx thread and migrate it at this point.

Signed-off-by: Matthias Schoepfer <m.schoepfer@rethinkrobotics.com>
This commit is contained in:
Matthias Schoepfer 2021-09-27 14:56:01 +02:00
parent 34dcf04d4c
commit e6d842cc8f
3 changed files with 17 additions and 4 deletions

View File

@ -42,6 +42,7 @@
#include <linux/device.h>
#include <linux/version.h>
#include <linux/hrtimer.h>
#include <linux/kthread.h>
#include "globals.h"
#include "slave.h"
@ -144,7 +145,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
const uint8_t *backup_mac, /**< MAC address of backup device */
dev_t device_number, /**< Character device number. */
struct class *class, /**< Device class. */
unsigned int debug_level /**< Debug level (module parameter). */
unsigned int debug_level, /**< Debug level (module parameter). */
unsigned int run_on_cpu /**< bind created kernel threads to a cpu */
)
{
int ret;
@ -222,6 +224,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->fsm_exec_count = 0U;
master->debug_level = debug_level;
master->run_on_cpu = run_on_cpu;
master->stats.timeouts = 0;
master->stats.corrupted = 0;
master->stats.unmatched = 0;
@ -581,7 +584,7 @@ int ec_master_thread_start(
)
{
EC_MASTER_INFO(master, "Starting %s thread.\n", name);
master->thread = kthread_run(thread_func, master, name);
master->thread = kthread_create(thread_func, master, name);
if (IS_ERR(master->thread)) {
int err = (int) PTR_ERR(master->thread);
EC_MASTER_ERR(master, "Failed to start master thread (error %i)!\n",
@ -589,6 +592,12 @@ int ec_master_thread_start(
master->thread = NULL;
return err;
}
if (0xffffffff != master->run_on_cpu) {
EC_MASTER_INFO(master, " binding thread to cpu %u\n",master->run_on_cpu);
kthread_bind(master->thread,master->run_on_cpu);
}
/* Ignoring return value of wake_up_process */
(void) wake_up_process(master->thread);
return 0;
}

View File

@ -283,6 +283,7 @@ struct ec_master {
unsigned int fsm_exec_count; /**< Number of entries in execution list. */
unsigned int debug_level; /**< Master debug level. */
unsigned int run_on_cpu; /**< bind kernel threads to this cpu */
ec_stats_t stats; /**< Cyclic statistics. */
struct task_struct *thread; /**< Master thread. */
@ -318,7 +319,7 @@ void ec_master_init_static(void);
// master creation/deletion
int ec_master_init(ec_master_t *, unsigned int, const uint8_t *,
const uint8_t *, dev_t, struct class *, unsigned int);
const uint8_t *, dev_t, struct class *, unsigned int, unsigned int);
void ec_master_clear(ec_master_t *);
/** Number of Ethernet devices.

View File

@ -59,6 +59,7 @@ static unsigned int master_count; /**< Number of masters. */
static char *backup_devices[MAX_MASTERS]; /**< Backup devices parameter. */
static unsigned int backup_count; /**< Number of backup devices. */
static unsigned int debug_level; /**< Debug level parameter. */
static unsigned int run_on_cpu = 0xffffffff; /**< Bind created kernel threads to a cpu. Default do not bind*/
static ec_master_t *masters; /**< Array of masters. */
static struct semaphore master_sem; /**< Master semaphore. */
@ -85,6 +86,8 @@ module_param_array(backup_devices, charp, &backup_count, S_IRUGO);
MODULE_PARM_DESC(backup_devices, "MAC addresses of backup devices");
module_param_named(debug_level, debug_level, uint, S_IRUGO);
MODULE_PARM_DESC(debug_level, "Debug level");
module_param_named(run_on_cpu, run_on_cpu, uint, S_IRUGO);
MODULE_PARM_DESC(run_on_cpu, "Bind kthreads to a specific cpu");
/** \endcond */
@ -150,7 +153,7 @@ int __init ec_init_module(void)
for (i = 0; i < master_count; i++) {
ret = ec_master_init(&masters[i], i, macs[i][0], macs[i][1],
device_number, class, debug_level);
device_number, class, debug_level, run_on_cpu);
if (ret)
goto out_free_masters;
}