drivers/md/dm-vdo/funnel-queue.c
Source file repositories/reference/linux-study-clean/drivers/md/dm-vdo/funnel-queue.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/md/dm-vdo/funnel-queue.c- Extension
.c- Size
- 5093 bytes
- Lines
- 171
- 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.
- 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.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
funnel-queue.hcpu.hmemory-alloc.hpermassert.h
Detected Declarations
function vdo_make_funnel_queuefunction vdo_free_funnel_queuefunction vdo_is_funnel_queue_emptyfunction vdo_funnel_queue_poll
Annotated Snippet
if (oldest != newest) {
/*
* Another thread has already swung queue->newest atomically, but not yet
* assigned previous->next. The queue is really still empty.
*/
return NULL;
}
/*
* Put the stub entry back on the queue, ensuring a successor will eventually be
* seen.
*/
vdo_funnel_queue_put(queue, &queue->stub);
/* Check again for a successor. */
next = READ_ONCE(oldest->next);
if (next == NULL) {
/*
* We lost a race with a producer who swapped queue->newest before we did,
* but who hasn't yet updated previous->next. Try again later.
*/
return NULL;
}
}
return oldest;
}
/*
* Poll a queue, removing the oldest entry if the queue is not empty. This function must only be
* called from a single consumer thread.
*/
struct funnel_queue_entry *vdo_funnel_queue_poll(struct funnel_queue *queue)
{
struct funnel_queue_entry *oldest = get_oldest(queue);
if (oldest == NULL)
return oldest;
/*
* Dequeue the oldest entry and return it. Only one consumer thread may call this function,
* so no locking, atomic operations, or fences are needed; queue->oldest is owned by the
* consumer and oldest->next is never used by a producer thread after it is swung from NULL
* to non-NULL.
*/
queue->oldest = READ_ONCE(oldest->next);
/*
* Make sure the caller sees the proper stored data for this entry. Since we've already
* fetched the entry pointer we stored in "queue->oldest", this also ensures that on entry
* to the next call we'll properly see the dependent data.
*/
smp_rmb();
/*
* If "oldest" is a very light-weight work item, we'll be looking for the next one very
* soon, so prefetch it now.
*/
uds_prefetch_address(queue->oldest, true);
WRITE_ONCE(oldest->next, NULL);
return oldest;
}
/*
* Check whether the funnel queue is empty or not. If the queue is in a transition state with one
* or more entries being added such that the list view is incomplete, this function will report the
* queue as empty.
*/
bool vdo_is_funnel_queue_empty(struct funnel_queue *queue)
{
return get_oldest(queue) == NULL;
}
/*
* Check whether the funnel queue is idle or not. If the queue has entries available to be
* retrieved, it is not idle. If the queue is in a transition state with one or more entries being
* added such that the list view is incomplete, it may not be possible to retrieve an entry with
* the vdo_funnel_queue_poll() function, but the queue will not be considered idle.
*/
bool vdo_is_funnel_queue_idle(struct funnel_queue *queue)
{
/*
* Oldest is not the stub, so there's another entry, though if next is NULL we can't
* retrieve it yet.
*/
if (queue->oldest != &queue->stub)
return false;
/*
* Oldest is the stub, but newest has been updated by _put(); either there's another,
* retrievable entry in the list, or the list is officially empty but in the intermediate
* state of having an entry added.
Annotation
- Immediate include surface: `funnel-queue.h`, `cpu.h`, `memory-alloc.h`, `permassert.h`.
- Detected declarations: `function vdo_make_funnel_queue`, `function vdo_free_funnel_queue`, `function vdo_is_funnel_queue_empty`, `function vdo_funnel_queue_poll`.
- Atlas domain: Driver Families / drivers/md.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.