Skip to content

Instantly share code, notes, and snippets.

@mmalone
Created January 30, 2011 04:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mmalone/14585329e013d1bf5134 to your computer and use it in GitHub Desktop.
Save mmalone/14585329e013d1bf5134 to your computer and use it in GitHub Desktop.
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <fcntl.h>
#include <string.h>
#define CLOCKID CLOCK_PROCESS_CPUTIME_ID
#define SIG SIGRTMIN
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
/* This function is intended to rack up both user and system time. */
static void * chew_cpu (void *arg) {
while (1) {
static volatile char buf[4096];
for (int i = 0; i < 100; ++i) {
for (size_t j = 0; j < sizeof buf; ++j) {
buf[j] = 0xaa;
}
}
int nullfd = open("/dev/null", O_WRONLY);
for(int i = 0; i < 100; ++i) {
for (size_t j = 0; j < sizeof buf; ++j) {
buf[j] = 0xbb;
}
}
write(nullfd, (char *) buf, sizeof buf);
close(nullfd);
}
return NULL;
}
int count = 0;
int failures = 0;
long long freq_nanosecs;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void sig_handler(int sig, siginfo_t *si, void *ctx) {
pthread_mutex_lock(&lock);
++count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
void maketimer() {
timer_t timerid;
sigset_t mask;
struct sigevent sev;
struct itimerspec its;
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sig_handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
errExit("sigaction");
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
long int result;
while (result = timer_create(CLOCKID, &sev, &timerid) == -1) {
failures++;
struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
nanosleep(&ts, NULL);
}
/* Start the timer */
its.it_value.tv_sec = freq_nanosecs / 1000000000;
its.it_value.tv_nsec = freq_nanosecs % 1000000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime(timerid, 0, &its, NULL) == -1)
errExit("timer_settime");
}
int main(int argc, char *argv[]) {
long long wait_count;
if (argc != 4) {
fprintf(stderr, "Usage: %s <sleep-secs> <freq-nanosecs> <wait-count>\n", argv[0]);
exit(EXIT_FAILURE);
}
wait_count = atoll(argv[3]);
freq_nanosecs = atoll(argv[2]);
/* Spin up a core so we have some work going on */
printf("Busying the processor with some stuff.\n");
for (int i = 0; i < 32; i++) {
pthread_t th;
int e = pthread_create(&th, NULL, chew_cpu, NULL);
if (e != 0) {
printf("pthread_create: %s\n", strerror(e));
exit (1);
}
}
for (int i = 0; i < 10; i++) {
maketimer();
}
time_t start = time(NULL);
while (count < wait_count) {
if (time(NULL) > (start + atoi(argv[1]))) {
printf("Count is %d, failures %d, sleeping for %ds\n", count, failures, atoi(argv[1]));
start = time(NULL);
}
struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
nanosleep(&ts, NULL);
}
printf("All done, count is %d\n", count);
exit(EXIT_SUCCESS);
}
@mdavid
Copy link

mdavid commented Jan 11, 2012

compile with:

gcc -o stresscputest gistfile1.txt -lpthread -std=gnu99 -lrt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment