#include <getopt.h>
#include <linux/logger.h>
#include <pthread.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define BIT(nr) ((1UL) << (nr))
+// Note, largest singular message payload is 4076
+#define BIG_MSG_SIZE 8000
+
+#define ALL_TEST_BITS \
+ (BIT(0) | BIT(2) | BIT(3) | BIT(6) | BIT(7))
+
+struct targ {
+ int fd;
+ int iter;
+};
+
void *tstart(void *arg)
{
- int *fd = arg;
- write(*fd, "child thread msg #1\nchild thread msg #2", 39);
+ struct targ *targ = arg;
+ int fd = targ->fd;
+ int iter = targ->iter;
+ bool inf = (iter < 0);
+ int i;
+
+ fprintf(stderr,"iter: %d\n", iter);
+ for (i = 0; inf || i < iter; i++)
+ write(fd, "child thread msg #1\nchild thread msg #2", 39);
return 0;
}
-int dump_logger(const char *device)
+int clear_logger(const char *device)
+{
+ int fd;
+ int ret = 0;
+
+ fd = open(device, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ perror("open");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = ioctl(fd, LOGGER_FLUSH_LOG, 0);
+ if (ret < 0) {
+ perror("ioctl(FLUSH_LOG)");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+
+ return ret;
+}
+
+int dump_logger(const char *device, bool clear)
{
int fd;
int ret = 0;
}
tag_len = strlen(e->msg + 1) + 2; /* 2: priority, NUL */
- fprintf(stdout, "[%5d.%6d] %s<%u>: %s\n", e->sec, e->nsec / 1000, &e->msg[1], e->msg[0], &e->msg[tag_len]);
+ fprintf(stdout, "[%5d.%06d] %s<%u>[%u|%u]: %s\n", e->sec, e->nsec / 1000, &e->msg[1], e->msg[0], e->pid, e->tid, &e->msg[tag_len]);
};
+ close(fd);
+
+ if (clear)
+ clear_logger(device);
+
return ret;
}
+
+void thread_logger(int iter, int fd)
+{
+ int s;
+ pthread_t tid;
+ struct targ targ;
+ bool inf = (iter < 0);
+ int i;
+
+ targ.fd = fd;
+ targ.iter = iter;
+
+ s = pthread_create(&tid, NULL, &tstart, &targ);
+ if (s != 0)
+ handle_error_en(s, "pthread_create");
+
+ for (i = 0; inf || i < iter; i++)
+ write(fd, "PARENT THREAD\n", 14);
+
+ s = pthread_join(tid, NULL);
+ if (s != 0)
+ handle_error_en(s, "pthread_join");
+}
+
+void fork_logger(int iter, int fd)
+{
+ bool inf = (iter < 0);
+ pid_t child;
+ int s;
+ int i;
+
+ child = fork();
+ if (child < 0) {
+ exit(EXIT_FAILURE);
+ } else if (child == 0) {
+ for (i = 0; inf || i < iter; i++) {
+ write(fd, "child 1\n", 8);
+ write(fd, "child 2\n", 8);
+ }
+ close(fd);
+ exit(EXIT_SUCCESS);
+ }
+ for (i = 0; inf || i < iter; i++)
+ write(fd, "PARENT\n", 7);
+ wait(&s);
+
+}
+
+void large_message_logger(int iter, int fd, unsigned long test_mask)
+{
+ bool inf = (iter < 0);
+ char *msg;
+ int i, j;
+
+ msg = malloc(BIG_MSG_SIZE);
+ if (!msg)
+ return;
+
+ for (i = 0; i < BIG_MSG_SIZE; i++)
+ msg[i] = '!' + (i % 95);
+ msg[BIG_MSG_SIZE - 4] = 'E';
+ msg[BIG_MSG_SIZE - 3] = 'O';
+ msg[BIG_MSG_SIZE - 2] = 'F';
+ msg[BIG_MSG_SIZE - 1] = '\n';
+
+ write(fd, msg, BIG_MSG_SIZE);
+
+ for (j = 0; (test_mask & BIT(4)) && (inf || j < iter); j++ )
+ for (i = 0; i < 40; i++)
+ write(fd, msg, BIG_MSG_SIZE);
+
+ for (j = 0; (test_mask & BIT(5)) && (inf || j < iter); j++ )
+ for (i = 0; i < BIG_MSG_SIZE; i++)
+ write(fd, &msg[i], 1);
+
+ free(msg);
+ msg = NULL;
+}
+
+void stdio_logger(int iter, int fd)
+{
+ bool inf = (iter < 0);
+ int count;
+ int i;
+
+ count = write(fd, "The Foo From STDIO\n", 19);
+ if (count != 19)
+ fprintf(stderr, "%d != 19\n", count);
+
+ for (i = 0; inf || i < iter; i++) {
+ write(fd, "LINE #1\nLINE #2", 15);
+ write(fd, " CONTINUED\nONCE", 15);
+ write(fd, " AGAIN\n", 7);
+ }
+}
+
+void iov_logger(int iter, int fd, unsigned long test_mask, unsigned char prio, char *tag, char *msg)
+{
+ bool inf = (iter < 0);
+ int i;
+ struct iovec vec[3];
+
+ for (i = 0; inf || i < iter; i++) {
+ vec[0].iov_base = &prio;
+ vec[0].iov_len = 1;
+ vec[1].iov_base = tag;
+ vec[1].iov_len = strlen(tag) + 1;
+ vec[2].iov_base = msg;
+ vec[2].iov_len = strlen(msg) + 1;
+
+ writev(fd, vec, 3);
+ if (test_mask & BIT(1)) {
+ msg = "line #1\nline #2";
+ vec[2].iov_base = msg;
+ vec[2].iov_len = strlen(msg) + 1;
+
+ writev(fd, vec, 3);
+ }
+ }
+}
+
+int count_bits(unsigned long i) {
+ int n = 0;
+ while(i) {
+ n += i & 1;
+ i >>= 1;
+ }
+ return n;
+}
+
int main(int ac, char *av[]) {
char *device = "/dev/log_main";
.len = 6,
.ptr = (uintptr_t)tag,
};
- int c, fd, s, ret;
- pid_t child;
- int dump = 0;
- pthread_t tid;
- struct iovec vec[3];
+ int c, fd, ret;
+ bool dump = false;
+ bool clear = false;
+
unsigned char prio = 4;
unsigned long test_mask = ~0UL;
+ int iterations = 1;
while (1) {
static struct option long_options[] = {
{"tag", required_argument, 0, 't'},
{"test-mask", required_argument, 0, 'm'},
{"device", required_argument, 0, 'd'},
+ {"dump", no_argument, 0, 'D'},
+ {"loop", optional_argument, 0, 'l'},
+ {"clear", no_argument, 0, 'C'},
{0, 0, 0, 0}
};
- c = getopt_long(ac, av, "p:t:m:d:D", long_options, NULL);
+ c = getopt_long(ac, av, "p:t:m:d:Dl::C", long_options, NULL);
if (c == -1)
break;
device = strdup(optarg);
break;
case 'D':
- dump = 1;
+ dump = true;
+ break;
+ case 'l':
+ if (optarg != NULL)
+ iterations = (int) strtol(optarg, NULL, 10);
+ else
+ iterations = -1; // a.k.a. infinity
+ break;
+ case 'C':
+ clear = true;
break;
default:
+ fprintf(stderr, "c: %c\n", c);
exit(1);
}
}
+ fprintf(stderr, "dump: %u\n", dump);
+ fprintf(stderr, "clear: %u\n", clear);
+
if (dump)
- return dump_logger(device);
+ return dump_logger(device, clear);
+
+ if (clear)
+ return clear_logger(device);
+
+ fprintf(stderr, "prio: %u\n", prio);
+ fprintf(stderr, "tag: %s\n", tag);
+ fprintf(stderr, "mask: %u\n", test_mask);
+ fprintf(stderr, "cnt: %u\n", count_bits(test_mask));
+ fprintf(stderr, "dev: %s\n", device);
+ fprintf(stderr, "loop: %d\n", iterations);
+
+ if ((iterations < 0) && count_bits(test_mask & ALL_TEST_BITS) != 1) {
+ fprintf(stderr, "Choose one test scenario only for infinite loop testing.\n");
+ exit(EXIT_FAILURE);
+ }
setlinebuf(stdout);
fd = open(device, O_WRONLY);
}
if (test_mask & BIT(0)) {
- vec[0].iov_base = &prio;
- vec[0].iov_len = 1;
- vec[1].iov_base = tag;
- vec[1].iov_len = strlen(tag) + 1;
- vec[2].iov_base = msg;
- vec[2].iov_len = strlen(msg) + 1;
-
- writev(fd, vec, 3);
- if (test_mask & BIT(1)) {
- msg = "line #1\nline #2";
- vec[2].iov_base = msg;
- vec[2].iov_len = strlen(msg) + 1;
-
- writev(fd, vec, 3);
- }
+ iov_logger(iterations, fd, test_mask, prio, tag, msg);
}
ret = ioctl(fd, LOGGER_SET_PRIO, prio);
exit(EXIT_FAILURE);
}
- if (test_mask & BIT(2)) {
- int count;
- count = write(fd, "The Foo From STDIO\n", 19);
- if (count != 19)
- fprintf(stderr, "%d != 19\n", count);
-
- write(fd, "LINE #1\nLINE #2", 15);
- write(fd, " CONTINUED\nONCE", 15);
- write(fd, " AGAIN\n", 7);
- }
-
- if (test_mask & BIT(3)) {
- msg = malloc(8000);
- if (!msg)
- return 1;
+ if (test_mask & BIT(2))
+ stdio_logger(iterations, fd);
- for (int i = 0; i < 8000; i++)
- msg[i] = '!' + (i % 95);
- msg[7996] = 'E';
- msg[7997] = 'O';
- msg[7998] = 'F';
- msg[7999] = '\n';
- write(fd, msg, 8000);
+ if (test_mask & BIT(3))
+ large_message_logger(iterations, fd, test_mask);
- for (int i = 0; (test_mask & BIT(4)) && i < 40; i++)
- write(fd, msg, 8000);
+ if (test_mask & BIT(6))
+ fork_logger(iterations, fd);
- for (int i = 0; (test_mask & BIT(5)) && i < 8000; i++)
- write(fd, &msg[i], 1);
-
- free(msg);
- msg = NULL;
- }
-
- if (test_mask & BIT(6)) {
- child = fork();
- if (child < 0) {
- return -1;
- } else if (child == 0) {
- sleep(1);
- printf("child: %d\n", getpid());
- write(fd, "child 1\n", 8);
- sleep(1);
- write(fd, "child 2\n", 8);
- close(fd);
- return 0;
- }
- write(fd, "PARENT\n", 7);
- printf("PARENT: %d\n", getpid());
- wait(&s);
- }
-
- if (test_mask & BIT(7)) {
- s = pthread_create(&tid, NULL, &tstart, &fd);
- if (s != 0)
- handle_error_en(s, "pthread_create");
- sleep(1);
- write(fd, "PARENT THREAD\n", 14);
-
- s = pthread_join(tid, NULL);
- if (s != 0)
- handle_error_en(s, "pthread_join");
- }
+ if (test_mask & BIT(7))
+ thread_logger(iterations, fd);
return 0;
}