On Tue, Jun 01, 2010 at 04:32:37PM +0200, Philippe Gerum wrote:
> Not in the absence of syscall. We thought about this once already, when
> considering how a watchdog preempting a runaway task in primary mode
> could force a secondary mode switch: there is no sane and easy solution
> to this unfortunately.

This is exactly Sigmatek's problem: Our customers develop code
within our debugging/development environment. We want to catch
this situation (the developer implements a while(1)) with a
watchdog throwing SIGTRAP so that our debugger gets active
and can locate the problem according to the stack frame...

Find attached a separated test case (using SIGTERM which
should terminate the application). When pressing space
the system freezes (work_l() is in the while() loop with
pending signal and work_h() does not rt_task_suspend()
anymore (returning EINTR).

Then, we implement a workaround sending a rt-signal
when rt_task_suspend() returns EINTR. In the rt-signal
handler we explicitely migrate the task to secondary
domain, where linux signal handling is triggered...

Thanks,

        Olli

-- 
Tschaeche IT-Services       Tel.:  +49/9134/9089850
Dr.-Ing. Oliver Tschäche    Mobil: +49/176/20435601
Welluckenweg 4              Email: [email protected]
91077 Neunkirchen
/* compile with gcc -Wall -D_GNU_SOURCE -lpthread -o thisfile thisfile.c */
/*
 * Simple test app to show pthread api mutex behaviour.
 *
 * This is compared against the Xenomai native api behaviour.
 * See mutex_xeno_native.c
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>		/* Needed for mlockall() */
#include <limits.h>
#include <pthread.h>

#include "native/task.h"

#define MY_STACK_SIZE (100*1024)      /* 100 kB is enough for now. */

static pthread_t ph, pl;
static RT_TASK xh, xl;
static volatile int state = 0;

void *
work_h(void *cookie)
{
	if (rt_task_shadow(&xh, "high", 50, 0)) {
		printf("failed to shadow high\n");
		return NULL;
	}
	if (rt_task_set_periodic(&xh, TM_NOW, 1000000)) {
		printf("failed to set high periodic\n");
		return NULL;
	}
	while (1) {
		if (rt_task_wait_period(NULL)) {
			printf("wait_period failed\n");
			break;
		}

		switch (state) {
			case -1:
				if (rt_task_suspend(&xl)) {
					/* work around??? */
				}
				state = 1;
				break;
			case 1:
				rt_task_resume(&xl);
				state = -1;
				break;
			default:
				break;
		}
	}
	return NULL;
}

void *
work_l(void *cookie)
{
	if (rt_task_shadow(&xl, "low", 25, 0)) {
		printf("failed to shadow low\n");
		return NULL;
	}
	if (rt_task_set_mode(0, T_PRIMARY, NULL)) {
		printf("failed to migrate low\n");
		return NULL;
	}
	state = -1;
	while (1)
		;
	return NULL;
}

int main(void)
{
	pthread_attr_t threadattr;
	mlockall(MCL_CURRENT | MCL_FUTURE);

	pthread_attr_init(&threadattr);
	pthread_attr_setstacksize(&threadattr, MY_STACK_SIZE);

	pthread_create(&ph, &threadattr, work_h, NULL);
	printf("high prio watchdog started\n");
	pthread_create(&pl, &threadattr, work_l, NULL);
	printf("low prio work started\n");

	printf("Press <ENTER> to send a signal\n");
	getc(stdin);

	pthread_kill(pl, SIGTERM);

	/* you will not get here, because work_l() eats up your CPU */
	printf("Press <ENTER> to finish\n");
	getc(stdin);

	printf("main finished\n");
	return 0;
}
_______________________________________________
Xenomai-help mailing list
[email protected]
https://mail.gna.org/listinfo/xenomai-help

Reply via email to