include/linux/seqlock.h

Source file repositories/reference/linux-study-clean/include/linux/seqlock.h

File Facts

System
Linux kernel
Corpus path
include/linux/seqlock.h
Extension
.h
Size
42691 bytes
Lines
1367
Domain
Core OS
Bucket
Core Kernel Interface
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 ss_tmp {
	enum ss_state	state;
	unsigned long	data;
	spinlock_t	*lock;
	spinlock_t	*lock_irqsave;
};

static __always_inline void __scoped_seqlock_cleanup(struct ss_tmp *sst)
	__no_context_analysis
{
	if (sst->lock)
		spin_unlock(sst->lock);
	if (sst->lock_irqsave)
		spin_unlock_irqrestore(sst->lock_irqsave, sst->data);
}

extern void __scoped_seqlock_invalid_target(void);

#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 90000) || \
	defined(CONFIG_KASAN) || defined(CONFIG_UBSAN_ALIGNMENT)
/*
 * For some reason some GCC-8 architectures (nios2, alpha) have trouble
 * determining that the ss_done state is impossible in __scoped_seqlock_next()
 * below.
 *
 * Similarly KASAN and UBSAN_ALIGNMENT are known to confuse compilers enough
 * to break this. But we don't care about code quality for such builds anyway.
 */
static inline void __scoped_seqlock_bug(void) { }
#else
/*
 * Canary for compiler optimization -- if the compiler doesn't realize this is
 * an impossible state, it very likely generates sub-optimal code here.
 */
extern void __scoped_seqlock_bug(void);
#endif

static __always_inline void
__scoped_seqlock_next(struct ss_tmp *sst, seqlock_t *lock, enum ss_state target)
	__no_context_analysis
{
	switch (sst->state) {
	case ss_done:
		__scoped_seqlock_bug();
		return;

	case ss_lock:
	case ss_lock_irqsave:
		sst->state = ss_done;
		return;

	case ss_lockless:
		if (!read_seqretry(lock, sst->data)) {
			sst->state = ss_done;
			return;
		}
		break;
	}

	switch (target) {
	case ss_done:
		__scoped_seqlock_invalid_target();
		return;

	case ss_lock:
		sst->lock = &lock->lock;
		spin_lock(sst->lock);
		sst->state = ss_lock;
		return;

	case ss_lock_irqsave:
		sst->lock_irqsave = &lock->lock;
		spin_lock_irqsave(sst->lock_irqsave, sst->data);
		sst->state = ss_lock_irqsave;
		return;

	case ss_lockless:
		sst->data = read_seqbegin(lock);
		return;
	}
}

/*
 * Context analysis no-op helper to release seqlock at the end of the for-scope;
 * the alias analysis of the compiler will recognize that the pointer @s is an
 * alias to @_seqlock passed to read_seqbegin(_seqlock) below.
 */
static __always_inline void __scoped_seqlock_cleanup_ctx(struct ss_tmp **s)
	__releases_shared(*((seqlock_t **)s)) __no_context_analysis {}

Annotation

Implementation Notes