From: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>
To: Jan Kiszka <jan.kiszka@domain.hid>
Cc: xenomai-core <xenomai@xenomai.org>
Subject: Re: [Xenomai-core] Fast userspace locks for native skin
Date: Thu, 21 Aug 2008 21:53:40 +0200 [thread overview]
Message-ID: <48ADC7C4.8040902@domain.hid> (raw)
In-Reply-To: <48ADC493.7000009@domain.hid>
[-- Attachment #1: Type: text/plain, Size: 1962 bytes --]
Jan Kiszka wrote:
> Gilles Chanteperdrix wrote:
>> Gilles Chanteperdrix wrote:
>>> Jan Kiszka wrote:
>>>> Hi Gilles,
>>>>
>>>> do you - or anyone else - happen to have some patches under preparation
>>>> to extend also the native skin with the newly added CONFIG_XENO_FASTSEM
>>>> support? Just to avoid duplicate work (we are about to work on this).
>>> Not yet. But the fastsem work is largely unfinished in other areas: for
>>> instance, semaphores are not implemented yet.
>> neither is x86_64 support, which is a shame...
>>
>
> Uhh, that's bad. But I guess we are just lacking the required atomic ops
> here, aren't we?
Yes. And with a little luck, these will probably be a cut-n-past of the
x86_32. At the time I started doing this, I had no access to an x86_64,
and since I have an x86_64 at hand, I had no time to implement it.
>
> What about pthread_cond_*?
Well, nothing can be gained for pthread_cond_wait since it will suspend,
so needs a call to kernel. pthread_cond_signal needs a scheduler
decision (we could store the first pending thread priority in a
user/kernel shared area, with the complication that we would need
updating this priority if it ever changes, but to get the priority of
the current thread, we also need a syscall, moreover switching to
secondary mode).
>
> And do we have test cases for the support in the posix skin? Or did
> anyone look at the stuff LTP is doing for realtime testing? I guess that
> should be reusable (hmm, with some search&replace also for native...).
I have a small test, attached to this mail. It does not test XNROBBED.
About LTP, a long time ago, I started running the open posix testsuite
with Xenomai, the recurring problem I had was that this testsuite
assumes that the SCHED_OTHER policy means time sharing, so uses the CPU
in endless loops. Needless to say that it systematically caused lockups
with Xenomai (we had not SCHED_OTHER support in Xenomai at that time).
--
Gilles.
[-- Attachment #2: unit_mutex.c --]
[-- Type: text/x-csrc, Size: 11789 bytes --]
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <native/timer.h>
#include <posix/syscall.h>
extern unsigned __pse51_muxid;
#ifdef __pse51_get_current_prio
unsigned get_current_prio(void)
{
unsigned prio;
XENOMAI_SKINCALL1(__pse51_muxid, __pse51_get_current_prio, &prio);
return prio;
}
#endif
int check(const char *service, int status, int err)
{
if (status >= 0)
return 0;
fprintf(stderr, "%s: %s\n", service, strerror(err));
exit(EXIT_FAILURE);
}
#define check_pthread(service, status) \
({ \
int _status = (status); \
check((service), -_status, _status); \
})
#define check_unix(service, status) check((service), (status), errno)
void *waiter(void *cookie)
{
pthread_mutex_t *mutex = (pthread_mutex_t *) cookie;
unsigned long long start, diff;
check_pthread("pthread_detach", pthread_detach(pthread_self()));
start = rt_timer_tsc();
check_pthread("waiter mutex_lock", pthread_mutex_lock(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);
}
usleep(10000);
check_pthread("waiter mutex_unlock", pthread_mutex_unlock(mutex));
return cookie;
}
void simple_wait(void)
{
unsigned long long start, diff;
pthread_mutex_t mutex;
pthread_t waiter_tid;
fprintf(stderr, "simple_wait\n");
check_pthread("simple mutex_init", pthread_mutex_init(&mutex, NULL));
check_pthread("simple mutex_lock 1", pthread_mutex_lock(&mutex));
check_pthread("simple thread_create",
pthread_create(&waiter_tid, NULL, waiter, &mutex));
usleep(10000);
check_pthread("simple mutex_unlock 1", pthread_mutex_unlock(&mutex));
sched_yield();
start = rt_timer_tsc();
check_pthread("simple mutex_lock 2", pthread_mutex_lock(&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);
}
check_pthread("simple mutex_unlock 2", pthread_mutex_unlock(&mutex));
check_pthread("simple mutex_destroy", pthread_mutex_destroy(&mutex));
}
void recursive_wait(void)
{
unsigned long long start, diff;
pthread_mutexattr_t mattr;
pthread_mutex_t mutex;
pthread_t waiter_tid;
fprintf(stderr, "recursive_wait\n");
check_pthread("rec mutexattr_init", pthread_mutexattr_init(&mattr));
check_pthread("rec mutexattr_settype",
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
check_pthread("rec mutex_init", pthread_mutex_init(&mutex, &mattr));
check_pthread("rec mutexattr_destroy", pthread_mutexattr_destroy(&mattr));
check_pthread("rec mutex_lock 1", pthread_mutex_lock(&mutex));
check_pthread("rec mutex_lock 2", pthread_mutex_lock(&mutex));
check_pthread("rec thread_create",
pthread_create(&waiter_tid, NULL, waiter, &mutex));
check_pthread("rec mutex_unlock 2", pthread_mutex_unlock(&mutex));
usleep(10000);
check_pthread("rec mutex_unlock 1", pthread_mutex_unlock(&mutex));
sched_yield();
start = rt_timer_tsc();
check_pthread("rec mutex_lock 3", pthread_mutex_lock(&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);
}
check_pthread("rec mutex_unlock 3", pthread_mutex_unlock(&mutex));
check_pthread("rec mutex_destroy", pthread_mutex_destroy(&mutex));
}
void errorcheck_wait(void)
{
unsigned long long start, diff;
pthread_mutexattr_t mattr;
pthread_mutex_t mutex;
pthread_t waiter_tid;
int err;
fprintf(stderr, "errorcheck_wait\n");
check_pthread("errorcheck mutexattr_init",
pthread_mutexattr_init(&mattr));
check_pthread("errorcheck mutexattr_settype",
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK));
check_pthread("errorcheck mutex_init", pthread_mutex_init(&mutex, &mattr));
check_pthread("errorcheck mutexattr_destroy", pthread_mutexattr_destroy(&mattr));
check_pthread("errorcheck mutex_lock 1", pthread_mutex_lock(&mutex));
err = pthread_mutex_lock(&mutex);
if (err != EDEADLK) {
fprintf(stderr, "errorcheck mutex_lock 2: %s\n", strerror(err));
exit(EXIT_FAILURE);
}
check_pthread("errorcheck thread_create",
pthread_create(&waiter_tid, NULL, waiter, &mutex));
usleep(10000);
check_pthread("errorcheck mutex_unlock 1", pthread_mutex_unlock(&mutex));
sched_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();
check_pthread("errorcheck mutex_lock 3", pthread_mutex_lock(&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);
}
check_pthread("errorcheck mutex_unlock 3", pthread_mutex_unlock(&mutex));
check_pthread("errorcheck mutex_destroy", pthread_mutex_destroy(&mutex));
}
void pi_wait(void)
{
unsigned long long start, diff;
pthread_attr_t waiter_attr;
struct sched_param sparam;
pthread_mutexattr_t mattr;
pthread_mutex_t mutex;
pthread_t waiter_tid;
fprintf(stderr, "pi_wait\n");
check_pthread("pi mutexattr_init",
pthread_mutexattr_init(&mattr));
check_pthread("pi mutexattr_settype",
pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT));
check_pthread("pi mutex_init", pthread_mutex_init(&mutex, &mattr));
check_pthread("pi mutexattr_destroy", pthread_mutexattr_destroy(&mattr));
check_pthread("pi mutex_lock 1", pthread_mutex_lock(&mutex));
check_pthread("pi pthread_attr_init", pthread_attr_init(&waiter_attr));
check_pthread("pi pthread_setinheritsched",
pthread_attr_setinheritsched(&waiter_attr,
PTHREAD_EXPLICIT_SCHED));
check_pthread("pi pthread_attr_setschedpolicy",
pthread_attr_setschedpolicy(&waiter_attr, SCHED_FIFO));
sparam.sched_priority = 45;
check_pthread("pi pthread_attr_setschedparam",
pthread_attr_setschedparam(&waiter_attr, &sparam));
#ifdef __pse51_get_current_prio
if (get_current_prio() != 0) {
fprintf(stderr, "pi: non null prio %d\n", get_current_prio());
exit(EXIT_FAILURE);
}
#endif
check_pthread("pi thread_create",
pthread_create(&waiter_tid, &waiter_attr, waiter, &mutex));
usleep(10000);
#ifdef __pse51_get_current_prio
if (get_current_prio() != 45) {
fprintf(stderr, "pi: prio %d != 45\n", get_current_prio());
exit(EXIT_FAILURE);
}
#endif
check_pthread("pi mutex_unlock 1", pthread_mutex_unlock(&mutex));
sched_yield();
#ifdef __pse51_get_current_prio
if (get_current_prio() != 0) {
fprintf(stderr, "pi: non null prio %d\n", get_current_prio());
exit(EXIT_FAILURE);
}
#endif
start = rt_timer_tsc();
check_pthread("pi mutex_lock 2", pthread_mutex_lock(&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);
}
check_pthread("pi mutex_unlock 2", pthread_mutex_unlock(&mutex));
check_pthread("pi mutex_destroy", pthread_mutex_destroy(&mutex));
}
struct cond_mutex {
pthread_mutex_t *mutex;
pthread_cond_t *cond;
};
void *cond_signaler(void *cookie)
{
struct cond_mutex *cm = (struct cond_mutex *) cookie;
unsigned long long start, diff;
check_pthread("pthread_detach", pthread_detach(pthread_self()));
start = rt_timer_tsc();
check_pthread("cond_signaler mutex_lock 1",
pthread_mutex_lock(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);
}
usleep(10000);
check_pthread("cond_signaler cond_signal",
pthread_cond_signal(cm->cond));
check_pthread("cond_signaler mutex_unlock 2",
pthread_mutex_unlock(cm->mutex));
sched_yield();
start = rt_timer_tsc();
check_pthread("cond_signaler mutex_lock 2",
pthread_mutex_lock(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);
}
check_pthread("cond_signaler mutex_unlock 2",
pthread_mutex_unlock(cm->mutex));
return cookie;
}
void simple_condwait(void)
{
unsigned long long start, diff;
pthread_mutex_t mutex;
pthread_cond_t cond;
struct cond_mutex cm = {
.mutex = &mutex,
.cond = &cond,
};
pthread_t cond_signaler_tid;
fprintf(stderr, "simple_condwait\n");
check_pthread("simple_condwait mutex_init",
pthread_mutex_init(&mutex, NULL));
check_pthread("simple_condwait cond_init",
pthread_cond_init(&cond, NULL));
check_pthread("simple_condwait mutex_lock 1",
pthread_mutex_lock(&mutex));
check_pthread("simple_condwait thread_create",
pthread_create(&cond_signaler_tid, NULL, cond_signaler, &cm));
usleep(10000);
start = rt_timer_tsc();
check_pthread("simple_condwait cond_wait 1",
pthread_cond_wait(&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);
}
usleep(10000);
check_pthread("simple_condwait mutex_unlock 1",
pthread_mutex_unlock(&mutex));
sched_yield();
check_pthread("simple_condwait mutex_destroy",
pthread_mutex_destroy(&mutex));
check_pthread("simple_condwait cond_destroy",
pthread_cond_destroy(&cond));
}
void recursive_condwait(void)
{
unsigned long long start, diff;
pthread_mutexattr_t mattr;
pthread_mutex_t mutex;
pthread_cond_t cond;
struct cond_mutex cm = {
.mutex = &mutex,
.cond = &cond,
};
pthread_t cond_signaler_tid;
fprintf(stderr, "recursive_condwait\n");
check_pthread("rec_condwait mutexattr_init",
pthread_mutexattr_init(&mattr));
check_pthread("rec_condwait mutexattr_settype",
pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
check_pthread("rec_condwait mutex_init",
pthread_mutex_init(&mutex, &mattr));
check_pthread("rec_condwait mutexattr_destroy",
pthread_mutexattr_destroy(&mattr));
check_pthread("rec_condwait cond_init",
pthread_cond_init(&cond, NULL));
check_pthread("rec_condwait mutex_lock 1",
pthread_mutex_lock(&mutex));
check_pthread("rec_condwait mutex_lock 2",
pthread_mutex_lock(&mutex));
check_pthread("rec_condwait thread_create",
pthread_create(&cond_signaler_tid, NULL, cond_signaler, &cm));
usleep(10000);
start = rt_timer_tsc();
check_pthread("rec_condwait cond_wait 1",
pthread_cond_wait(&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);
}
check_pthread("rec_condwait mutex_unlock 1",
pthread_mutex_unlock(&mutex));
usleep(10000);
check_pthread("rec_condwait mutex_unlock 2",
pthread_mutex_unlock(&mutex));
sched_yield();
check_pthread("rec_condwait mutex_destroy",
pthread_mutex_destroy(&mutex));
check_pthread("simple_condwait cond_destroy",
pthread_cond_destroy(&cond));
}
int main(void)
{
check_unix("mlockall", mlockall(MCL_CURRENT | MCL_FUTURE));
simple_wait();
recursive_wait();
errorcheck_wait();
pi_wait();
simple_condwait();
recursive_condwait();
fprintf(stderr, "Test OK\n");
return 0;
}
next prev parent reply other threads:[~2008-08-21 19:53 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-21 19:25 [Xenomai-core] Fast userspace locks for native skin Jan Kiszka
2008-08-21 19:29 ` Gilles Chanteperdrix
2008-08-21 19:36 ` Gilles Chanteperdrix
[not found] ` <48ADC493.7000009@domain.hid>
2008-08-21 19:53 ` Gilles Chanteperdrix [this message]
2008-08-22 9:18 ` Jan Kiszka
2008-08-22 9:21 ` Gilles Chanteperdrix
2008-08-22 10:33 ` Jan Kiszka
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=48ADC7C4.8040902@domain.hid \
--to=gilles.chanteperdrix@xenomai.org \
--cc=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.