drivers/tty/tty_ldsem.c
Source file repositories/reference/linux-study-clean/drivers/tty/tty_ldsem.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/tty/tty_ldsem.c- Extension
.c- Size
- 10275 bytes
- Lines
- 414
- Domain
- Driver Families
- Bucket
- drivers/tty
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/list.hlinux/spinlock.hlinux/atomic.hlinux/tty.hlinux/sched.hlinux/sched/debug.hlinux/sched/task.h
Detected Declarations
struct ldsem_waiterfunction __init_ldsemfunction __ldsem_wake_readersfunction list_for_each_entry_safefunction writer_trylockfunction __ldsem_wake_writerfunction __ldsem_wakefunction ldsem_wakefunction down_read_failedfunction down_write_failedfunction __ldsem_down_read_nestedfunction __ldsem_down_write_nestedfunction ldsem_down_readfunction ldsem_down_read_trylockfunction ldsem_down_writefunction ldsem_up_readfunction ldsem_up_writefunction ldsem_down_read_nestedfunction ldsem_down_write_nested
Annotated Snippet
struct ldsem_waiter {
struct list_head list;
struct task_struct *task;
};
/*
* Initialize an ldsem:
*/
void __init_ldsem(struct ld_semaphore *sem, const char *name,
struct lock_class_key *key)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make sure we are not reinitializing a held semaphore:
*/
debug_check_no_locks_freed((void *)sem, sizeof(*sem));
lockdep_init_map(&sem->dep_map, name, key, 0);
#endif
atomic_long_set(&sem->count, LDSEM_UNLOCKED);
sem->wait_readers = 0;
raw_spin_lock_init(&sem->wait_lock);
INIT_LIST_HEAD(&sem->read_wait);
INIT_LIST_HEAD(&sem->write_wait);
}
static void __ldsem_wake_readers(struct ld_semaphore *sem)
{
struct ldsem_waiter *waiter, *next;
struct task_struct *tsk;
long adjust, count;
/*
* Try to grant read locks to all readers on the read wait list.
* Note the 'active part' of the count is incremented by
* the number of readers before waking any processes up.
*/
adjust = sem->wait_readers * (LDSEM_ACTIVE_BIAS - LDSEM_WAIT_BIAS);
count = atomic_long_add_return(adjust, &sem->count);
do {
if (count > 0)
break;
if (atomic_long_try_cmpxchg(&sem->count, &count, count - adjust))
return;
} while (1);
list_for_each_entry_safe(waiter, next, &sem->read_wait, list) {
tsk = waiter->task;
smp_store_release(&waiter->task, NULL);
wake_up_process(tsk);
put_task_struct(tsk);
}
INIT_LIST_HEAD(&sem->read_wait);
sem->wait_readers = 0;
}
static inline int writer_trylock(struct ld_semaphore *sem)
{
/*
* Only wake this writer if the active part of the count can be
* transitioned from 0 -> 1
*/
long count = atomic_long_add_return(LDSEM_ACTIVE_BIAS, &sem->count);
do {
if ((count & LDSEM_ACTIVE_MASK) == LDSEM_ACTIVE_BIAS)
return 1;
if (atomic_long_try_cmpxchg(&sem->count, &count, count - LDSEM_ACTIVE_BIAS))
return 0;
} while (1);
}
static void __ldsem_wake_writer(struct ld_semaphore *sem)
{
struct ldsem_waiter *waiter;
waiter = list_entry(sem->write_wait.next, struct ldsem_waiter, list);
wake_up_process(waiter->task);
}
/*
* handle the lock release when processes blocked on it that can now run
* - if we come here from up_xxxx(), then:
* - the 'active part' of count (&0x0000ffff) reached 0 (but may have changed)
* - the 'waiting part' of count (&0xffff0000) is -ve (and will still be so)
* - the spinlock must be held by the caller
* - woken process blocks are discarded from the list after having task zeroed
*/
static void __ldsem_wake(struct ld_semaphore *sem)
{
if (!list_empty(&sem->write_wait))
__ldsem_wake_writer(sem);
Annotation
- Immediate include surface: `linux/list.h`, `linux/spinlock.h`, `linux/atomic.h`, `linux/tty.h`, `linux/sched.h`, `linux/sched/debug.h`, `linux/sched/task.h`.
- Detected declarations: `struct ldsem_waiter`, `function __init_ldsem`, `function __ldsem_wake_readers`, `function list_for_each_entry_safe`, `function writer_trylock`, `function __ldsem_wake_writer`, `function __ldsem_wake`, `function ldsem_wake`, `function down_read_failed`, `function down_write_failed`.
- Atlas domain: Driver Families / drivers/tty.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.