|
Home > Archive > Unix Programming > August 2005 > kernel timer
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| martinm69x@hotmail.com 2005-08-23, 9:02 pm |
| Hey all,
I've been working on the code for a kernel timer which will report real
time, CPU time, user time and kernel time on the operation of fibonacci
method.
The way im doing it is keeping track of the parent and two child times
(using fork()).
I can get parent times to come up, however i do not think they are
correct, and i can not get child times to come up at all. I think in
the signal handler methods i have to somehow restart the timer or
signal, but i am not entirely sure how to.
All the code is below, can someone please assist me. Don't worry about
the delta_time method.
Thanks in advance for any help.
Michael M
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
long unsigned int fibonacci(unsigned int n);
long unsigned int elapsed_usecs(long, long);
long unsigned int delta_time(struct itimerval, struct itimerval);
void p_handler(int);
void c1_handler(int);
void c2_handler(int);
/* These variables are used to record the accumulated times. They
are set by the signal handlers and read by the processes when
they report the results */
static long p_realt_secs = 0, c1_realt_secs = 0, c2_realt_secs = 0;
static long p_virtt_secs = 0, c1_virtt_secs = 0, c2_virtt_secs = 0;
static long p_proft_secs = 0, c1_proft_secs = 0, c2_proft_secs = 0;
static struct itimerval p_realt, c1_realt, c2_realt;
static struct itimerval p_virtt, c1_virtt, c2_virtt;
static struct itimerval p_proft, c1_proft, c2_proft;
main(int argc, char **argv) {
long unsigned fib = 0;
int pid1, pid2;
unsigned int fibarg;
int status;
// Get command line argument, fibarg (N)
if(argc != 2) {
printf("usage: $./a.out <number>\n");
exit(EXIT_FAILURE);
}
fibarg = (int)strtoul(argv[1], NULL, 10);
printf("Fib is: %u\n", fibarg);
// Initialize parent, child1 and child2 timer values
p_realt.it_interval.tv_sec = 1; //change
p_realt.it_interval.tv_usec = 0; // change
p_realt.it_value.tv_sec = 1; // change
p_realt.it_value.tv_usec = 0; // change
c1_realt.it_interval.tv_sec = 0; //change
c1_realt.it_interval.tv_usec = 0; // change
c1_realt.it_value.tv_sec = 0; // change
c1_realt.it_value.tv_usec = 0; // change
c2_realt.it_interval.tv_sec = 0; //change
c2_realt.it_interval.tv_usec = 0; // change
c2_realt.it_value.tv_sec = 0; // change
c2_realt.it_value.tv_usec = 0; // change
p_virtt.it_interval.tv_sec = 1; //change
p_virtt.it_interval.tv_usec = 0; // change
p_virtt.it_value.tv_sec = 1; // change
p_virtt.it_value.tv_usec = 0; // change
c1_virtt.it_interval.tv_sec = 0; //change
c1_virtt.it_interval.tv_usec = 0; // change
c1_virtt.it_value.tv_sec = 0; // change
c1_virtt.it_value.tv_usec = 0; // change
c2_virtt.it_interval.tv_sec = 0; //change
c2_virtt.it_interval.tv_usec = 0; // change
c2_virtt.it_value.tv_sec = 0; // change
c2_virtt.it_value.tv_usec = 0; // change
p_proft.it_interval.tv_sec = 1; //change
p_proft.it_interval.tv_usec = 0; // change
p_proft.it_value.tv_sec = 1; // change
p_proft.it_value.tv_usec = 0; // change
c1_proft.it_interval.tv_sec = 0; //change
c1_proft.it_interval.tv_usec = 0; // change
c1_proft.it_value.tv_sec = 0; // change
c1_proft.it_value.tv_usec = 0; // change
c2_proft.it_interval.tv_sec = 0; //change
c2_proft.it_interval.tv_usec = 0; // change
c2_proft.it_value.tv_sec = 0; // change
c2_proft.it_value.tv_usec = 0; // change
// Enable parents signal handlers
signal(SIGALRM, p_handler); // change to own signal handlers
signal(SIGVTALRM, p_handler); // change to own signal handlers
signal(SIGPROF, p_handler); // change to own signal handlers
// Set parents itimers
if(setitimer(ITIMER_REAL, &p_realt, NULL) == -1)
perror("parent real timer set error");
if(setitimer(ITIMER_VIRTUAL, &p_virtt, NULL) == -1)
perror("parent virtual timer set error");
if(setitimer(ITIMER_PROF, &p_proft, NULL) == -1)
perror("parent profile timer set error");
pid1 = fork();
if(pid1 == 0) {
// Enable child1 signal handlers (disable parent handlers)
signal(SIGALRM, c1_handler); // change to own signal handlers
signal(SIGVTALRM, c1_handler); // change to own signal
handlers
signal(SIGPROF, c1_handler);
// enable child1 signal handlers
// Set child1 itimers
if(setitimer(ITIMER_REAL, &c1_realt, NULL) == -1)
perror("child1 real timer set error");
if(setitimer(ITIMER_VIRTUAL, &c1_virtt, NULL) == -1)
perror("child1 virtual timer set error");
if(setitimer(ITIMER_PROF, &c1_proft, NULL) == -1)
perror("child1 profile timer set error");
// Start child1 itimer on the fibonacci program
fib = fibonacci(fibarg);
// Read child1 itimer values and report them
getitimer(ITIMER_PROF, &c1_proft);
getitimer(ITIMER_REAL, &c1_realt);
getitimer(ITIMER_VIRTUAL, &c1_virtt);
printf("\n");
printf("Child 1 fib = %ld, real time = %ld sec, %ld msec\n",
fib,
c1_realt_secs, elapsed_usecs(c1_realt.it_value.tv_sec,
c1_realt.it_value.tv_usec)/1000);
printf("Child 1 fib = %ld, cpu time = %ld sec, %ld msec\n",
fib,
c1_proft_secs, elapsed_usecs(c1_proft.it_value.tv_sec,
c1_proft.it_value.tv_usec)/1000);
printf("Child 1 fib = %ld, user time = %ld sec, %ld msec\n",
fib,
c1_virtt_secs, elapsed_usecs(c1_virtt.it_value.tv_sec,
c1_virtt.it_value.tv_usec)/1000);
printf("Child 1 fib = %ld, kernel time = %ld sec, %ld msec\n",
fib,
delta_time(c1_proft, c1_virtt),
(elapsed_usecs(c1_proft.it_value.tv_sec,
c1_proft.it_value.tv_usec)/1000) -
(elapsed_usecs(c1_virtt.it_value.tv_sec,
c1_virtt.it_value.tv_usec)
/1000));
fflush(stdout);
exit(0);
} else {
pid2 = fork();
if(pid2 == 0) {
// Enable child2 signal handlers
signal(SIGALRM, c2_handler); // change to own signal
handlers
signal(SIGVTALRM, c2_handler); // change to own signal
handlers
signal(SIGPROF, c2_handler);
// Set child2 itimers
if(setitimer(ITIMER_REAL, &c2_realt, NULL) == -1)
perror("child 2 real timer set error");
if(setitimer(ITIMER_VIRTUAL, &c2_virtt, NULL) == -1)
perror("child 2 virtual timer set error");
if(setitimer(ITIMER_PROF, &c2_proft, NULL) == -1)
perror("child 2 profile timer set error");
// Start child2 on the fibonacci program
fib = fibonacci(fibarg);
// Read child2 itimer vlues and report them
getitimer(ITIMER_PROF, &c2_proft);
getitimer(ITIMER_REAL, &c2_realt);
getitimer(ITIMER_VIRTUAL, &c2_virtt);
printf("\n");
printf("Child 2 fib = %ld, real time = %ld sec, %ld
msec\n", fib,
c2_realt_secs, elapsed_usecs(c2_realt.it_value.tv_sec,
c2_realt.it_value.tv_usec)/1000);
printf("Child 2 fib = %ld, cpu time = %ld sec, %ld
msec\n", fib,
c2_proft_secs, elapsed_usecs(c2_proft.it_value.tv_sec,
c2_proft.it_value.tv_usec)/1000);
printf("Child 2 fib = %ld, user time = %ld sec, %ld
msec\n", fib,
c2_virtt_secs, elapsed_usecs(c2_virtt.it_value.tv_sec,
c2_virtt.it_value.tv_usec)/1000);
printf("Child 2 fib = %ld, kernel time = %ld sec, %ld
msec\n",
fib,
delta_time(c2_proft, c2_virtt),
(elapsed_usecs(c2_proft.it_value.tv_sec,
c2_proft.it_value.tv_usec)/1000) -
(elapsed_usecs(c2_virtt.it_value.tv_sec,
c2_virtt.it_value.tv_usec)
/1000));
fflush(stdout);
exit(0);
} else { /* this is the parent */
// Start parent on the fibonacci program
fib = fibonacci(fibarg);
// Wait for children to terminate
waitpid(0, &status, 0);
waitpid(0, &status, 0);
// Read parent itimer values and report them
getitimer(ITIMER_PROF, &p_proft);
getitimer(ITIMER_REAL, &p_realt);
getitimer(ITIMER_VIRTUAL, &p_virtt);
printf("\n");
printf("Parent fib = %ld, real time = %ld sec, %ld msec\n",
fib,
p_realt_secs, elapsed_usecs(p_realt.it_value.tv_sec,
p_realt.it_value.tv_usec)/1000);
printf("Parent fib = %ld, cpu time = %ld sec, %ld msec\n",
fib,
p_proft_secs, elapsed_usecs(p_proft.it_value.tv_sec,
p_proft.it_value.tv_usec)/1000);
printf("Parent fib = %ld, user time = %ld sec, %ld msec\n",
fib,
p_virtt_secs, elapsed_usecs(p_virtt.it_value.tv_sec,
p_virtt.it_value.tv_usec)/1000);
printf("Parent fib = %ld, kernel time = %ld sec, %ld
msec\n", fib,
delta_time(p_proft, p_virtt),
(elapsed_usecs(p_proft.it_value.tv_sec,
p_proft.it_value.tv_usec)/1000) -
(elapsed_usecs(p_virtt.it_value.tv_sec,
p_virtt.it_value.tv_usec)
/1000));
fflush(stdout);
exit(0);
}
printf("this line should never be printed\n");
}
}
long unsigned int fibonacci(unsigned int n) {
if(n == 0)
return 0;
else if ( n == 1 || n == 2)
return 1;
else
return (fibonacci(n-1) + fibonacci(n-2));
}
long unsigned int elapsed_usecs(long sec, long usec)
{
return ((sec*1000000) + usec);
}
long unsigned int delta_time(struct itimerval n, struct itimerval m)
{
return m.it_value.tv_sec + n.it_value.tv_sec;
}
void p_handler(int signo)
{
switch(signo) {
case SIGALRM:
p_realt_secs++;
signal(SIGALRM, p_handler); // change to own signal
handlers
break;
case SIGVTALRM:
p_virtt_secs++;
signal(SIGVTALRM, p_handler); // change to own signal
handlers
break;
case SIGPROF:
p_proft_secs++;
signal(SIGPROF, p_handler);
break;
}
return;
}
void c1_handler(int signo)
{
switch(signo) {
case SIGALRM:
c1_realt_secs++;
signal(SIGALRM, c1_handler); // change to own signal
handlers
break;
case SIGVTALRM:
c1_virtt_secs++;
signal(SIGVTALRM, c1_handler); // change to own signal
handlers
break;
case SIGPROF:
c1_proft_secs++;
signal(SIGPROF, c1_handler);
break;
}
return;
}
void c2_handler(int signo)
{
switch(signo) {
case SIGALRM:
c2_realt_secs++;
break;
case SIGVTALRM:
c2_virtt_secs++;
break;
case SIGPROF:
c2_proft_secs++;
break;
}
return;
}
| |
| Maxim Yegorushkin 2005-08-24, 7:52 am |
|
martinm69x@hotmail.com wrote:
> Hey all,
>
> I've been working on the code for a kernel timer which will report real
> time, CPU time, user time and kernel time on the operation of fibonacci
> method.
>
> The way im doing it is keeping track of the parent and two child times
> (using fork()).
>
> I can get parent times to come up, however i do not think they are
> correct, and i can not get child times to come up at all. I think in
> the signal handler methods i have to somehow restart the timer or
> signal, but i am not entirely sure how to.
>
> All the code is below, can someone please assist me. Don't worry about
> the delta_time method.
I just skimmed through your code and noticed that you set the timers
before forking.
http://www.opengroup.org/onlinepubs...tions/fork.html
It says: Interval timers shall be reset in the child process.
| |
| martinm69x@hotmail.com 2005-08-24, 7:52 am |
| I set the child timers after forking, I dont think i have to do this
for parent timers as well, are you saying that once the parent signal
is caught, i have to reset them in both child processes?
| |
| Maxim Yegorushkin 2005-08-24, 7:52 am |
|
martinm69x@hotmail.com wrote:
> I set the child timers after forking, I dont think i have to do this
> for parent timers as well, are you saying that once the parent signal
> is caught, i have to reset them in both child processes?
Sorry, my answer was wrong.
| |
| Loic Domaigne 2005-08-24, 6:11 pm |
| Salut Michael,
> I've been working on the code for a kernel timer which will report real
> time, CPU time, user time and kernel time on the operation of fibonacci
> method.
what Do you mean by CPU time?
Usually the interesting time collection is: execution time, user CPU
time, kernel CPU time.
> The way im doing it is keeping track of the parent and two child times
> (using fork()).
Make it (much) simpler: have a look to the function times():
man 2 times
HTH,
Loic.
| |
| martinm69x@hotmail.com 2005-08-25, 8:52 pm |
| ITIMER_PROF reflects the passage of time during which the process is
active (virtual time/user time) plus the time that the kernel is doing
work on behlaf of the corresponding process for example executing a
system call. This is CPU time.
Thanks for the suggestion but i want to keep my solution structured as
it is. Anyone else know how i can fix my code, so that it works as its
meant to?
|
|
|
|
|