All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wolfgang Grandegger <wg@domain.hid>
To: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
Cc: xenomai-core <xenomai@xenomai.org>
Subject: Re: [Xenomai-core] How to cancel a Xenomai POSIX thread
Date: Wed, 12 Dec 2007 22:00:33 +0100	[thread overview]
Message-ID: <47604BF1.5040102@domain.hid> (raw)
In-Reply-To: <18272.16326.1660.17610@domain.hid>

[-- Attachment #1: Type: text/plain, Size: 4655 bytes --]

Gilles Chanteperdrix wrote:
> Wolfgang Grandegger wrote:
>  > Gilles Chanteperdrix wrote:
>  > > Wolfgang Grandegger wrote:
>  > >  > Gilles Chanteperdrix wrote:
>  > >  > > Wolfgang Grandegger wrote:
>  > >  > >  > Gilles Chanteperdrix wrote:
>  > >  > >  > > On Dec 11, 2007 2:20 PM, Wolfgang Grandegger <wg@domain.hid> wrote:
>  > >  > >  > >> Wolfgang Grandegger wrote:
>  > >  > >  > >>> The attached test application using a more sophisticated signal handling
>  > >  > >  > >>> works fine on my MPC5200-board running Linux 2.6.23 and Xenomai trunk.
>  > >  > >  > >>> Going to try it tomorrow on my PC.
>  > >  > >  > >> It works fine as well on my PC with Linux 2.6.23 and Xenomai trunk and
>  > >  > >  > >> now also with Linux 2.4.25 and Xenomai 2.3.x :-). Just to understand it
>  > >  > >  > >> right: The task signaled with pthread_kill() will be suspended and
>  > >  > >  > >> switches to secondary mode if it was running in primary mode. The signal
>  > >  > >  > >> will then be handled by Linux as usual. When the task resumes, does it
>  > >  > >  > >> get switched back to primary mode automatically?
>  > >  > >  > > 
>  > >  > >  > > No, it will get swtiched back to primary mode only if it calls a
>  > >  > >  > > service needing primary mode.
>  > >  > >  > 
>  > >  > >  > OK.
>  > >  > >  > 
>  > >  > >  > >> Great, the only open issue is why executing init_task() switches to
>  > >  > >  > >> secondary mode resulting in period overruns in high_prio_task(). Is that
>  > >  > >  > >> obvious to you?
>  > >  > >  > > 
>  > >  > >  > > init_task calls pthread_create, which needs running in secondary mode
>  > >  > >  > > to create a thread. We can not create a task without help from
>  > >  > >  > > secondary mode.
>  > >  > >  > 
>  > >  > >  > OK.
>  > >  > >  > 
>  > >  > >  > I was a bit quick with my assumption that it works with 2.4. It actually
>  > >  > >  > only works, if I have a pthread_set_mode_np() in the while loop of the
>  > >  > >  > primary task:
>  > >  > >  > 
>  > >  > >  >         while (1) {
>  > >  > >  > 		pthread_set_mode_np(0, PTHREAD_PRIMARY);
>  > >  > >  >                 count++;
>  > >  > >  >         }
>  > >  > >  > 
>  > >  > >  > Without pthread_set_mode_np(), the system hangs after the following
>  > >  > >  > output lines:
>  > >  > >  > 
>  > >  > >  >   bash-2.05b# ./kill_pthread2
>  > >  > >  >   Starting high_prio_task
>  > >  > >  >   low_prio_task: policy=1 prio=5
>  > >  > >  >   SIGUSER1 to id_low: count=17497245, overruns=0
>  > >  > >  > 
>  > >  > >  > It seems to hang when the low_prio_task() calls pthread_wait_np()
>  > >  > >  > thereafter. Any quick idea where the problem is?
>  > >  > > 
>  > >  > > I am clueless. Are you sure you recompiled the kernel after applying the
>  > >  > > patch adding the pthread_kill syscall ?
>  > >  > 
>  > >  > Well, I tried with v2.3.2, v2.3.x and also trunk, which does not require
>  > >  > the patch. Unfortunately, all versions show the same behavior.
>  > > 
>  > > Did you check all the system call return values to see if one of them is
>  > > not failing ?
>  > 
>  > pthread_kill() returns always 0, or what do you exactly mean. I also
>  > checked with printk() that ksrc/skins/posix/signal.c:pthread_kill() gets
>  > called. I realized the following behaviour if I call a printf after a
>  > certain count value:
>  > 
>  >   void* low_prio_task(void* dummy)
>  >   {
>  >      while (1) {
>  > 		count++;
>  > 		if (count == 100000000)
>  > 			printf("Wakeup\n");
>  >         }
>  >      return 0;
>  >   }
>  > 
>  > Then the program goes on when the above count value is reached:
>  > 
>  >   Starting high_prio_task
>  >   low_prio_task: policy=1 prio=5
>  >   SIGUSER1 to id_low: count=13819079, overruns=0
>  >   ... blocks for a while ...
>  >   SIGUSER2 to id_low: count=27681649, overruns=0
>  >   suspend signal handler
>  >   resume signal handler
>  >   SIGUSER1 to id_low: count=100000000, overruns=0
>  >   SIGUSER2 to id_low: count=100000000, overruns=0
>  >   resume signal handler
>  >   suspend signal handler
>  >   SIGUSER1 to id_low: count=100000000, overruns=0
>  >   SIGUSER2 to id_low: count=100000000, overruns=0
>  >   ...
>  > 
>  > This shows that the task did not get suspended before the printf is
>  > executed. And thereafter it never really resumes.
> 
> I tested the last program you posted, and it works on ARM (where I am
> using linuxthreads, not NPTL), as far as I can tell. Could you send the
> one that does not work ?

