kernel/kcsan/kcsan_test.c

Source file repositories/reference/linux-study-clean/kernel/kcsan/kcsan_test.c

File Facts

System
Linux kernel
Corpus path
kernel/kcsan/kcsan_test.c
Extension
.c
Size
52323 bytes
Lines
1626
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 expect_report {
	/* Access information of both accesses. */
	struct {
		void *fn;    /* Function pointer to expected function of top frame. */
		void *addr;  /* Address of access; unchecked if NULL. */
		size_t size; /* Size of access; unchecked if @addr is NULL. */
		int type;    /* Access type, see KCSAN_ACCESS definitions. */
	} access[2];
};

/* Check observed report matches information in @r. */
__no_kcsan
static bool __report_matches(const struct expect_report *r)
{
	const bool is_assert = (r->access[0].type | r->access[1].type) & KCSAN_ACCESS_ASSERT;
	bool ret = false;
	unsigned long flags;
	typeof(*observed.lines) *expect;
	const char *end;
	char *cur;
	int i;

	/* Doubled-checked locking. */
	if (!report_available())
		return false;

	expect = (typeof(expect))kmalloc_obj(observed.lines);
	if (WARN_ON(!expect))
		return false;

	/* Generate expected report contents. */

	/* Title */
	cur = expect[0];
	end = ARRAY_END(expect[0]);
	cur += scnprintf(cur, end - cur, "BUG: KCSAN: %s in ",
			 is_assert ? "assert: race" : "data-race");
	if (r->access[1].fn) {
		char tmp[2][64];
		int cmp;

		/* Expect lexographically sorted function names in title. */
		scnprintf(tmp[0], sizeof(tmp[0]), "%pS", r->access[0].fn);
		scnprintf(tmp[1], sizeof(tmp[1]), "%pS", r->access[1].fn);
		cmp = strcmp(tmp[0], tmp[1]);
		cur += scnprintf(cur, end - cur, "%ps / %ps",
				 cmp < 0 ? r->access[0].fn : r->access[1].fn,
				 cmp < 0 ? r->access[1].fn : r->access[0].fn);
	} else {
		scnprintf(cur, end - cur, "%pS", r->access[0].fn);
		/* The exact offset won't match, remove it. */
		cur = strchr(expect[0], '+');
		if (cur)
			*cur = '\0';
	}

	/* Access 1 */
	cur = expect[1];
	end = ARRAY_END(expect[1]);
	if (!r->access[1].fn)
		cur += scnprintf(cur, end - cur, "race at unknown origin, with ");

	/* Access 1 & 2 */
	for (i = 0; i < 2; ++i) {
		const int ty = r->access[i].type;
		const char *const access_type =
			(ty & KCSAN_ACCESS_ASSERT) ?
				      ((ty & KCSAN_ACCESS_WRITE) ?
					       "assert no accesses" :
					       "assert no writes") :
				      ((ty & KCSAN_ACCESS_WRITE) ?
					       ((ty & KCSAN_ACCESS_COMPOUND) ?
							"read-write" :
							"write") :
					       "read");
		const bool is_atomic = (ty & KCSAN_ACCESS_ATOMIC);
		const bool is_scoped = (ty & KCSAN_ACCESS_SCOPED);
		const char *const access_type_aux =
				(is_atomic && is_scoped)	? " (marked, reordered)"
				: (is_atomic			? " (marked)"
				   : (is_scoped			? " (reordered)" : ""));

		if (i == 1) {
			/* Access 2 */
			cur = expect[2];
			end = &expect[2][sizeof(expect[2]) - 1];

			if (!r->access[1].fn) {
				/* Dummy string if no second access is available. */
				strscpy(expect[2], "<none>");

Annotation

Implementation Notes