/*
 * dripper.c -- DF-5833 rig: pre-forked drip driver.
 *
 * Waits for the eater's "ready" file (floor reached; the victim will
 * release its workers within ~100 ms), sleeps past the drain + crash +
 * prelude + DRYRUN, then drives the drip sequence into the eater's
 * fifo. NEVER forks -- all syscalls (access/open/write) survive the
 * memory-pressure window.
 *
 * usage: dripper <readyfile> <fifo>
 */
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

int
main(int argc, char **argv)
{
	const char *gofile = argv[1];
	const char *fifo = argv[2];
	char buf[64];
	int fd, i, n;

	if (argc < 3)
		return (1);

	/* wait for the eater's ready marker (no forks; access() only) */
	while (access(gofile, F_OK) != 0)
		usleep(5000);

	/* Timeline (relative to ready):
	 *   +100ms  victim releases workers (drain begins)
	 *   +700ms  victim crashes; dumper enters sigexit
	 *   +700ms..  dumper prelude (expand_name/vn_open/..., ~30 fresh
	 *             pages) crawls on vm_wait; workers are parked in
	 *             their in-flight lwp_create (~4-8 fresh pages each)
	 *   +850ms  open the fifo
	 *   +900ms.. small staged drips: the prelude (~30 pages) completes
	 *            FIRST, then the 16 workers (~80 pages) insert AFTER
	 *            the DRYRUN note walk, and the dumper's huge
	 *            core-header alloc (hundreds of pages) completes LAST.
	 *            This ordering is what lands the lwp_create insertions
	 *            between the DRYRUN sizing pass and the WRITE pass. */
	usleep(1100000);
	fd = open(fifo, O_WRONLY);
	if (fd < 0)
		return (2);
	usleep(50000);

	/* ONE big burst timed INSIDE the [DRYRUN, WRITE] window: the
	 * dumper's huge core-header kmalloc completes, AND every parked
	 * in-flight lwp_create completes at the same instant -- dozens of
	 * worker threads then race the single dumper for p_token and
	 * their RB-tree insertions land BEFORE the WRITE note walk. */
	n = snprintf(buf, sizeof(buf), "D 4194304\n");
	write(fd, buf, n);
	usleep(150000);

	for (i = 0; i < 24; i++) {
		n = snprintf(buf, sizeof(buf), "D 65536\n");
		write(fd, buf, n);
		usleep(80000);
	}

	n = snprintf(buf, sizeof(buf), "D 4194304\n");
	write(fd, buf, n);
	usleep(300000);
	n = snprintf(buf, sizeof(buf), "D 67108864\n");
	write(fd, buf, n);
	close(fd);
	return (0);
}
