Jan Kiszka wrote:
> Hopefully the last round, addressing remarks brought up on the last
> posting. The changes are:
> 
> [Patches 7-9]
>  - define xnsynch_owner_check as xnsynch-implementation-independent way
>    to check provided and current synch owner match (reduces #ifdefs)
> 
> [Patches 6 and 9]
>  - push lockcnt changes to native mutexes into separate patch (patch
> 
> [Patch 2]
>  - switch creation of xeno_current_key etc. from pthread_once to a
>    constructor
>  - translate pthread_getspecific == NULL into XN_NO_HANDLE
>    (funnily, this shrinks the code on x86-64)
> 
> [Patch 13]
>  - detect SMP feature inconsistency between kernel and userland
>    (but keep SMP off by default for now)
> 
> Note that this series (as well as the latter) depends on the VRTX fix of
> Philippe which is not yet merged into SVN trunk.
> 
> Jan
> 
> PS: Hope this series is compatible with more mail clients /wrt
> commenting on the inlined patches.
> 

Again forgot to attach the testbench we derived from Gilles' unit test.
It currently depends on my infamous inquire patches. Compile with
-D__POSIX_SKIN__ and the usual wrapping for the posix skin, or against
the native lib otherwise.

Jan

-- 
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
/*
 * Functional testing of the mutex implementation for native & posix skins.
 *
 * Copyright (C) Gilles Chanteperdrix  <[EMAIL PROTECTED]>,
 *               Marion Deveaud <[EMAIL PROTECTED]>,
 *               Jan Kiszka <[EMAIL PROTECTED]>
 *
 * Released under the terms of GPLv2.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdarg.h>
#include <sys/mman.h>
#include <pthread.h>
#include <native/timer.h>

#ifdef __POSIX_SKIN__
#include <posix/syscall.h>
#else /* __NATIVE_SKIN__ */
#include <native/task.h>
#include <native/mutex.h>
#include <native/sem.h>
#include <native/cond.h>
#endif

#define MUTEX_CREATE	1
#define MUTEX_LOCK	2
#define MUTEX_TRYLOCK	3
#define MUTEX_UNLOCK	4
#define MUTEX_DESTROY	5
#define COND_CREATE	6
#define COND_SIGNAL	7
#define COND_WAIT	8
#define COND_DESTROY	9
#define THREAD_DETACH	10
#define THREAD_CREATE	11

#define NS_PER_MS	1000000

#ifdef __POSIX_SKIN__
typedef pthread_mutex_t mutex_t;
typedef	pthread_t thread_t;
typedef pthread_cond_t cond_t;
#else /* __NATIVE_SKIN__ */
typedef RT_MUTEX mutex_t;
typedef RT_TASK thread_t;
typedef RT_COND cond_t;
#endif /* __NATIVE_SKIN__ */

void ms_sleep(int time)
{
#ifdef __POSIX_SKIN__
	struct timespec ts;

	ts.tv_sec = 0;
	ts.tv_nsec = time*NS_PER_MS;

	nanosleep(&ts, NULL);
#else /* __NATIVE_SKIN__ */
	rt_task_sleep(time*NS_PER_MS);
#endif /* __NATIVE_SKIN__ */
}

void check_current_prio(int expected_prio)
{
	int current_prio;
#ifdef __POSIX_SKIN__
# ifdef __pse51_get_current_prio
	extern unsigned __pse51_muxid;

        XENOMAI_SKINCALL1(__pse51_muxid, __pse51_get_current_prio, &current_prio);
# else /* !__pse51_get_current_prio */
	current_prio = expected_prio;
# endif /* !__pse51_get_current_prio */

#else /* __NATIVE_SKIN__ */
	int ret;
	RT_TASK_INFO task_info;

	if ((ret = rt_task_inquire(NULL, &task_info)) < 0) {
		fprintf(stderr, "Task inquire: %i (%s)\n", -ret, strerror(-ret));
		exit(EXIT_FAILURE);
	}
	current_prio = task_info.cprio;
#endif /* __NATIVE_SKIN__ */

	if (current_prio != expected_prio) {
		fprintf(stderr, "current prio (%d) != expected prio (%d)\n",
			current_prio, expected_prio);
		exit(EXIT_FAILURE);
	}
}

void check_current_mode(int expected_primary_mode)
{
	int current_in_primary, ret;
#ifdef __POSIX_SKIN__
	pthread_info_t thread_info;

	if ((ret = pthread_inquire_np(pthread_self(), &thread_info)) > 0) {
		fprintf(stderr, "Thread inquire: %i (%s)\n", ret, strerror(ret));
		exit(EXIT_FAILURE);
	}
	current_in_primary = !!(thread_info.status & PTHREAD_PRIMARY);
#else /* __NATIVE_SKIN__ */
	RT_TASK_INFO task_info;

	if ((ret = rt_task_inquire(NULL, &task_info)) < 0) {
		fprintf(stderr, "Task inquire: %i (%s)\n", -ret, strerror(-ret));
		exit(EXIT_FAILURE);
	}
	current_in_primary = !!(task_info.status & T_PRIMARY);
#endif /* __NATIVE_SKIN__ */

	if (current_in_primary != expected_primary_mode) {
		fprintf(stderr, "current mode (%d) != expected mode (%d)\n",
			current_in_primary, expected_primary_mode);
		exit(EXIT_FAILURE);
	}
}

void yield(void)
{
#ifdef __POSIX_SKIN__
	sched_yield();
#else /* __NATIVE_SKIN__ */
	rt_task_yield();
#endif /* __NATIVE_SKIN__ */
}

int dispatch(const char *service_name, int service_type, int check, ...)
{
	thread_t *thread;
	cond_t *cond;
	void *handler;
	va_list ap;
	int status;
#ifdef __POSIX_SKIN__
	struct sched_param param;
	pthread_attr_t threadattr;
	pthread_mutexattr_t mutexattr;
	pthread_mutex_t *mutex;
#else /* __NATIVE_SKIN__ */
	int prio;
#endif /* __NATIVE_SKIN__ */

	va_start(ap, check);
	switch (service_type) {
	case MUTEX_CREATE:
#ifdef __POSIX_SKIN__
		mutex = va_arg(ap, pthread_mutex_t *);
		pthread_mutexattr_init(&mutexattr);
		if (va_arg(ap, int) != 0)
			pthread_mutexattr_setprotocol(&mutexattr,
						      PTHREAD_PRIO_INHERIT);
		pthread_mutexattr_settype(&mutexattr, va_arg(ap, int));
		status = pthread_mutex_init(mutex, &mutexattr);
#else /* __NATIVE_SKIN__ */
		status = -rt_mutex_create(va_arg(ap, RT_MUTEX *), NULL);
#endif /* __NATIVE_SKIN__ */
		break;

	case MUTEX_LOCK:
#ifdef __POSIX_SKIN__
		status = pthread_mutex_lock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
		status =
		    -rt_mutex_acquire(va_arg(ap, RT_MUTEX *), TM_INFINITE);
#endif /* __NATIVE_SKIN__ */
		break;

	case MUTEX_TRYLOCK:
#ifdef __POSIX_SKIN__
		status = pthread_mutex_trylock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
		status =
		    -rt_mutex_acquire(va_arg(ap, RT_MUTEX *), TM_NONBLOCK);
#endif /* __NATIVE_SKIN__ */
		break;

	case MUTEX_UNLOCK:
#ifdef __POSIX_SKIN__
		status = pthread_mutex_unlock(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
		status = -rt_mutex_release(va_arg(ap, RT_MUTEX *));
#endif /* __NATIVE_SKIN__ */
		break;

	case MUTEX_DESTROY:
#ifdef __POSIX_SKIN__
		status = pthread_mutex_destroy(va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
		status = -rt_mutex_delete(va_arg(ap, RT_MUTEX *));
#endif /* __NATIVE_SKIN__ */
		break;

	case COND_CREATE:
#ifdef __POSIX_SKIN__
		status = pthread_cond_init(va_arg(ap, pthread_cond_t *), NULL);
#else /* __NATIVE_SKIN__ */
		status = -rt_cond_create(va_arg(ap, RT_COND *), NULL);
#endif /* __NATIVE_SKIN__ */
		break;

	case COND_SIGNAL:
#ifdef __POSIX_SKIN__
		status = pthread_cond_signal(va_arg(ap, pthread_cond_t *));
#else /* __NATIVE_SKIN__ */
		status = -rt_cond_signal(va_arg(ap, RT_COND *));
#endif /* __NATIVE_SKIN__ */
		break;
	
	case COND_WAIT:
#ifdef __POSIX_SKIN__
		cond = va_arg(ap, pthread_cond_t *);
		status =
		    pthread_cond_wait(cond, va_arg(ap, pthread_mutex_t *));
#else /* __NATIVE_SKIN__ */
		cond = va_arg(ap, RT_COND *);
		status =
		    -rt_cond_wait(cond, va_arg(ap, RT_MUTEX *), TM_INFINITE);
#endif /* __NATIVE_SKIN__ */
		break;

	case COND_DESTROY:
#ifdef __POSIX_SKIN__
		status = pthread_cond_destroy(va_arg(ap, pthread_cond_t *));
#else /* __NATIVE_SKIN__ */
		status = -rt_cond_delete(va_arg(ap, RT_COND *));
#endif /* __NATIVE_SKIN__ */
		break;

#ifdef __POSIX_SKIN__
	case THREAD_DETACH:
		status = pthread_detach(pthread_self());
		break;
#else /* __NATIVE_SKIN__ */
	case THREAD_DETACH:
		return 0;
#endif /* __NATIVE_SKIN__ */

	case THREAD_CREATE:
#ifdef __POSIX_SKIN__
		thread = va_arg(ap, pthread_t *);
		pthread_attr_init(&threadattr);
		pthread_attr_setschedpolicy(&threadattr, SCHED_FIFO);
		param.sched_priority = va_arg(ap, int);
		pthread_attr_setschedparam(&threadattr, &param);
		pthread_attr_setinheritsched(&threadattr,
					     PTHREAD_EXPLICIT_SCHED);
		handler = va_arg(ap, void *);
		status = pthread_create(thread, &threadattr, handler,
					va_arg(ap, void *));
#else /* __NATIVE_SKIN__ */
		thread = va_arg(ap, RT_TASK *);
		prio = va_arg(ap, int);
		handler = va_arg(ap, void *);
		status = -rt_task_spawn(thread, NULL, 0, prio, 0, handler,
					va_arg(ap, void *));
#endif /* __NATIVE_SKIN__ */
		break;

	default:
		fprintf(stderr, "Unknown service %i.\n", service_type);
		exit(EXIT_FAILURE);
	}
	va_end(ap);

	if (status > 0 && check) {
		fprintf(stderr, "%s: %i (%s)\n", 
			service_name, status, strerror(status));
		exit(EXIT_FAILURE);
	}
	return status;
}

void *waiter(void *cookie)
{
	mutex_t *mutex = (mutex_t *) cookie;
	unsigned long long start, diff;

	dispatch("waiter pthread_detach", THREAD_DETACH, 1);
	start = rt_timer_tsc();
	dispatch("waiter mutex_lock", MUTEX_LOCK, 1, mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "waiter, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	ms_sleep(11);
	dispatch("waiter mutex_unlock", MUTEX_UNLOCK, 1, mutex);

	return cookie;
}

void simple_wait(void)
{
	unsigned long long start, diff;
	mutex_t mutex;
	thread_t waiter_tid;

	fprintf(stderr, "simple_wait\n");

	dispatch("simple mutex_init", MUTEX_CREATE, 1, &mutex, 0, 0);
	dispatch("simple mutex_lock 1", MUTEX_LOCK, 1, &mutex);
	dispatch("simple thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
		 waiter, &mutex);
	ms_sleep(10);
	dispatch("simple mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
	yield();

	start = rt_timer_tsc();
	dispatch("simple mutex_lock 2", MUTEX_LOCK, 1, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}

	dispatch("simple mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
	dispatch("simple mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}

void recursive_wait(void)
{
	unsigned long long start, diff;
	mutex_t mutex;
	thread_t waiter_tid;

	fprintf(stderr, "recursive_wait\n");

	dispatch("rec mutex_init", MUTEX_CREATE, 1, &mutex, 0,
		 PTHREAD_MUTEX_RECURSIVE);
	dispatch("rec mutex_lock 1", MUTEX_LOCK, 1, &mutex);
	dispatch("rec mutex_lock 2", MUTEX_LOCK, 1, &mutex);

	dispatch("rec thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
		 waiter, &mutex);

	dispatch("rec mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex); 
	ms_sleep(10);
	dispatch("rec mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
	yield();

	start = rt_timer_tsc();
	dispatch("rec mutex_lock 3", MUTEX_LOCK, 1, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);

	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	dispatch("rec mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
	dispatch("rec mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}

void errorcheck_wait(void)
{
#ifdef __POSIX_SKIN__
	/* This test only makes sense under POSIX */
	unsigned long long start, diff;
	mutex_t mutex;
	thread_t waiter_tid;
	int err;

	fprintf(stderr, "errorcheck_wait\n");

	dispatch("errorcheck mutex_init", MUTEX_CREATE, 1, &mutex, 0,
		 PTHREAD_MUTEX_ERRORCHECK);
	dispatch("errorcheck mutex_lock 1", MUTEX_LOCK, 1, &mutex);

	err = pthread_mutex_lock(&mutex);
	if (err != EDEADLK) {
		fprintf(stderr, "errorcheck mutex_lock 2: %s\n",
			strerror(err));
		exit(EXIT_FAILURE);
	}

	dispatch("errorcheck thread_create", THREAD_CREATE, 1, &waiter_tid, 2,
		 waiter, &mutex);
	ms_sleep(10);
	dispatch("errorcheck mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
	yield();
	err = pthread_mutex_unlock(&mutex);
	if (err != EPERM) {
		fprintf(stderr, "errorcheck mutex_unlock 2: %s\n",
			strerror(err));
		exit(EXIT_FAILURE);
	}

	start = rt_timer_tsc();
	dispatch("errorcheck mutex_lock 3", MUTEX_LOCK, 1, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	dispatch("errorcheck mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
	dispatch("errorcheck mutex_destroy", MUTEX_DESTROY, 1, &mutex);
#endif /* __POSIX_SKIN__ */
}

void mode_switch(void)
{
	mutex_t mutex;

	fprintf(stderr, "mode_switch\n");

	dispatch("switch mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);

	check_current_mode(0);

	dispatch("switch mutex_lock", MUTEX_LOCK, 1, &mutex);

	check_current_mode(1);

	dispatch("switch mutex_unlock", MUTEX_UNLOCK, 1, &mutex);
	dispatch("switch mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}

void pi_wait(void)
{
	unsigned long long start, diff;
	mutex_t mutex;
	thread_t waiter_tid;

	fprintf(stderr, "pi_wait\n");

	dispatch("pi mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);
	dispatch("pi mutex_lock 1", MUTEX_LOCK, 1, &mutex);

	check_current_prio(2);

	/* Give waiter a higher priority than main thread */
	dispatch("pi thread_create", THREAD_CREATE, 1, &waiter_tid, 3, waiter,
		 &mutex);
	ms_sleep(10);

	check_current_prio(3);

	dispatch("pi mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
	yield();

	check_current_prio(2);

	start = rt_timer_tsc();
	dispatch("pi mutex_lock 2", MUTEX_LOCK, 1, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	dispatch("pi mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
	dispatch("pi mutex_destroy", MUTEX_DESTROY, 1, &mutex);
}

void lock_stealing(void)
{
	mutex_t mutex;
	thread_t lowprio_tid;
	int trylock_result;

	/* Main thread acquires the mutex and starts a waiter with lower
	   priority. Then main thread releases the mutex, but locks it again
	   without giving the waiter a chance to get it beforehand. */

	fprintf(stderr, "lock_stealing\n");

	dispatch("lock_stealing mutex_init", MUTEX_CREATE, 1, &mutex, 1, 0);
	dispatch("lock_stealing mutex_lock 1", MUTEX_LOCK, 1, &mutex);

	/* Main thread should have higher priority */
	dispatch("lock_stealing thread_create 1", THREAD_CREATE, 1,
		 &lowprio_tid, 1, waiter, &mutex);

	/* Give lowprio thread 1 more ms to block on the mutex */
	ms_sleep(6);

	dispatch("lock_stealing mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);

	/* Try to stealing the lock from low prio task */
	trylock_result = dispatch("lock_stealing mutex_trylock",
				  MUTEX_TRYLOCK, 0, &mutex);
	if (trylock_result == 0) {
		ms_sleep(6);

		dispatch("lock_stealing mutex_unlock 2", MUTEX_UNLOCK, 1,
			 &mutex);

		/* Let waiter_lowprio a chance to run */
		ms_sleep(20);

		dispatch("lock_stealing mutex_lock 3", MUTEX_LOCK, 1, &mutex);

		/* Restart the waiter */
		dispatch("lock_stealing thread_create 2", THREAD_CREATE, 1,
			 &lowprio_tid, 1, waiter, &mutex);

		ms_sleep(6);

		dispatch("lock_stealing mutex_unlock 3", MUTEX_UNLOCK, 1, &mutex);
#ifdef __POSIX_SKIN__
	} else if (trylock_result != EBUSY) {
#else /* __NATIVE_SKIN__ */
	} else if (trylock_result != EWOULDBLOCK) {
#endif /* __NATIVE_SKIN__ */
		fprintf(stderr, "lock_stealing mutex_trylock: %i (%s)\n",
			trylock_result, strerror(trylock_result));
		exit(EXIT_FAILURE);
	}

	/* Stealing the lock (again) from low prio task */
	dispatch("lock_stealing mutex_lock 4", MUTEX_LOCK, 1, &mutex);

	ms_sleep(6);

	dispatch("lock_stealing mutex_unlock 4", MUTEX_UNLOCK, 1, &mutex);

	/* Let waiter_lowprio a chance to run */
	ms_sleep(20);

	dispatch("lock_stealing mutex_destroy", MUTEX_DESTROY, 1, &mutex);

	if (trylock_result != 0)
		fprintf(stderr,
			"lock_stealing mutex_trylock: not supported\n");
}

struct cond_mutex {
	mutex_t *mutex;
	cond_t *cond;
};

void *cond_signaler(void *cookie)
{
	struct cond_mutex *cm = (struct cond_mutex *) cookie;
	unsigned long long start, diff;

	dispatch("cond_signaler pthread_detach", THREAD_DETACH, 1);

	start = rt_timer_tsc();
	dispatch("cond_signaler mutex_lock 1", MUTEX_LOCK, 1, cm->mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);

	if (diff < 10000000) {
		fprintf(stderr,
			"cond_signaler, mutex_lock waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	ms_sleep(10);
	dispatch("cond_signaler cond_signal", COND_SIGNAL, 1, cm->cond);
	dispatch("cond_signaler mutex_unlock 2", MUTEX_UNLOCK, 1, cm->mutex);
	yield();

	start = rt_timer_tsc();
	dispatch("cond_signaler mutex_lock 2", MUTEX_LOCK, 1, cm->mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr,
			"cond_signaler, mutex_lock 2 waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	dispatch("cond_signaler mutex_unlock 2", MUTEX_UNLOCK, 1, cm->mutex);

	return cookie;
}

void simple_condwait(void)
{
	unsigned long long start, diff;
	mutex_t mutex;
	cond_t cond;
	struct cond_mutex cm = {
		.mutex = &mutex,
		.cond = &cond,
	};
	thread_t cond_signaler_tid;

	fprintf(stderr, "simple_condwait\n");

	dispatch("simple_condwait mutex_init", MUTEX_CREATE, 1, &mutex);
	dispatch("simple_condwait cond_init", COND_CREATE, 1, &cond);
	dispatch("simple_condwait mutex_lock", MUTEX_LOCK, 1, &mutex);
	dispatch("simple_condwait thread_create", THREAD_CREATE, 1,
		 &cond_signaler_tid, 2, cond_signaler, &cm);

	ms_sleep(11);
	start = rt_timer_tsc();
	dispatch("simple_condwait cond_wait", COND_WAIT, 1, &cond, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	ms_sleep(10);
	dispatch("simple_condwait mutex_unlock", MUTEX_UNLOCK, 1, &mutex);
	yield();

	dispatch("simple_condwait mutex_destroy", MUTEX_DESTROY, 1, &mutex);
	dispatch("simple_condwait cond_destroy", COND_DESTROY, 1, &cond);
}

void recursive_condwait(void)
{
	unsigned long long start, diff;
	mutex_t mutex;
	cond_t cond;
	struct cond_mutex cm = {
		.mutex = &mutex,
		.cond = &cond,
	};
	thread_t cond_signaler_tid;

	fprintf(stderr, "recursive_condwait\n");

	dispatch("rec_condwait mutex_init", MUTEX_CREATE, 1, &mutex, 0,
		 PTHREAD_MUTEX_RECURSIVE);
	dispatch("rec_condwait cond_init", COND_CREATE, 1, &cond);
	dispatch("rec_condwait mutex_lock 1", MUTEX_LOCK, 1, &mutex);
	dispatch("rec_condwait mutex_lock 2", MUTEX_LOCK, 1, &mutex);
	dispatch("rec_condwait thread_create", THREAD_CREATE, 1,
		 &cond_signaler_tid, 2, cond_signaler, &cm);

	ms_sleep(10);
	start = rt_timer_tsc();
	dispatch("rec_condwait cond_wait", COND_WAIT, 1, &cond, &mutex);
	diff = rt_timer_tsc2ns(rt_timer_tsc() - start);
	if (diff < 10000000) {
		fprintf(stderr, "main, waited %Ld.%03u us\n",
			diff / 1000, (unsigned) (diff % 1000));
		exit(EXIT_FAILURE);
	}
	dispatch("rec_condwait mutex_unlock 1", MUTEX_UNLOCK, 1, &mutex);
	ms_sleep(10);
	dispatch("rec_condwait mutex_unlock 2", MUTEX_UNLOCK, 1, &mutex);
	yield();

	dispatch("rec_condwait mutex_destroy", MUTEX_DESTROY, 1, &mutex);
	dispatch("rec_condwait cond_destroy", COND_DESTROY, 1, &cond);
}

int main(void)
{
#ifdef __POSIX_SKIN__
	struct sched_param sparam;
#else /* __NATIVE_SKIN__ */
	RT_TASK main_tid;
#endif /* __NATIVE_SKIN__ */

	mlockall(MCL_CURRENT | MCL_FUTURE);

	/* Set scheduling parameters for the current process */
#ifdef __POSIX_SKIN__
	sparam.sched_priority = 2;
	sched_setscheduler(0, SCHED_FIFO, &sparam);
#else /* __NATIVE_SKIN__ */
	rt_task_shadow(&main_tid, "main_task", 2, 0);
#endif /* __NATIVE_SKIN__ */

	/* Call test routines */
	simple_wait();
	recursive_wait();
	errorcheck_wait();
	mode_switch();
	pi_wait();
	lock_stealing();
	simple_condwait();
	recursive_condwait();
	fprintf(stderr, "Test OK\n");
	return 0;
}
_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to