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, &param);
    pthread_attr_setschedparam_rt(&thattr_sampler, &param);

    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;
}

Reply via email to