/*
 * DF-2896 console writer (ROOT) — simulates syslogd/console writers.
 *
 * N threads hammering write() on /dev/console.  Each write goes through
 * cnwrite(): captures constty->t_dev, sleeps ms-scale in log_console(),
 * then dispatches through the captured (possibly destroyed) cdev.
 */
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define NTHREADS	1
#define CHUNK		(4 * 1024 * 1024)

static void *
wr(void *arg)
{
	long id = (long)arg;
	int fd;
	char *buf;
	unsigned long n = 0;

	buf = malloc(CHUNK);
	if (buf == NULL) return (NULL);
	memset(buf, 'W', CHUNK);

	for (;;) {
		fd = open("/dev/console", O_WRONLY | O_NONBLOCK);
		if (fd < 0) {
			usleep(10000);
			continue;
		}
		for (;;) {
			ssize_t r = write(fd, buf, CHUNK);
			if (r < 0) {
				if (errno == EINTR || errno == EIO ||
				    errno == EAGAIN || errno == ENXIO)
					usleep(500);
				else
					usleep(1000);
				continue;
			}
			n++;
			if ((n & 0x3f) == 0)
				printf("writer%ld: %lu writes\n", id, n);
			usleep(200000);	/* ~3 dispatch instants/s */
		}
		close(fd);
	}
	return (NULL);
}

int
main(void)
{
	pthread_t th[NTHREADS];
	long i;

	setvbuf(stdout, NULL, _IONBF, 0);
	printf("writer: %d threads x %d bytes\n", NTHREADS, CHUNK);
	for (i = 0; i < NTHREADS; i++)
		pthread_create(&th[i], NULL, wr, (void *)i);
	for (i = 0; i < NTHREADS; i++)
		pthread_join(th[i], NULL);
	return (0);
}
