I was able to get the domain to exchange, I recompiled everything
(including etherlabmaster-1.5, with the above hack of disabling
callbacks).
> Which runtime enviroment do you use?
>
> Xenomai/RTAI?
RTAI 3.8.1
> Kernelversion ?
2.6.29.5
> Distro?
Custom distribution made using buildroot, and gcc 4.4.3.
I think I have found the source of the deadlock. The rtdm module
creates a mutex that it uses to marshal calls to etherlab kernel
functions, however it also uses the same mutex reference in the
callback functions it registers.
module.c:599 (initalisation of rtdm module)
register locking / unlocking callback
module.c:422 (marshal body)
> marshal send call:
> locks the mutex
> calls ecrt_master_send
master.c:2058 (send function body)
> calls ec_master_inject_fsm_datagrams
master.c:670 (inject function body)
> calls the mutex callback (fsm_queue_locking_data)
The callback registered @ initialisation time, attempts to lock the
mutex, this is where the dead lock occurs.
I think the intent of the callbacks has changed, it appears to be for
the purposes of protecting the internal datagram queue; rather than
for controlling when other threads (EoE) can also send/receive data.
So I am not sure if they are needed to be used in this way as the user
of the API does not have access to the internal queue directly anyway.
Patch includes my effort so far, changed the nature of locking in
inject datagrams to a speculative one. Doing so solves the dead-lock,
however, no domain data is exchanged, as inject datagrams never gets a
chance, except through ecrt_master_send (where a lock has already been
borrowed by rtdm callback).
-ravi
Index: include/ecrt.h
===================================================================
--- include/ecrt.h (revision 179)
+++ include/ecrt.h (working copy)
@@ -536,7 +536,7 @@
*/
void ecrt_master_callbacks(
ec_master_t *master, /**< EtherCAT master */
- void (*lock_cb)(void *), /**< Lock function. */
+ int (*lock_cb)(void *, int), /**< Lock function. */
void (*unlock_cb)(void *), /**< Unlock function. */
void *cb_data /**< Arbitrary user data. */
);
Index: master/master.c
===================================================================
--- master/master.c (revision 179)
+++ master/master.c (working copy)
@@ -674,8 +674,11 @@
ec_datagram_t *datagram, *next;
size_t queue_size = 0;
- if (master->fsm_queue_lock_cb)
- master->fsm_queue_lock_cb(master->fsm_queue_locking_data);
+ if (master->fsm_queue_lock_cb) {
+ // cannot obtain lock
+ if (!master->fsm_queue_lock_cb(master->fsm_queue_locking_data, 0)) return;
+ }
+
if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0) {
if (master->fsm_queue_unlock_cb)
master->fsm_queue_unlock_cb(master->fsm_queue_locking_data);
@@ -800,7 +803,7 @@
ec_datagram_t *queued_datagram;
if (master->fsm_queue_lock_cb)
- master->fsm_queue_lock_cb(master->fsm_queue_locking_data);
+ master->fsm_queue_lock_cb(master->fsm_queue_locking_data, 0);
ec_mutex_lock(&master->fsm_queue_mutex);
// check, if the datagram is already queued
@@ -2243,7 +2246,7 @@
/*****************************************************************************/
void ecrt_master_callbacks(ec_master_t *master,
- void (*lock_cb)(void *), void (*unlock_cb)(void *),
+ int (*lock_cb)(void *, int), void (*unlock_cb)(void *),
void *cb_data)
{
EC_MASTER_DBG(master, 1,"ecrt_master_callbacks(master = %p, "
Index: rtdm/module.c
===================================================================
--- rtdm/module.c (revision 179)
+++ rtdm/module.c (working copy)
@@ -163,9 +163,42 @@
}
+int lock_callback(void *cb_data, int try) {
+ int ret;
+ EC_RTDM_DRV_STRUCT * pdrvstruc;
+
+ pdrvstruc = (EC_RTDM_DRV_STRUCT*)cb_data;
+ if (!pdrvstruc->master) return;
+
+ if (try) {
+ // if ret is 0 then locking did not take place
+ ret = rt_sem_wait_if(&pdrvstruc->masterlock);
+
+ if (ret == 0xFFFF) ret = 0; // error condition
+ else if (ret <= 0) ret = 0; // would have locked
+ else if (ret > 0) ret = 1; // locking took place
+
+ } else {
+ rt_sem_wait(&pdrvstruc->masterlock);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+void unlock_callback(void *cb_data) {
+ EC_RTDM_DRV_STRUCT * pdrvstruc;
+
+ pdrvstruc = (EC_RTDM_DRV_STRUCT*)cb_data;
+ if (!pdrvstruc->master) return;
+
+ rt_sem_signal(&pdrvstruc->masterlock);
+}
+
/**********************************************************/
/* DRIVER sendcallback */
/**********************************************************/
+/*
void send_callback(void *cb_data)
{
EC_RTDM_DRV_STRUCT * pdrvstruc;
@@ -174,13 +207,14 @@
if (pdrvstruc->master)
{
my_mutex_acquire(&pdrvstruc->masterlock,TM_INFINITE);
- ecrt_master_send_ext(pdrvstruc->master);
+ //ecrt_master_send_ext(pdrvstruc->master);
my_mutex_release(&pdrvstruc->masterlock);
}
}
+*/
/*****************************************************************************/
-
+ /*
void receive_callback(void *cb_data)
{
EC_RTDM_DRV_STRUCT * pdrvstruc;
@@ -193,10 +227,10 @@
my_mutex_release(&pdrvstruc->masterlock);
}
}
+*/
-
void detach_master(EC_RTDM_DRV_STRUCT * pdrvstruc)
{
@@ -561,7 +595,8 @@
EC_RTDM_INFO(pdrvstruc->masterno,"Creating Master mutex %s!\n",&pdrvstruc->mutexname[0]);
my_mutex_create(&pdrvstruc->masterlock,&pdrvstruc->mutexname[0]);
//ecrt_release_master(mstr);
- ecrt_master_callbacks(pdrvstruc->master, send_callback, receive_callback, pdrvstruc);
+ EC_RTDM_INFO(pdrvstruc->masterno,"Attaching locking callbacks...bar");
+ ecrt_master_callbacks(pdrvstruc->master, lock_callback, unlock_callback, pdrvstruc);
EC_RTDM_INFO(pdrvstruc->masterno,"MSTR ATTACH done domain=%u!\n",(unsigned int)pdrvstruc->domain);
pdrvstruc->isattached=1;
ret = 0;
Index: master/master.h
===================================================================
--- master/master.h (revision 179)
+++ master/master.h (working copy)
@@ -261,10 +261,10 @@
struct ec_mutex_t io_mutex; /**< Mutex used in \a IDLE phase. */
- void (*fsm_queue_lock_cb)(void *); /**< FSM queue lock callback. */
+ int (*fsm_queue_lock_cb)(void *, int); /**< FSM queue lock callback. */
void (*fsm_queue_unlock_cb)(void *); /**< FSM queue unlock callback. */
void *fsm_queue_locking_data; /**< Data parameter of fsm queue locking callbacks. */
- void (*app_fsm_queue_lock_cb)(void *); /**< App's FSM queue lock callback. */
+ int (*app_fsm_queue_lock_cb)(void *, int); /**< App's FSM queue lock callback. */
void (*app_fsm_queue_unlock_cb)(void *); /**< App's FSM queue unlock callback. */
void *app_fsm_queue_locking_data; /**< App's data parameter of fsm queue locking callbacks. */
_______________________________________________
etherlab-users mailing list
[email protected]
http://lists.etherlab.org/mailman/listinfo/etherlab-users