PSERIALIZE(9) | Kernel Developer's Manual | PSERIALIZE(9) |
pserialize
—
#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);
IPL_SOFTCLOCK
.
pserialize_create
()pserialize_destroy
()pserialize_read_enter
()pserialize_read_exit
()pserialize_perform
()struct frotz { ... struct frotz *f_next; }; static struct { kmutex_t lock; pserialize_t psz; struct frotz *first; } frobbotzim __cacheline_aligned;
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.first; /* * Publish the contents of f->f_next before we publish the * pointer to f in frobbotzim.first. */ membar_producer(); frobbotzim.first = 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.first; f != NULL; f = f->f_next) { /* Fetch f before we fetch anything f points to. */ membar_datadep_consumer(); if (f->f_... == key) { /* * Grab whatever part of the frotz we need. * Note that we can't use the frotz after * pserialize_read_exit, without a stronger * kind of reference, say a reference count * managed by atomic_ops(3). */ *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.first; (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);
pserialize
is implemented within the file
sys/kern/subr_pserialize.c.
Hennessy, et al., Passive serialization in a multitasking environment, US Patent and Trademark Office, US Patent 4809168, February 28, 1989.
January 26, 2016 | NetBSD 9.0 |