drivers/md/dm-vdo/funnel-queue.h

Source file repositories/reference/linux-study-clean/drivers/md/dm-vdo/funnel-queue.h

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-vdo/funnel-queue.h
Extension
.h
Size
4901 bytes
Lines
111
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct funnel_queue_entry {
	/* The next (newer) entry in the queue. */
	struct funnel_queue_entry *next;
};

/*
 * The dynamically allocated queue structure, which is allocated on a cache line boundary so the
 * producer and consumer fields in the structure will land on separate cache lines. This should be
 * consider opaque but it is exposed here so vdo_funnel_queue_put() can be inlined.
 */
struct __aligned(L1_CACHE_BYTES) funnel_queue {
	/*
	 * The producers' end of the queue, an atomically exchanged pointer that will never be
	 * NULL.
	 */
	struct funnel_queue_entry *newest;

	/* The consumer's end of the queue, which is owned by the consumer and never NULL. */
	struct funnel_queue_entry *oldest __aligned(L1_CACHE_BYTES);

	/* A dummy entry used to provide the non-NULL invariants above. */
	struct funnel_queue_entry stub;
};

int __must_check vdo_make_funnel_queue(struct funnel_queue **queue_ptr);

void vdo_free_funnel_queue(struct funnel_queue *queue);

/*
 * Put an entry on the end of the queue.
 *
 * The entry pointer must be to the struct funnel_queue_entry embedded in the caller's data
 * structure. The caller must be able to derive the address of the start of their data structure
 * from the pointer that passed in here, so every entry in the queue must have the struct
 * funnel_queue_entry at the same offset within the client's structure.
 */
static inline void vdo_funnel_queue_put(struct funnel_queue *queue,
					struct funnel_queue_entry *entry)
{
	struct funnel_queue_entry *previous;

	/*
	 * Barrier requirements: All stores relating to the entry ("next" pointer, containing data
	 * structure fields) must happen before the previous->next store making it visible to the
	 * consumer. Also, the entry's "next" field initialization to NULL must happen before any
	 * other producer threads can see the entry (the xchg) and try to update the "next" field.
	 *
	 * xchg implements a full barrier.
	 */
	WRITE_ONCE(entry->next, NULL);
	previous = xchg(&queue->newest, entry);
	/*
	 * Preemptions between these two statements hide the rest of the queue from the consumer,
	 * preventing consumption until the following assignment runs.
	 */
	WRITE_ONCE(previous->next, entry);
}

struct funnel_queue_entry *__must_check vdo_funnel_queue_poll(struct funnel_queue *queue);

bool __must_check vdo_is_funnel_queue_empty(struct funnel_queue *queue);

bool __must_check vdo_is_funnel_queue_idle(struct funnel_queue *queue);

#endif /* VDO_FUNNEL_QUEUE_H */

Annotation

Implementation Notes