kernel/printk/printk_ringbuffer_kunit_test.c

Source file repositories/reference/linux-study-clean/kernel/printk/printk_ringbuffer_kunit_test.c

File Facts

System
Linux kernel
Corpus path
kernel/printk/printk_ringbuffer_kunit_test.c
Extension
.c
Size
9557 bytes
Lines
328
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct prbtest_rbdata {
	unsigned int size;
	char text[] __counted_by(size);
};

#define MAX_RBDATA_TEXT_SIZE 0x80
#define MAX_PRB_RECORD_SIZE (sizeof(struct prbtest_rbdata) + MAX_RBDATA_TEXT_SIZE)

struct prbtest_data {
	struct kunit *test;
	struct printk_ringbuffer *ringbuffer;
	/* used by writers to signal reader of new records */
	wait_queue_head_t new_record_wait;
};

struct prbtest_thread_data {
	unsigned long num;
	struct prbtest_data *test_data;
};

static void prbtest_fail_record(struct kunit *test, const struct prbtest_rbdata *dat, u64 seq)
{
	unsigned int len;

	len = dat->size - 1;

	KUNIT_FAIL(test, "BAD RECORD: seq=%llu size=%u text=%.*s\n",
		   seq, dat->size,
		   len < MAX_RBDATA_TEXT_SIZE ? len : -1,
		   len < MAX_RBDATA_TEXT_SIZE ? dat->text : "<invalid>");
}

static bool prbtest_check_data(const struct prbtest_rbdata *dat)
{
	unsigned int len;

	/* Sane size? At least one character + trailing '\0' */
	if (dat->size < 2 || dat->size > MAX_RBDATA_TEXT_SIZE)
		return false;

	len = dat->size - 1;
	if (dat->text[len] != '\0')
		return false;

	/* String repeats with the same character? */
	while (len--) {
		if (dat->text[len] != dat->text[0])
			return false;
	}

	return true;
}

static int prbtest_writer(void *data)
{
	struct prbtest_thread_data *tr = data;
	char text_id = 'A' + tr->num;
	struct prb_reserved_entry e;
	struct prbtest_rbdata *dat;
	u32 record_size, text_size;
	unsigned long count = 0;
	struct printk_record r;

	kunit_info(tr->test_data->test, "start thread %03lu (writer)\n", tr->num);

	for (;;) {
		/* ensure at least 1 character + trailing '\0' */
		text_size = get_random_u32_inclusive(2, MAX_RBDATA_TEXT_SIZE);
		if (WARN_ON_ONCE(text_size < 2))
			text_size = 2;
		if (WARN_ON_ONCE(text_size > MAX_RBDATA_TEXT_SIZE))
			text_size = MAX_RBDATA_TEXT_SIZE;

		record_size = sizeof(struct prbtest_rbdata) + text_size;
		WARN_ON_ONCE(record_size > MAX_PRB_RECORD_SIZE);

		/* specify the text sizes for reservation */
		prb_rec_init_wr(&r, record_size);

		/*
		 * Reservation can fail if:
		 *
		 *      - No free descriptor is available.
		 *      - The buffer is full, and the oldest record is reserved
		 *        but not yet committed.
		 *
		 * It actually happens in this test because all CPUs are trying
		 * to write an unbounded number of messages in a tight loop.
		 * These failures are intentionally ignored because this test
		 * focuses on races, ringbuffer consistency, and pushing system

Annotation

Implementation Notes