On Fri, Aug 20, 2004 at 01:16:37PM +0200, frogger wrote:
> Again with my HRT-Userspace Skin, aperiodic timer - using the modified
> fusion-demo example (see attached code).
Marc
--
<Dan> Not at all. "D'oh" is one of my favorite words.
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <rts.h>
#define WAIT_USEC 1000
#define COUNT 60000
static sem_rt_t semA, semB;
static xnsysinfo_t info;
struct rts_measure {
long long nano;
long long sem;
};
struct rts_measure *m;
static int end;
int count;
static inline long long __cputime (void)
{
long long t;
__asm__ __volatile__( "rdtsc" : "=A" (t));
return t;
}
static inline long long __count2ns (long long t)
{
return t * 1000000000 / info.cpufreq;
}
static void endme(int dummy)
{
end = 1;
}
void *poster_thread (void *arg)
{
sem_init_rt(&semA, 0, 0);
for (;;) {
sem_wait_rt(&semA);
sem_post_rt(&semB);
}
}
void *sampler_thread (void *arg)
{
long long minj1 = 10000000, maxj1 = 0, sumj1 = 0;
long long minj2 = 10000000, maxj2 = 0, sumj2 = 0;
long long t, t0, t1;
struct timespec ts;
int n;
sem_init_rt(&semB, 0, 0);
printf_rt("Demo thread now sampling at %d Hz...\n", 1000000 / WAIT_USEC);
for (n = count = 0; n < COUNT; n++) {
/* First, align on the next incoming tick. */
ts.tv_sec = 0;
ts.tv_nsec = 1000000;
nanosleep_rt(&ts,NULL);
/* Then, perform the measurement. */
ts.tv_nsec = WAIT_USEC * 1000;
t0 = __cputime();
nanosleep_rt(&ts,NULL);
t1 = __cputime();
t = t1 - t0;
if (t > maxj1) maxj1 = t;
if (t < minj1) minj1 = t;
sumj1 += t;
(m+n)->nano = __count2ns(t) - WAIT_USEC * 1000;
/* Handshake with Bob. */
sem_post_rt(&semA);
t0 = __cputime();
sem_wait_rt(&semB);
t1 = __cputime();
t = t1 - t0;
if (t > maxj2) maxj2 = t;
if (t < minj2) minj2 = t;
sumj2 += t;
(m+n)->sem = __count2ns(t);
count++;
}
printf_rt("%d samples:\n",count);
printf_rt("nanosleep jitter: min = %lld ns, max = %lld ns, avg = %lld ns\n",
__count2ns(minj1) - WAIT_USEC * 1000,
__count2ns(maxj1) - WAIT_USEC * 1000,
__count2ns(sumj1 / count) - WAIT_USEC * 1000);
printf_rt("sema4 handshake: min = %lld ns, max = %lld ns, avg = %lld ns\n",
__count2ns(minj2),
__count2ns(maxj2),
__count2ns(sumj2 / count));
return NULL;
}
int main (int ac, char **av)
{
pthread_rt_t sampler_thid, poster_thid;
struct sched_param_rt param;
pthread_attr_rt_t thattr_poster, thattr_sampler;
size_t stacksize = PTHREAD_STACK_MIN_RT;
void *stack_poster, *stack_sampler;
FILE *dout;
int i;
signal(SIGINT, endme);
pthread_info_rt(&info);
stack_poster = malloc(stacksize);
stack_sampler = malloc(stacksize);
m = malloc(sizeof(struct rts_measure) * COUNT);
if (NULL == stack_poster) {
exit(EXIT_FAILURE);
}
if (NULL == stack_sampler) {
free(stack_poster);
exit(EXIT_FAILURE);
}
pthread_attr_init_rt(&thattr_poster);
pthread_attr_init_rt(&thattr_sampler);
pthread_attr_setdetachstate_rt(&thattr_poster, PTHREAD_CREATE_DETACHED_RT);
pthread_attr_setdetachstate_rt(&thattr_sampler, PTHREAD_CREATE_DETACHED_RT);
pthread_attr_setstack_rt(&thattr_poster, stack_poster, stacksize);
pthread_attr_setstack_rt(&thattr_sampler, stack_sampler, stacksize);
pthread_attr_setschedpolicy_rt(&thattr_poster, SCHED_FIFO_RT);
pthread_attr_setschedpolicy_rt(&thattr_sampler, SCHED_FIFO_RT);
param.sched_priority = 10;
pthread_attr_setschedparam_rt(&thattr_poster, ¶m);
pthread_attr_setschedparam_rt(&thattr_sampler, ¶m);
pthread_create_rt(&poster_thid, &thattr_poster, &poster_thread, NULL);
pthread_create_rt(&sampler_thid, &thattr_sampler, &sampler_thread, NULL);
while (!end) {
printf("%d\n", count);
sleep(1);
}
dout = fopen("./data.txt", "w");
for (i = 0; i < COUNT; i++) {
fprintf(dout, "%lld\t%lld\n", (m+i)->nano, (m+i)->sem);
}
fclose(dout);
return 0;
}