[Xenomai-help] Xenomai 2.0.1 - Posix Skin - implementing a periodic thread

2005-12-13 Thread Paolo Gai

Dear all,

here is another small demo... this time of a periodic thread in POSIX.

It works under Xenomai, but it fails under Posix Real-Time.

The reason of the failure is the SIGUSR1 not being blocked by the main 
thread. If in main() the comments below the note // REMOVE THE COMMENTS 
BELOW are removed, then the signal is masked also in the main(), and as 
a result the POSIX version works.


The question I have is if the behavior in Xenomai (that is, not failing 
like the POSIX counterpart) is correct or not...


bye

Paolo

--
Evidence S.R.L. - Paolo Gai, CEO
http://www.evidence.eu.com   Tel: +39 0587 274823   Fax: +39 0587 291904

#include stdlib.h
#include stdio.h
#include time.h
#include errno.h
#include signal.h
#include unistd.h
#include pthread.h

void abort_perror(const char *msg)
{
  perror(msg);
  exit(1);
}


void *my_periodic_thread (void *cookie)
{
  struct itimerspec its;
  struct sigevent sig;
  sigset_t blocked;
  siginfo_t si;
  timer_t mytimer;
  int i;

  /* create a timer that will be used to periodically send a signal */
  sig.sigev_notify = SIGEV_SIGNAL;
  sig.sigev_signo = SIGUSR1;
  sig.sigev_value.sival_ptr = sig;
  if(timer_create(CLOCK_REALTIME, sig, mytimer))
abort_perror(timer_create);

  /* block the signal used by the timer */
  sigemptyset(blocked);
  sigaddset(blocked, SIGUSR1);
  pthread_sigmask(SIG_BLOCK, blocked, NULL);

  /* set the periodic timer */
  its.it_value.tv_sec = 0;
  its.it_value.tv_nsec = 4000; /* 40 ms */
  its.it_interval.tv_sec = 0;
  its.it_interval.tv_nsec = 2000; /* 20 ms */;
  if(timer_settime(mytimer, 0, its, NULL))
abort_perror(timer_settime);

  printf(periodic thread started...\n);

  for (i=0; i40; i++) {
while (sigwaitinfo(blocked, si) == -1  errno == EINTR);

/* The thread body */
printf(%d\n,i);
  }

  printf(...periodic thread end!\n);
  
  timer_delete(mytimer);
  return NULL;
}

int main()
{
  pthread_t mythread;
  pthread_attr_t myattr;
  struct sched_param myparam;
  void *returnvalue;
  sigset_t blocked;

  /* block the signal used by the timer */
  // REMOVE THE COMMENTS BELOW
  //  sigemptyset(blocked);
  //  sigaddset(blocked, SIGUSR1);
  //  pthread_sigmask(SIG_BLOCK, blocked, NULL);

  /* initializes the thread attribute */
  pthread_attr_init(myattr);
  pthread_attr_setinheritsched(myattr, PTHREAD_EXPLICIT_SCHED);
  pthread_attr_setschedpolicy(myattr, SCHED_FIFO);
  myparam.sched_priority = 3;
  pthread_attr_setschedparam(myattr, myparam);

  printf(starting a periodic thread...\n);

  if (pthread_create(mythread, myattr, my_periodic_thread, NULL))
abort_perror(pthread_create);

  pthread_attr_destroy(myattr);

  /* wait the end of the thread we just created */
  pthread_join(mythread, returnvalue);

  printf(ending main...\n);

  return 0;
}



Re: [Xenomai-help] Xenomai 2.0.1 - Posix Skin - implementing a periodic thread

2005-12-13 Thread Gilles Chanteperdrix
Paolo Gai wrote:
  Dear all,
  
  here is another small demo... this time of a periodic thread in POSIX.
  
  It works under Xenomai, but it fails under Posix Real-Time.
  
  The reason of the failure is the SIGUSR1 not being blocked by the main 
  thread. If in main() the comments below the note // REMOVE THE COMMENTS 
  BELOW are removed, then the signal is masked also in the main(), and as 
  a result the POSIX version works.
  
  The question I have is if the behavior in Xenomai (that is, not failing 
  like the POSIX counterpart) is correct or not...

The answer is in section 2.4.2 of the standard, delivery of real-time
signals.

http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_02

real-time signals are marked pending to the process, not a particular
thread. So, Linux implementation is correct, Xenomai is incorrect.

When creating a timer with timer_create, Xenomai assume that signals
will be delivered to the thread which created the thread.

Linux supports an extension which allows timer notifications to be
delivered to a particular thread; set the sigev_notify member of the
sigevent structure to 
SIGEV_SIGNAL | SIGEV_THREAD_ID
and set the member _sigev_un._tid to the thread ID of the target thread.

-- 


Gilles Chanteperdrix.