Hi GIlles,

As you suggested, I have prepared simple test case that demonstrate how Xenomai 
is utilized by OROCOS. This test case behaves exactly the same like helloword 
example. Scheduler is chosen before any mutex are processed, so in my opinion 
it is not the case which you defined. What is really surprising is that the 
replacing TM_NONBLOCK with TM_INFINITE, in one before last line, do magic and 
suppress signal generation. Furthermore, there is no call to 
'rt_task_set_mode(0, T_WARNSW, NULL);' so why 
signal is generated? If we enable T_WARNSW in the thread, SIGXCPU is generated 
when mutex is locked first time in the thread. 

Code is following:

/*****************************************************************************
 * mutexTest.c
 * Xenomai mutex test for SIGXCPU
 * Mariusz Janiak
 * Wroclaw 2013
 *****************************************************************************/

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <execinfo.h>
#include <sched.h>
#include <native/task.h>
#include <native/mutex.h>
#include <native/sem.h>

#define ORO_SCHED_OTHER 1 /** Soft real-time */

#ifdef UNUSED
#elif defined(__GNUC__)
# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
#else
# define UNUSED(x) x
#endif

void test(void *UNUSED(arg));
void warn_upon_switch(int UNUSED(sig));

RT_TASK  mainTask, testTask; 
RT_MUTEX mutex;
RT_SEM   sem;

void warn_upon_switch(int UNUSED(sig))
{
  void *bt[32];
  int nentries;
  
  nentries = backtrace(bt, sizeof(bt) / sizeof(bt[0]));
  backtrace_symbols_fd(bt, nentries, fileno(stderr));
}

void test(void *UNUSED(arg))
{
  
  /* thread_function() in Thread.cpp:83 -- Thread::configure() in 
     Thread.cpp:489 -- rtos_task_set_period(...) in fosi_internal.cpp:387 --
     rtos_task_make_periodic(...) in fosi_internal.cpp:378*/
  rt_task_set_periodic(NULL, TM_NOW, TM_INFINITE);
  /* thread_function() in Thread.cpp:86 -- rtos_sem_signal(...) in fosi.h:188*/
  rt_sem_v(&sem);
  /* thread_function() in Thread.cpp:89 -- MutexLock */
  rt_mutex_acquire(&mutex, TM_INFINITE);
  rt_mutex_release(&mutex);
  /* hread_function() in Thread.cpp:116 -- rtos_sem_wait(...) in fosi.h:194 */
  rt_sem_p(&sem, TM_INFINITE);
}

int main(int UNUSED(argc), char *UNUSED(argv[]))
{
  int                ret=0;
  struct sched_param param;
  struct sigaction   sa;

  /* rtos_task_create_main(...) in fosi_internal.cpp:82 */
  mlockall(MCL_CURRENT|MCL_FUTURE);
  /* rtos_task_create_main(...) in fosi_internal.cpp:91 */
  param.sched_priority = sched_get_priority_max(ORO_SCHED_OTHER);
  if (param.sched_priority != -1 ){
    sched_setscheduler(0, ORO_SCHED_OTHER, &param);
  }
  /* rtos_task_create_main(...) in fosi_internal.cpp:102 */
  ret = rt_task_shadow(&mainTask, "MutexTest", 0, 0);
  if(ret < 0){
    printf("ERROR: rt_task_shadow(...)\n");
    return -1;
  }
  /* rtos_task_create_main(...) in fosi_internal.cpp:162 */
  sa.sa_sigaction = warn_upon_switch;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  sigaction(SIGXCPU, &sa, 0);

  /* Thread::Thread(...) in Thread.cpp:238 -- automatic in constructor */
  rt_mutex_create(&mutex, "breaker");
  /* Thread::setup(...) in Thread.cpp:257 -- in MutexLock constructor */
  ret = rt_mutex_acquire(&mutex, TM_INFINITE);
  /* Thread::setup(...) in Thread.cpp:264 -- rtos_sem_init(...) in fosi.h:176*/
  rt_sem_create(&sem, "sem", 0, S_PRIO);
  /* Thread::setup(...) in Thread.cpp:293 -- rtos_task_create(...) in 
     fosi_internal.cpp:240 */
  ret = rt_task_spawn(&testTask, "testTask", 128000, 1, T_JOINABLE | (0 & 
T_CPUMASK), test, NULL);
  if(ret < 0){
    printf("ERROR: rt_task_spawn(...)\n");
    return -1;
  }
  /* Thread::setup(...) in Thread.cpp:309 -- rtos_sem_wait(...) in fosi.h:194 */
  rt_sem_p(&sem, TM_INFINITE);
  /* Thread::setup(...) in Thread.cpp:324 --  in MutexLock destructor */
  rt_mutex_release(&mutex);

  /* Do something */
  sleep(1);

  /* Thread::terminate() in Thread.cpp:614 -- rtos_sem_signal(...) in 
     fosi.h:188*/
  rt_sem_v(&sem);
  /* Thread::terminate() in Thread.cpp:616 -- rtos_task_delete(...) in 
     fosi_internal.cpp:490*/
  rt_task_join(&testTask); 
  rt_task_delete(&testTask);
  /* Thread::~Thread() in Thread.cpp:326 -- automatic in destructor when 
     TaskContext::setActivity(...) is called by HelloWord object (default 
     activity created in object constructor is replaced by new activity)*/
  rt_mutex_acquire(&mutex, TM_NONBLOCK); /* rtos_mutex_trylock(...) in 
                                            fosi.h:247 */
  rt_mutex_release(&mutex);              /* we get the SIG here!!! */
  return 0;
}

Building procedure (you need Obj, Dep and Bin dirs in the current path, and 
Xenomai in /usr/xenomai)

gcc -c -Wp,-MM,-MP,-MT,mutexTest.o,-MF,Dep/mutexTest.d -O2 -ggdb3 -DDEBUG_EN   
-I/usr/xenomai/include -D_GNU_SOURCE -D_REENTRANT -D__XENO__ -Wall -Wextra 
-Wcast-align -Wimplicit -Wpointer-arith  -Wswitch -Wredundant-decls 
-Wreturn-type  -Wunused  -Wsign-compare -Waggregate-return  -Wnested-externs  
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations 
-Wbad-function-cast mutexTest.c -o Obj/mutexTest.o

gcc -o Bin/mutexTest.run Obj/mutexTest.o  -lnative -L/usr/xenomai/lib -lxenomai 
-lpthread -lrt -lm

Mariusz




_______________________________________________
Xenomai mailing list
[email protected]
http://www.xenomai.org/mailman/listinfo/xenomai

Reply via email to