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: Fri, 07 Dec 2007 15:03:57 +0100	[thread overview]
Message-ID: <475952CD.3020003@domain.hid> (raw)
In-Reply-To: <2ff1a98a0712060621k436f32b7sc1d1cfe53bea8f18@domain.hid>

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

Hi Gilles,

Gilles Chanteperdrix wrote:
> On Dec 6, 2007 3:05 PM, Wolfgang Grandegger <wg@domain.hid> wrote:
>> Gilles Chanteperdrix wrote:
>>> On Dec 6, 2007 2:28 PM, Gilles Chanteperdrix
>>> <gilles.chanteperdrix@xenomai.org> wrote:
>>>> On Dec 6, 2007 2:24 PM, Wolfgang Grandegger <wg@domain.hid> wrote:
>>>>> Gilles Chanteperdrix wrote:
>>>>>> On Dec 6, 2007 1:31 PM, Wolfgang Grandegger <wg@domain.hid> wrote:
>>>>>>> Hello,
>>>>>>>
>>>>>>> how do I cancel or delete a Xenomai POSIX thread running in primary
>>>>>>> context from a higher priority thread? IIUC, pthread_kill() can only be
>>>>>>> used in secondary context. I tried pthread_cancel(), but it only works
>>>>>>> when hitting a cancelation point, e.g. pthread_testcancel(). Setting
>>>>>>> pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS) did not help. Is
>>>>>>> there a code snippet or even an example program showing how to cancel a
>>>>>>> pthread in primary context?
>>>>>> pthread_kill or pthread_cancel should result in sending a signal to
>>>>>> the target thread, so should cause this thread to switch to secondary
>>>>>> mode to handle it. If you want to wait for the target thread to be
>>>>>> canceled, you should use pthread_cancel and pthread_join.
>>>>> There is no way to cancel a pthread in primary mode from another pthread?
>>>> No. You always need secondary mode to effectively delete a thread. The
>>>> same goes for the native skin.
>>> Ok. I understand what you mean. You want pthread_cancel not to leave
>>> primary mode. This can easily be done by causing pthread_cancel to use
>>> the kernel-space real-time pthread_cancel service. This should work
>>> with no further modification.
>> I want to cancel/delete a task running in primary mode, e.g.
>>
>>   void* work_task(void* dummy)
>>   {
>>         int count = 0;
>>         while (1)
>>                 count++;
>>   }
>>
>> from the outside (= another higher priority task). How can I use the
>> kernel-space real-time pthread_cancel service? My POSIX app is runs in
>> user-land.
> 
> I was thinking about adding a pthread_cancel syscall that would have
> triggered the kernel-space pthread_cancel. But this will not work:
> user-space cleanup handlers would no longer get executed. However,
> this can work for pthread_kill. Here is a patch which adds the
> pthread_kill syscall.

Great, thanks a lot. This seems to work but I'm now fiddling with proper
cleanup and exit. I have attached my small test program. It behaves
somehow strange, at least to me:

- I see task period overruns when the low prio task is started. I
  suspect some switch to secondary mode in init_task().

- The program/system hangs after the listed messages:

  # ./kill_pthread
  Starting high_prio_task
  Killed low_prio task: count=3813129, overruns=0

Any idea what I'm doing wrong?

This is with Linux 2.4.25 and Xenomai 2.3.x on a MPC5200 board.

TIA.

Wolfgang.


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

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

static int count;

static pthread_t id_low;
static pthread_t id_high;

#define LOW_PRIO 5
#define HIGH_PRIO 10

#undef WITH_PRINTF
#undef WITH_SIGXCPU

void init_task(int prio);

void* low_prio_task(void* dummy)
{

   while (1)
   {
#ifdef WITH_PRINTF
	   printf("%s %d\n", __FUNCTION__, count);
#endif
	   count++;
   }
   printf("Exiting %s, count=%d\n", __FUNCTION__, count);
   return 0;
}

void* high_prio_task(void* dummy)
{
	struct timespec tstart = { .tv_sec = 0, .tv_nsec = 0};
#ifdef WITH_PRINTF
	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;

	printf("Starting %s\n", __FUNCTION__);

#ifdef WITH_SIGXCPU
	pthread_set_mode_np(0, PTHREAD_WARNSW);
#endif
	err = pthread_make_periodic_np(pthread_self(), &tstart, &tperiod);
	if (err)
		return (void *)err;

	while (1) {
		err = pthread_wait_np(&overruns);
#if 0
		if (err) {
			pthread_kill(id_low, SIGSTOP);
			printf("%s overruns=%lu, tick=%d, count=%d, err=%d\n",
			       __FUNCTION__, overruns, tick, count, err);
			return 0;
		}
#endif
		if  (step == 0 && loop > 100) {
			loop = 0;
			step = 1;
			init_task(LOW_PRIO);
		}
		else if (step == 1 && loop > 50) {
			loop = 0;
			step = 0;
			pthread_kill(id_low, SIGSTOP);
			printf("Killed low_prio task: count=%d, overruns=%lu\n",
			       count, overruns);
			return 0;
		}
		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);
   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");
   }
}

void catch_signal(int sig)
{
	printf("Signal %d catched\n", sig);
}

#ifdef WITH_SIGXCPU
void catch_switch(int sig)
{
	void *bt[32];
	int nentries;

	printf("Signal %d catched\n", sig);

	/* Dump a backtrace of the frame which caused the switch to
	   secondary mode: */
	nentries = backtrace(bt,sizeof(bt) / sizeof(bt[0]));
	backtrace_symbols_fd(bt,nentries,fileno(stdout));
}
#endif

int main(int argc, char *argv[])
{
	mlockall(MCL_CURRENT|MCL_FUTURE);

	signal(SIGTERM, catch_signal);
	signal(SIGINT, catch_signal);
	signal(SIGHUP, catch_signal);
#ifdef WITH_SIGXCPU
	signal(SIGXCPU, catch_switch);
#endif
	init_task(HIGH_PRIO);

	pthread_join(id_high, NULL);

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

  reply	other threads:[~2007-12-07 14:03 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 [this message]
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
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=475952CD.3020003@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.