Attached. On my MPC5200 it works with pthread_set_mode_np() in the
counter loop of low_prio_thread(), but fails without.

Thanks.

Wolfgang.



[-- Attachment #2: kill_pthread.c --]
[-- Type: text/x-csrc, Size: 4834 bytes --]

#include <stdio.h>
#include <pthread.h>
#include <signal.h>
#include <sys/mman.h>

static unsigned long count;

static pthread_t id_low;
static pthread_t id_high;

#define LOW_PRIO 5
#define HIGH_PRIO 10

void init_task(int prio);

void* low_prio_task(void* dummy)
{
        struct sched_param  param;
        int policy;

        pthread_getschedparam(pthread_self(), &policy, &param);
        printf("Starting %s: policy=%d prio=%d\n",
               __FUNCTION__, policy, param.sched_priority);

	/* Switch back to primary mode */
        pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);

        while (1) {
#if 0
		pthread_set_mode_np(0, PTHREAD_PRIMARY);
#endif
		count++;
        }
        printf("Exiting %s, count=%lu\n", __FUNCTION__, count);
        return 0;
}

void* high_prio_task(void* dummy)
{
        struct timespec tstart = { .tv_sec = 0, .tv_nsec = 0};
#if 0
        struct timespec tperiod = { .tv_sec = 0, .tv_nsec = 10000000 };
#else
        struct timespec tperiod = { .tv_sec = 0, .tv_nsec = 1000000 };
#endif
        unsigned long overruns = 0;
        int tick = 0, step = 0, loop = 0, err;
        struct sched_param  param = { .sched_priority = HIGH_PRIO };
        int policy;

        pthread_getschedparam(pthread_self(), &policy, &param);
        printf("Starting %s: policy=%d prio=%d\n",
               __FUNCTION__, policy, param.sched_priority);

        err = pthread_make_periodic_np(pthread_self(), &tstart, &tperiod);
        if (err) {
		perror("pthread_make_periodic_np");
		return (void *)err;
	}

        while (1) {
                err = pthread_wait_np(&overruns);
#if 0
                if (err) {
                        err = pthread_kill(id_low, SIGUSR1);
			if (err) {
				perror("pthread_kill");
				break;
			}
                        printf("%s overruns=%lu, tick=%d, count=%lu, err=%d\n",
                               __FUNCTION__, overruns, tick, count, err);
                        loop = 0;
                        step = 2;
                }
#endif
                if  (step == 0 && loop >= 100) {
                        loop = 0;
                        step = 1;
                        init_task(LOW_PRIO);
                }
                else if (step == 1 && loop >= 500) {
                        loop = 0;
                        step = 2;
                        err = pthread_kill(id_low, SIGUSR1);
			if (err) {
				perror("pthread_kill");
				break;
			}
                        printf("SIGUSER1 to id_low: count=%lu, overruns=%lu\n",
                               count, overruns);
                }
                else if (step == 2 && loop >= 500) {
			loop = 0;
			step = 1;
                        printf("SIGUSER2 to id_low: count=%lu, overruns=%lu\n",
                               count, overruns);
			err = pthread_kill(id_low, SIGUSR2);
			if (err) {
				perror("pthread_kill");
				break;
			}
		}
                tick++;
                loop++;
        }
        printf("Exiting %s\n", __FUNCTION__);
	return 0;
}

