Skip to content

Instantly share code, notes, and snippets.

@sjenning
Created December 20, 2016 15:43
Show Gist options
  • Save sjenning/c9ee2a8cc2164ad42a0d5e0414b72f2e to your computer and use it in GitHub Desktop.
Save sjenning/c9ee2a8cc2164ad42a0d5e0414b72f2e to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/eventfd.h>
#define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>"
int main(int argc, char **argv)
{
int efd = -1;
int cfd = -1;
int event_control = -1;
#define PATH_MAX 255
#define LINE_MAX 255
char event_control_path[PATH_MAX];
char line[LINE_MAX];
int ret;
int blksz_mbs = 20;
int allocated_mbs = 0;
#define MAXBLOCKS 300
char *blocks[MAXBLOCKS];
int index = 0;
char grow = 1;
int flags = 0;
if (argc != 3)
errx(1, "%s", USAGE_STR);
cfd = open(argv[1], O_RDONLY);
if (cfd == -1)
err(1, "Cannot open %s", argv[1]);
ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control",
dirname(argv[1]));
if (ret >= PATH_MAX)
errx(1, "Path to cgroup.event_control is too long");
event_control = open(event_control_path, O_WRONLY);
if (event_control == -1)
err(1, "Cannot open %s", event_control_path);
efd = eventfd(0, 0);
if (efd == -1)
err(1, "eventfd() failed");
ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]);
if (ret >= LINE_MAX)
errx(1, "Arguments string is too long");
ret = write(event_control, line, strlen(line) + 1);
if (ret == -1)
err(1, "Cannot write to cgroup.event_control");
flags = fcntl(efd, F_GETFL, 0);
ret = fcntl(efd, F_SETFL, flags | O_NONBLOCK);
if (ret == -1)
err(1, "Cannot set non-blocking read");
#define PAGESIZE 4096
while (1) {
uint64_t result;
char *mem;
if (grow) {
// allocate more memory to try to hit threshold
if (index >= MAXBLOCKS)
err(1, "maximum allowed sized reached without hitting threshold");
mem = (char *)malloc(blksz_mbs<<20);
if (!mem)
err(1, "failed to allocate memory");
blocks[index++] = mem;
allocated_mbs += blksz_mbs;
/* touch each page to force actual allocation */
for (int i = 0; i < blksz_mbs<<20 ; i += PAGESIZE) {
memset(mem + i, 0, 1);
}
printf("allocated\n");
} else {
// free memory to drop below threshold
if (index <= 0)
err(1, "no blocks left to free to get below threshold");
free(blocks[--index]);
allocated_mbs -= blksz_mbs;
usleep(100000);
printf("freed\n");
}
ret = read(efd, &result, sizeof(result));
if (ret == -1) {
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
printf("not at threshold yet. %d MB allocated.\n", allocated_mbs);
continue;
}
err(1, "Cannot read from eventfd");
}
assert(ret == sizeof(result));
printf("%s %s: crossed\n", argv[1], argv[2]);
grow = !grow;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment