Interfaces for drivers code running in kernel space. More...
Functions | |
uint32 | acquire_read_seqlock (seqlock *lock) |
Prepare for read access to data protected by a seqlock. | |
void | acquire_read_spinlock (rw_spinlock *lock) |
Busy wait until a rw_spinlock can be read locked. | |
void | acquire_spinlock (spinlock *lock) |
Busy wait until the lock is acquired. | |
void | acquire_write_seqlock (seqlock *lock) |
Busy wait for a seqlock and acquire it for writing. | |
void | acquire_write_spinlock (rw_spinlock *lock) |
Wait for and acquire a write lock on an rw_spinlock. | |
int | add_debugger_command (const char *name, debugger_command_hook hook, const char *help) |
Add a command to the krnel debugger. | |
status_t | add_timer (timer *t, timer_hook hook, bigtime_t period, int32 flags) |
Schedule a timer to call the hook function periodically or at a specified time. | |
void | call_all_cpus (void(*func)(void *, int), void *cookie) |
Execute a function on all CPUs. | |
void | call_all_cpus_sync (void(*func)(void *, int), void *cookie) |
Execute a function on all CPUs, and wait for all of them to complete it before returning. | |
bool | cancel_timer (timer *t) |
Stop a timer scheduled by add_timer. | |
cpu_status | disable_interrupts (void) |
Disable interruptions. | |
void void | dump_block (const char *buffer, int size, const char *prefix) |
Dump a memory buffer as hexadecimal values to the kernel log. | |
void | dvprintf (const char *format, va_list args) |
Print a message to the kernel log if dprintf is enabled. | |
int32 | get_memory_map (const void *buffer, size_t size, physical_entry *table, int32 numEntries) |
Get memory map for the current team. | |
status_t | get_memory_map_etc (team_id team, const void *address, size_t numBytes, physical_entry *table, uint32 *_numEntries) |
Determine the physical addresses corresponding to a virtual memory range. | |
void void | kernel_debugger (const char *message) |
Enter the kernel debugger with the passed message. | |
void | kprintf (const char *fmt,...) _PRINTFLIKE(1 |
Print a message to the kernel log unconditionally. | |
status_t | lock_memory (void *buffer, size_t numBytes, uint32 flags) |
Lock memory from the current team into RAM. | |
status_t | lock_memory_etc (team_id team, void *buffer, size_t numBytes, uint32 flags) |
Lock memory pages into RAM. | |
area_id | map_physical_memory (const char *areaName, phys_addr_t physicalAddress, size_t size, uint32 flags, uint32 protection, void **_mappedAddress) |
Create an area that allows access to a specific range of physical memory. | |
void | memory_read_barrier (void) |
Execute a memory read barrier. | |
void | memory_write_barrier (void) |
Execute a memory write barrier. | |
void | panic (const char *format,...) _PRINTFLIKE(1 |
Enter the kernel debugger with the passed (formatted) message. | |
uint64 | parse_expression (const char *string) |
Parse an expression and return its value. | |
status_t | register_kernel_daemon (daemon_hook hook, void *arg, int frequency) |
Register a function to be called periodically. | |
bool | release_read_seqlock (seqlock *lock, uint32 count) |
Release a read lock and check if the read operation was successful. | |
void | release_read_spinlock (rw_spinlock *lock) |
Release a read lock on a rw_spinlock. | |
void | release_spinlock (spinlock *lock) |
Release a previously acquired spinlock. | |
void | release_write_seqlock (seqlock *lock) |
Release a write lock on a seqlock. | |
void | release_write_spinlock (rw_spinlock *lock) |
Release a previously acquired write lock on an rw_spinlock. | |
int | remove_debugger_command (const char *name, debugger_command_hook hook) |
Remove a debugger command previously installed by add_debugger_command. | |
void | restore_interrupts (cpu_status status) |
Restore interrupts to the previous state. | |
int | send_signal_etc (pid_t thread, uint signal, uint32 flags) |
Send a signal to a thread. | |
bool | set_dprintf_enabled (bool new_state) |
Enable dprintf log messages. | |
thread_id | spawn_kernel_thread (thread_func function, const char *name, int32 priority, void *arg) |
Start a kernel thread. | |
void | spin (bigtime_t microseconds) |
Busy loop for the given time. | |
bool | try_acquire_read_spinlock (rw_spinlock *lock) |
Acquire a rw_spinlock for reading, if available. | |
bool | try_acquire_write_seqlock (seqlock *lock) |
Acquire a seqlock for writing, without waiting. | |
bool | try_acquire_write_spinlock (rw_spinlock *lock) |
Acquire a rw_spinlock for writing, if available. | |
status_t | unlock_memory (void *buffer, size_t numBytes, uint32 flags) |
Unlock memory previously locked by lock_memory. | |
status_t | unlock_memory_etc (team_id team, void *address, size_t numBytes, uint32 flags) |
Unlock memory previously locked by lock_memory_etc. | |
status_t | unregister_kernel_daemon (daemon_hook hook, void *arg) |
Stop calling a daemon function. | |
status_t | user_memcpy (void *to, const void *from, size_t size) |
Copy memory between userspace and kernelspace. | |
status_t | user_memset (void *start, char c, size_t count) |
Set userspace memory. | |
ssize_t | user_strlcpy (char *to, const char *from, size_t size) |
Copy a string between userspace and kernel space. | |
Interfaces for drivers code running in kernel space.
uint32 acquire_read_seqlock | ( | seqlock * | lock | ) |
Prepare for read access to data protected by a seqlock.
void acquire_read_spinlock | ( | rw_spinlock * | lock | ) |
Busy wait until a rw_spinlock can be read locked.
Loop until there are no writers holding te lock, then acquire a read lock.
void acquire_spinlock | ( | spinlock * | lock | ) |
Busy wait until the lock is acquired.
Wait until the lock is acquired. Note that this keeps the thread running on the CPU, and does not release the CPU for other threads to run.
If the spinlock does not become available quickly enough, calls panic().
void acquire_write_seqlock | ( | seqlock * | lock | ) |
Busy wait for a seqlock and acquire it for writing.
Wait for all other writers to release the lock, then acquire it.
This increments the counter after acquiring the lock.
void acquire_write_spinlock | ( | rw_spinlock * | lock | ) |
Wait for and acquire a write lock on an rw_spinlock.
Repeatedly try to acquire a write lock until it works. If this fails for too long, call panic().
int add_debugger_command | ( | const char * | name, |
debugger_command_hook | hook, | ||
const char * | help | ||
) |
Add a command to the krnel debugger.
Drivers can add extra commands to the kernel debugger to ease investigation and debugging of the driver and hardware. The commands accept a typical argc/argv command line.
Schedule a timer to call the hook function periodically or at a specified time.
flags | If B_ONE_SHOT_ABSOLUTE_TIMER, use the period as a date when the hook should be called. Otherwise, use it as a period to call the hook repeatedly. |
flags | If B_TIMER_USE_TIMER_STRUCT_TIMES, use the period defined by t instead of period. |
cpu_status disable_interrupts | ( | void | ) |
Disable interruptions.
Drivers can disable interrupts in order to set up the interrupt handler for a device without being interrupted, or as a simple way to implement critical sections.
Interruptions should be kept disabled for as short as possible, and re-enabled using restore_interrupts.
Lock memory pages into RAM.
Lock a memory area and prevent accesses from other parts of the system. This establishes the following:
This is used for example during DMA transfers, to make sure the DMA can operate on memory that will not be accessed by the CPU or other devices.
area_id map_physical_memory | ( | const char * | areaName, |
phys_addr_t | physicalAddress, | ||
size_t | size, | ||
uint32 | flags, | ||
uint32 | protection, | ||
void ** | _mappedAddress | ||
) |
Create an area that allows access to a specific range of physical memory.
This can be used to map memory-mapped hardware to allow accessing it. The area can then be used by a driver, or its id sent to userspace for direct hardware access from userspace.
void memory_read_barrier | ( | void | ) |
Execute a memory read barrier.
Some CPU and cache architectures do not automatically ensure consistency between the CPU cache, the instruction ordering, and the memory. A barrier makes sure every read that should be executed before the barrier will be complete before any more memory access operations can be done.
void memory_write_barrier | ( | void | ) |
Execute a memory write barrier.
Some CPU and cache architectures do not automatically ensure consistency between the CPU cache, the instruction ordering, and the memory. A barrier makes sure every read that should be executed before the barrier will be complete before any more memory access operations can be done.
uint64 parse_expression | ( | const char * | string | ) |
Parse an expression and return its value.
Expressions can contain numbers in various bases and simple arithmetic operations, as well as kernel debugger variables. This function is used to parse kernel debugger command arguments.
bool release_read_seqlock | ( | seqlock * | lock, |
uint32 | count | ||
) |
Release a read lock and check if the read operation was successful.
count | The lock count value returned by the correspondin acquire_read_seqlock |
void release_spinlock | ( | spinlock * | lock | ) |
Release a previously acquired spinlock.
This will unblock any thread that is waiting on the spinlock.
void release_write_seqlock | ( | seqlock * | lock | ) |
Release a write lock on a seqlock.
This increments the counter before releasing the lock.
int remove_debugger_command | ( | const char * | name, |
debugger_command_hook | hook | ||
) |
Remove a debugger command previously installed by add_debugger_command.
It is important to remove the commands from a driver or module before it is unloaded, to avoid having commands that point to code that doesn't exist anymore.
void restore_interrupts | ( | cpu_status | status | ) |
Restore interrupts to the previous state.
If interrupts were already disabled before the matching call to disable_interrupts, do nothing. Otherwise, enable interrupts again.
bool set_dprintf_enabled | ( | bool | new_state | ) |
Enable dprintf log messages.
dprintf is used for debugging. It can be disabled to reduce the amount of logs from the kernel and drivers, which will also speed up the system in some cases. However, this makes debugging hardware and driver problems a lot more difficult.
thread_id spawn_kernel_thread | ( | thread_func | function, |
const char * | name, | ||
int32 | priority, | ||
void * | arg | ||
) |
Start a kernel thread.
Similar to spawn_thread, but the thread will run in the kernel team.
void spin | ( | bigtime_t | microseconds | ) |
Busy loop for the given time.
Some I/O operations may take a short while to complete. When the expected delay is less than a few hundred micrseconds, it is not worth locking the thread and calling the scheduler. In these situation, a busy loop is a better compromise, and the driver can continue its IO accesses in a reasonable time and without too many reschedulings.
bool try_acquire_read_spinlock | ( | rw_spinlock * | lock | ) |
Acquire a rw_spinlock for reading, if available.
If the rw_spinlock is not currently write locked, add a read lock on it and return true. Otherwise, return false.
There can be multiple readers at the same time on an rw_spinlock, but there can be only one writer.
bool try_acquire_write_seqlock | ( | seqlock * | lock | ) |
Acquire a seqlock for writing, without waiting.
A seqlock is similar to an rw_spinlock in that it can be locked separately for reading and writing. However, it avoids writer starvation problems (when there are always reads being done and a writer can never acquire the write lock).
To achieve this, the readers are not actually locked. Instead, they are allowed to read the protected resource even while it is being written. The writer increments a counter whenever it acquires and releases the lock. When releasing a read lock, a reader can use this counter to compare against the value when it acquired its read lock. If the counter changed, that means there was a concurrent write access, and the read data is invalid. The reader can try to acquire a read lock again and read the updated value of the data.
bool try_acquire_write_spinlock | ( | rw_spinlock * | lock | ) |
Acquire a rw_spinlock for writing, if available.
Check if no other thread is holding the lock, and in that case, acquires it immediately. Otherwise, return false. There is no wait for the rw_spinlock to become available.
Interrupts must be disabled, and recursive locking is not allowed.
status_t user_memcpy | ( | void * | to, |
const void * | from, | ||
size_t | size | ||
) |
Copy memory between userspace and kernelspace.
There are protections in place to avoid the kernel accidentally reading or writing to userspace memory. As a result, every access to userspace memory must be done with user_memcpy, user_strlcpy or user_memset.
For example, the buffers for a read, write or ioctl operation are handled in this way.
status_t user_memset | ( | void * | start, |
char | c, | ||
size_t | count | ||
) |
Set userspace memory.
Set memory to a specific byte value in the current userspace team.
ssize_t user_strlcpy | ( | char * | to, |
const char * | from, | ||
size_t | size | ||
) |
Copy a string between userspace and kernel space.
Similar to strlcpy, but one of the source and destination must be in kernel space, and the other must be in userspace.