Skip to content

Instantly share code, notes, and snippets.

@joaomlneto
Created February 12, 2019 16:14
Show Gist options
  • Save joaomlneto/4a52bbdada5a93d092963ef1cf857616 to your computer and use it in GitHub Desktop.
Save joaomlneto/4a52bbdada5a93d092963ef1cf857616 to your computer and use it in GitHub Desktop.
linux signals benchmarking
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <ucontext.h>
#include <fcntl.h>
#include <execinfo.h>
#include <sys/mman.h>
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
#define PAGE_MASK (PAGE_SIZE - 1)
#define PAGE_ALIGN_DOWN(x) (((intptr_t) (x)) & ~PAGE_MASK)
#define N (PAGE_SIZE/sizeof(uint64_t))
#define NTIMES 1ULL<<22
static uint64_t remaining;
void initialize(uint64_t *a, size_t size) {
printf("initializing... ");
fflush(stdout);
clock_t start = clock();
a[0] = 123;
for (size_t i=1; i < size; i++) {
a[i] = a[i-1] * a[i-1] % 100000;
}
clock_t end = clock();
double seconds = (double)(end - start) / CLOCKS_PER_SEC;
printf("done in %lf seconds\n", seconds);
}
void segv_handler(int signum, siginfo_t *siginfo, void *ctx) {
if (--remaining == 0) {
mprotect((void*) PAGE_ALIGN_DOWN(siginfo->si_addr),
PAGE_SIZE, PROT_READ | PROT_WRITE);
}
}
void install_sighandler() {
stack_t sigstk;
sigstk.ss_sp = malloc(SIGSTKSZ);
sigstk.ss_size = SIGSTKSZ;
sigstk.ss_flags = 0;
sigaltstack(&sigstk, NULL);
struct sigaction siga;
sigemptyset(&siga.sa_mask);
sigaddset(&siga.sa_mask, SIGSEGV);
// block signals temporarily
sigprocmask(SIG_BLOCK, &siga.sa_mask, NULL);
siga.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART | SA_NODEFER;
// install segv handler
siga.sa_sigaction = segv_handler;
if (sigaction(SIGSEGV, &siga, NULL) == -1) {
fprintf(stderr, "error installing sigsegv handler\n");
exit(-1);
}
sigprocmask(SIG_UNBLOCK, &siga.sa_mask, NULL);
}
void time_signals(uint64_t *a, size_t size, size_t ntimes) {
remaining = ntimes;
mprotect(a, PAGE_SIZE, PROT_READ);
clock_t start = clock();
a[1] = a[2] + a[3];
clock_t end = clock();
double seconds = (double)(end - start) / CLOCKS_PER_SEC;
printf("%zu signals -> %lf seconds\n", ntimes, seconds);
}
int main() {
uint64_t *a = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
install_sighandler();
initialize(a, N);
for (int i=1; i <= NTIMES; i *= 2) {
time_signals(a, 100, i);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment