Lunatik

rcuModule

RCU-synchronized hash table.

Provides a concurrent hash table using Read-Copy-Update (RCU) synchronization. Reads are lockless; writes are serialized. Keys are strings, and a number key is its decimal string, so t[1] and t["1"] are one entry; values can be booleans, integers, shareable lunatik objects, or nil (to delete an entry). A SINGLE object, such as a device, a probe or a hid driver, raises cannot share SINGLE object, and a string or a table raises unsupported type. Reading an object returns a new handle on the same kernel object, so two reads of an entry compare unequal; from a softirq or hardirq runtime, one whose class needs process context raises '<class>': process-context class in interrupt-context runtime. A read that meets a writer releasing the entry’s object sees the entry gone. An entry holds its object until the entry is overwritten or deleted or the table goes, and a reference count does not see a cycle, so storing an rcu.table raises ELOOP when it is the table it is stored in or reaches that table, directly or through the tables it holds; it raises ELOOP too when it reaches more than 16 tables that hold tables, itself included.

A table a probe handler writes is not written from another runtime with interrupts on: the writer takes the table’s lock with interrupts off only when they already are, so a probe that fires inside an interrupt handler on the CPU of a process or softirq writer spins on the lock that writer holds.

See examples/shared/daemon.lua for a practical example.

rcu

foreach (t, callback) Iterates over the table calling callback(key, value) for each entry.
table ([size=256]) Creates a new RCU hash table.

rcu in detail

foreach (t, callback)
Iterates over the table calling callback(key, value) for each entry. What the callback returns is ignored: it stops the walk early by raising an error. The walk runs inside an SRCU read-side critical section, which allows the callback to sleep; whether it may is its runtime’s context, as for any code of a softirq or hardirq runtime. A writer on any runtime may change the table meanwhile: an entry removed or replaced under the walk may still be reached and is then skipped, one added is visited only if its bucket is still ahead, and the order is not guaranteed.

Parameters

  • t rcu_table the table to walk
  • callback function function(key, value); an entry whose object a writer is releasing is skipped.

Raises

Error if callback raises.

Usage

rcu.foreach(t, function (key, value) print(key, value) end)
table ([size=256])
Creates a new RCU hash table.

Parameters

  • size integer Number of hash buckets (rounded up to power of two), from 1 up to the largest count whose table size does not overflow; what memory serves is the allocator’s. (default 256)

Returns

    rcu_table

Raises

if out of bounds or the allocation fails

Usage

local t = rcu.table()      -- 256 buckets (default)
local t = rcu.table(8192)  -- 8192 buckets