QNX Neutrino includes some special CPU-time clocks that you can use to monitor the execution times for processes and threads.
This mechanism is implemented following the POSIX Execution Time Monitoring option, which defines special clock IDs that represent the execution time of a thread or a process:
To obtain: | Call: | Specifying: | Classification |
---|---|---|---|
A process CPU-time clock ID | clock_getcpuclockid() | A process ID, or 0 to get the clock ID for the calling process | POSIX |
A thread CPU-time clock ID | pthread_getcpuclockid() | A thread ID in the calling process | POSIX |
Either of the above | ClockId() | A process ID and a thread ID | QNX Neutrino |
A process has permission to get the CPU-time clock ID of any process.
To get the execution time for the process or thread, call clock_gettime() or ClockTime(), passing a process or thread CPU-time clock ID. POSIX also defines the following, which you can use instead of calling clock_getcpuclockid() or pthread_getcpuclockid():
In QNX Neutrino 7.0.1 or later, the OS calculates the execution times on every clock tick and whenever an active thread is preempted.
Here's an example:
int process_clock_id, ret; struct timespec process_time; ret = clock_getcpuclockid(0, &process_clock_id); if (ret != 0) { perror ("clock_getcpuid()"); return (EXIT_FAILURE); } printf ("Process clock ID: %d\n", process_clock_id); ret = clock_gettime (process_clock_id, &process_time); if (ret != 0) { perror ("clock_gettime()"); return (EXIT_FAILURE); } printf ("Process clock: %ld sec, %ld nsec\n", process_time.tv_sec, process_time.tv_nsec);
Given that we're getting the execution time for the calling process, we could use CLOCK_PROCESS_CPUTIME_ID instead of clock_getcpuclockid():
int process_clock_id, ret; struct timespec process_time; ret = clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &process_time); if (ret != 0) { perror ("clock_gettime()"); return (EXIT_FAILURE); } printf ("Process clock: %ld sec, %ld nsec\n", process_time.tv_sec, process_time.tv_nsec);
In QNX Neutrino 7.0.1 or later, you can arrange to be notified when a thread uses more than a given amount of CPU time. You can't currently do this for a process.
Setting up this type of notification involves creating a timer with a thread CPU-time clock ID:
Here's an example:
struct sigevent event; timer_t timer_id; struct itimerspec cpu_usage; /* Set up the method of notification. */ SIGEV_SIGNAL_INIT(&event, SIGALRM); signal( SIGALRM, sig_handler ); /* Create a timer. */ if (timer_create(CLOCK_THREAD_CPUTIME_ID, &event, &timer_id)) { perror( "timer_create" ); return EXIT_FAILURE; } /* Set up the amount of CPU time and then set the timer. */ cpu_usage.it_value.tv_sec = 0; cpu_usage.it_value.tv_nsec = nsec; cpu_usage.it_interval.tv_sec = 0; cpu_usage.it_interval.tv_nsec = period_nsec; if (timer_settime(timer_id, 0, &cpu_usage, NULL)) { perror( "timer_settime" ); exit(EXIT_FAILURE); } /* If the thread exceeds the specified CPU time, we'll get a SIGALRM, and our sig_handler() function will be called. */
The accuracy of this mechanism depends on the clock period; if the thread exceeds the given execution time, the actual amount of time used is at least the amount you specified but less than the same amount plus the clock period.