void init_task(int prio)
{
	struct sched_param parm;
	pthread_attr_t attr;

	pthread_attr_init(&attr);
	pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
	if (prio == HIGH_PRIO)
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
	else
		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
	pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
	parm.sched_priority = prio;
	pthread_attr_setschedparam(&attr, &parm);

	if (prio == HIGH_PRIO) {
		pthread_create(&id_high, &attr, high_prio_task, NULL);
		pthread_set_name_np(id_high,"high_prio");
	} else {
		pthread_create(&id_low, &attr, low_prio_task, NULL);
		pthread_set_name_np(id_low,"low_prio");
	}
}

static void suspend_signal_handler(int sig)
{
	sigset_t signal_set;

	printf("suspend signal handler\n");
	sigfillset (&signal_set);
	sigdelset (&signal_set, SIGUSR2);
	sigsuspend(&signal_set);

	return;
}

static void resume_signal_handler(int sig)
{
	printf("resume signal handler\n");
	return;
}


void init_signals(sigset_t *mask)
{
	struct sigaction sigusr1, sigusr2;

	sigemptyset(mask);
	sigaddset(mask, SIGINT);
	sigaddset(mask, SIGTERM);
	sigaddset(mask, SIGHUP);
	sigaddset(mask, SIGALRM);

	pthread_sigmask(SIG_BLOCK, mask, NULL);

	/*
	 * Install the signal handlers for suspend/resume.
	 */
	sigemptyset (&sigusr1.sa_mask);
	sigusr1.sa_flags = 0;
	sigusr1.sa_handler = suspend_signal_handler;
	sigaction(SIGUSR1, &sigusr1, NULL);

	sigemptyset (&sigusr2.sa_mask);
	sigusr2.sa_flags = 0;
	sigusr2.sa_handler = resume_signal_handler;
	sigaction(SIGUSR2, &sigusr2, NULL);

}

int main(int argc, char *argv[])
{
	sigset_t mask;
	int sig;

        mlockall(MCL_CURRENT|MCL_FUTURE);

	init_signals(&mask);

        init_task(HIGH_PRIO);

	sigwait(&mask, &sig);

        printf("Exiting %s\n", __FUNCTION__);
        return 0;
}

  reply	other threads:[~2007-12-12 21:00 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-06 12:31 [Xenomai-core] How to cancel a Xenomai POSIX thread Wolfgang Grandegger
2007-12-06 13:13 ` Gilles Chanteperdrix
2007-12-06 13:24   ` Wolfgang Grandegger
2007-12-06 13:28     ` Gilles Chanteperdrix
2007-12-06 13:44       ` Gilles Chanteperdrix
2007-12-06 14:05         ` Wolfgang Grandegger
2007-12-06 14:21           ` Gilles Chanteperdrix
2007-12-07 14:03             ` Wolfgang Grandegger
2007-12-07 21:23               ` Gilles Chanteperdrix
2007-12-07 22:10                 ` Gilles Chanteperdrix
2007-12-09 21:55                   ` Wolfgang Grandegger
2007-12-09 22:52                     ` Gilles Chanteperdrix
2007-12-10  7:27                       ` Wolfgang Grandegger
2007-12-10 15:20                       ` Wolfgang Grandegger
2007-12-10 15:55                         ` Gilles Chanteperdrix
2007-12-10 21:39                           ` Wolfgang Grandegger
2007-12-10 21:46                             ` Wolfgang Grandegger
2007-12-11 13:20                               ` Wolfgang Grandegger
2007-12-11 13:23                                 ` Gilles Chanteperdrix
2007-12-11 14:39                                   ` Wolfgang Grandegger
2007-12-11 19:59                                     ` Gilles Chanteperdrix
2007-12-12  7:56                                       ` Wolfgang Grandegger
2007-12-12  9:07                                         ` Gilles Chanteperdrix
2007-12-12  9:59                                           ` Wolfgang Grandegger
2007-12-12 20:08                                             ` Gilles Chanteperdrix
2007-12-12 21:00                                               ` Wolfgang Grandegger [this message]
2007-12-12 21:48                                                 ` Gilles Chanteperdrix
2007-12-10 21:56                             ` Gilles Chanteperdrix
2007-12-10 21:21                         ` Gilles Chanteperdrix
2007-12-10 21:37                           ` Wolfgang Grandegger
2007-12-10 22:11                         ` Gilles Chanteperdrix
2007-12-11  7:45                           ` Wolfgang Grandegger
2007-12-06 13:47       ` Wolfgang Grandegger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47604BF1.5040102@domain.hid \
    --to=wg@domain.hid \
    --cc=gilles.chanteperdrix@xenomai.org \
    --cc=xenomai@xenomai.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.