Manual browser: pserialize_read_exit(9)
PSERIALIZE(9) | Kernel Developer's Manual | PSERIALIZE(9) |
NAME
pserialize — passive serialization mechanismSYNOPSIS
#include <sys/pserialize.h>
pserialize_t
pserialize_create(void);
void
pserialize_destroy(pserialize_t psz);
int
pserialize_read_enter(void);
void
pserialize_read_exit(int s);
void
pserialize_perform(pserialize_t psz);
DESCRIPTION
Passive serialization is a reader / writer synchronisation mechanism designed for lock-less read operations. The read operations may happen from software interrupt at IPL_SOFTCLOCK.FUNCTIONS
- pserialize_create()
- Allocate a new synchronisation object.
- pserialize_destroy()
- Destroy the synchronisation object. No synchronisation activity should happen at this point.
- pserialize_read_enter()
- Enter the critical path of the reader side. Returns an IPL value, which must be passed to pserialize_read_exit(9). Protected code path is not allowed to block.
- pserialize_read_exit()
- Exit the critical path of the reader side. Takes the IPL value returned by pserialize_read_enter(9).
- pserialize_perform()
- Perform the passive serialization on the writer side. Passing of this function ensures that no readers are in action. Writers must be additionally serialized with a separate mechanism, e.g. mutex(9). Operation blocks and it may only be performed from thread context.
EXAMPLES
Given a global database of frotz records:
struct frotz { ... struct frotz *f_next; }; kmutex_t frobbotzim_lock; struct frotz *frobbotzim; pserialize_t frobbotzim_psz;
Create a frotz and publish it, as a writer:
struct frotz *f = pool_get(&frotz_pool, PR_WAITOK); /* Initialize f. */ ... mutex_enter(&frobbotzim_lock); f->f_next = frobbotzim; /* * Publish the contents of f->f_next before we publish the * pointer to f in frobbotzim. */ membar_producer(); frobbotzim = f; mutex_exit(&frobbotzim_lock);
Find a frotz, as a reader:
struct frotz *f; int error = ENOENT; int s; s = pserialize_read_enter(); for (f = frobbotzim; f != NULL; f = f->f_next) { /* Fetch f before we fetch anything f points to. */ membar_consumer(); if (f->f_... = key) { *resultp = f->f_...; error = 0; break; } } pserialize_read_exit(s); return error;
Remove a frotz, as a writer, and free it once there are no more readers:
struct frotz **fp, *f; mutex_enter(&frobbotzim_lock); for (fp = &frobbotzim; (f = *fp) != NULL; fp = &f->f_next) { if (f->f_... == key) { /* * Unhook it from the list. Readers may still * be traversing the list at this point, so * the next pointer must remain valid and * memory must remain allocated. */ *fp = f->f_next; break; } } /* * Wait for all existing readers to complete. New readers will * not see f because the list no longer points to it. */ pserialize_perform(frobbotzim_psz); /* Now nobody else can be touching f, so it is safe to free. */ mutex_exit(&frobbotzim_lock); if (f != NULL) pool_put(&frotz_pool, f);
CODE REFERENCES
The pserialize is implemented within the file sys/kern/subr_pserialize.c.SEE ALSO
membar_ops(3), condvar(9), mutex(9), rwlock(9)Hennessy, et al., Passive serialization in a multitasking environment, US Patent and Trademark Office, US Patent 4809168, February 28, 1989.
HISTORY
Passive serialization mechanism first appeared in NetBSD 6.0.November 21, 2014 | NetBSD 7.0 |