[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-smp
Subject:    sharing CPU time between threads in real time
From:       Michal Szymanski <msz () astrouw ! edu ! pl>
Date:       2001-04-20 7:02:17
[Download RAW message or body]

Hi,

This is not a strict SMP problem, as the application I'm working on will
be run on a single-CPU machine. Nevertheless, it involves multiple
threading so I hope it is SMP-close enough to dare bothering you guys :)

I'm having problems with getting the two threads share the CPU time. In
the short program (included below), I set the scheduling policy of the
parent thread to SCHED_RR with priority of 10. Then a child thread is
created with optionally inherited scheduling policy parameters. For the
time being, the threads are not doing anything particularly
sofisticated, but it is just a test. Both threads increment their
specific counters, so I can examine, to some extent, whether and how the
CPU time was shared between them.

The effect is following:

1. when run the program without root priviledges, the scheduling setting
calls fail (of course) and the two threads share the CPU time in a
"normal" way - 'nc' grows up to MAX, 'nf' contains some big number at
exit. As expected.

With root priviledges, I get:

2. when the created child thread does not inherit scheduling policy
from the parent (thus getting default SCHED_OTHER - non-RT policy),
only the main thread is executing until alarm signal is delivered.
This is also expected behaviour.

3. when the created child thread *does* inherit scheduling policy
(by running the command with any command line argument),
I always get "nc=MAX nf=0 flag=1" final output. This means that
although in principle both parent and child threads have the same
round-robin scheduling policy and both "while" loops attempt
to yield CPU after every loop execution (sched_yield()), it does not work
- the child thread does the whole while loop in just one time slice.
Only when I make MAX much bigger, a single time slice is not enough
to perform the whole loop and I get nonzero "nf" counter.
Apart from "sched_yield()" apparently not working, it is strange
because, according to what sched_rr_get_interval() routine returns,
the time slice for SCHED_RR round-robin policy, the time slice
is 150 microseconds. And the total execution time of the program
is 0.2 seconds user time, so it seems that the two threads should
have been given many short time slices.

Is there any way to yield CPU between such threads effectively? 

The best thing that I'd like to do would be (in the future real
application) to make the parent thread sleep after doing its job in
every loop, thus letting the child thread work. The problem is that the
parent thread will have to check some external device status about every
20ms. This, unfortunately, is just about the lower limit on the time one
can "sleep" in Linux (10ms clock tick plus up to another 10ms of
unpredictable delay). I know that RT apps can nanosleep up to 2ms with
microsecond accuracy, but this is done with so called busy-waits which
apparently do not free the CPU resources, so they are hardly useful for
me.

Is there a way the RT thread can yield the CPU resources for, say, 5 or 10ms
(but not as much as 20ms)?

any hints will be appreciated,

regards, Michal.

-- 
  Michal Szymanski (msz@astrouw.edu.pl)
  Warsaw University Observatory, Warszawa, POLAND

-----------------------------------------------------------------

/*
** test threads in real time
*/
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <sys/types.h>
#include <asm/timex.h>
#include <asm/bitops.h>
#include <signal.h>

#define MAX 1000000

void en(int *);
void to(int *);

int       r1=0;
int       r2=0;
pthread_t  t1, t2;
int flag=0, nc=0, nf=0;
unsigned long long cpuclock[MAX];

void sigalarm(int sig)
{
  printf("%d %d %d\n", nc, nf, flag);
  exit(1);
}

main (int argc, char *argv[])
{
  struct sched_param sp;
  pthread_attr_t attr;
  int inherit=0;

  if ( argc > 1 ) inherit=1;
  sp.sched_priority = 10;
  pthread_setschedparam(pthread_self(), SCHED_RR, &sp);
  signal(SIGALRM, sigalarm);
  alarm(10);
  pthread_attr_init(&attr);
  if ( inherit ) pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
  pthread_create(&t1, &attr, (void *)en, (void *) &r1);
  to(NULL);
  pthread_join(t1, NULL);
  printf("%d %d %d\n", nc, nf, flag);
}

void en(int *foo)
{
  unsigned long eax, edx;

  while ( nc < MAX ) {
    rdtsc(eax,edx);
    cpuclock[nc] = ((unsigned long long)(edx) << 32) + eax;
    ++nc;
    sched_yield();
  }
  set_bit(0, &flag);
  pthread_exit(NULL);
}

void to(int *foo) {
  while ( !flag ) {
    ++nf;
    sched_yield();
  }
}
-
To unsubscribe from this list: send the line "unsubscribe linux-smp" in
the body of a message to majordomo@vger.kernel.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic