All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@domain.hid>
To: xenomai@xenomai.org
Subject: Re: [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more
Date: Fri, 17 Oct 2008 18:11:40 +0200	[thread overview]
Message-ID: <48F8B93C.7000908@domain.hid> (raw)
In-Reply-To: <20081017154559.420723261@domain.hid>

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

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

[-- Attachment #2: mutex-testbench.c --]
[-- Type: text/x-c++src, Size: 18149 bytes --]

/*
 * Functional testing of the mutex implementation for native & posix skins.
 *
 * Copyright (C) Gilles Chanteperdrix  <gilles.chanteperdrix@xenomai.org>,
 *               Marion Deveaud <marion.deveaud@domain.hid>,
 *               Jan Kiszka <jan.kiszka@domain.hid>
 *
 * 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;
}

  parent reply	other threads:[~2008-10-17 16:11 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-10-17 15:45 [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 01/13] Generic thread registration Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 02/13] Handle-based xeno_get_current service Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 03/13] Remove xnarch_atomic_intptr Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 04/13] Spread xeno_set_current under all skins Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 05/13] Factor out xnsynch_acquire/release Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 06/13] Refactor mutex lockcnt tracking Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 07/13] Lockless fast path for xnsynch_acquire/release Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 08/13] Convert POSIX skin to fast xnsynch Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 09/13] Use fast xnsynch with native skin Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 10/13] Optionally replace pthread_getspecific with TLS variables Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 11/13] Report current shadow thread mode to user space Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 12/13] Ensure mode switch in mutex fast paths Jan Kiszka
2008-10-17 15:46 ` [Xenomai-core] [PATCH 13/13] Catch inconsistent SMP feature support Jan Kiszka
2008-10-17 16:11 ` Jan Kiszka [this message]
2008-10-17 16:41 ` [Xenomai-core] [PATCH 00/13] Generic fast xnsynch support & more Gilles Chanteperdrix
2008-10-18 18:47 ` Gilles Chanteperdrix

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=48F8B93C.7000908@domain.hid \
    --to=jan.kiszka@domain.hid \
    --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.