Loading...
Searching...
No Matches
Functions
KernelExport.h File Reference

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.
 

Detailed Description

Interfaces for drivers code running in kernel space.

Function Documentation

◆ acquire_read_seqlock()

uint32 acquire_read_seqlock ( seqlock *  lock)

Prepare for read access to data protected by a seqlock.

Returns
The counter value of the seqlock, at the time of locking, to be passed to release_read_seqlock.

◆ acquire_read_spinlock()

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.

◆ acquire_spinlock()

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().

◆ acquire_write_seqlock()

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.

◆ acquire_write_spinlock()

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().

◆ add_debugger_command()

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.

◆ add_timer()

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.

Parameters
flagsIf 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.
flagsIf B_TIMER_USE_TIMER_STRUCT_TIMES, use the period defined by t instead of period.

◆ disable_interrupts()

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.

Returns
The previous state of interrupts, which should be passed to restore_interrupts

◆ lock_memory_etc()

status_t lock_memory_etc ( team_id  team,
void *  buffer,
size_t  numBytes,
uint32  flags 
)

Lock memory pages into RAM.

Lock a memory area and prevent accesses from other parts of the system. This establishes the following:

  • The memory is mapped into physical RAM (moved out of swap or committed if needed)
  • No other thread can lock an overlapping memory range

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.

◆ map_physical_memory()

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.

◆ memory_read_barrier()

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.

◆ memory_write_barrier()

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.

◆ parse_expression()

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.

◆ release_read_seqlock()

bool release_read_seqlock ( seqlock *  lock,
uint32  count 
)

Release a read lock and check if the read operation was successful.

Parameters
countThe lock count value returned by the correspondin acquire_read_seqlock
Returns
true if there were no write access while the lock was read-locked, false otherwise.

◆ release_spinlock()

void release_spinlock ( spinlock *  lock)

Release a previously acquired spinlock.

This will unblock any thread that is waiting on the spinlock.

◆ release_write_seqlock()

void release_write_seqlock ( seqlock *  lock)

Release a write lock on a seqlock.

This increments the counter before releasing the lock.

◆ remove_debugger_command()

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.

◆ restore_interrupts()

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.

◆ set_dprintf_enabled()

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.

◆ spawn_kernel_thread()

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.

◆ spin()

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.

◆ try_acquire_read_spinlock()

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.

◆ try_acquire_write_seqlock()

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.

◆ try_acquire_write_spinlock()

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.

◆ user_memcpy()

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.

◆ user_memset()

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.

◆ user_strlcpy()

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.