33#include <sys/kernel.h>
35#include <sys/sysctl.h>
38#include <sys/malloc.h>
41#include <sys/rmlock.h>
60 osd_destructor_t *osd_destructors;
61 osd_method_t *osd_methods;
63 const u_int osd_nmethods;
71#define OSD_DEBUG(...) do { \
73 printf("OSD (%s:%u): ", __func__, __LINE__); \
74 printf(__VA_ARGS__); \
86 [OSD_JAIL] = { .osd_nmethods = PR_MAXMETHOD },
101 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
107 if (destructor == NULL)
114 for (i = 0; i <
osdm[
type].osd_ntslots; i++) {
115 if (
osdm[
type].osd_destructors[i] == NULL) {
116 OSD_DEBUG(
"Unused slot found (type=%u, slot=%u).",
128 sizeof(osd_method_t) *
osdm[
type].osd_ntslots *
129 osdm[
type].osd_nmethods, M_OSD, M_WAITOK);
130 newptr =
malloc(
sizeof(osd_destructor_t) *
131 osdm[
type].osd_ntslots, M_OSD, M_WAITOK);
133 bcopy(
osdm[
type].osd_destructors, newptr,
134 sizeof(osd_destructor_t) * i);
136 osdm[
type].osd_destructors = newptr;
138 OSD_DEBUG(
"New slot allocated (type=%u, slot=%u).",
142 osdm[
type].osd_destructors[i] = destructor;
144 for (m = 0; m <
osdm[
type].osd_nmethods; m++)
146 = methods != NULL ? methods[m] : NULL;
155 struct osd *osd, *tosd;
157 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
158 KASSERT(slot > 0, (
"Invalid slot."));
160 sx_xlock(&
osdm[
type].osd_module_lock);
161 rm_wlock(&
osdm[
type].osd_object_lock);
162 KASSERT(
osdm[
type].osd_destructors[slot - 1] != NULL, (
"Unused slot."));
167 mtx_lock(&
osdm[
type].osd_list_lock);
168 LIST_FOREACH_SAFE(osd, &
osdm[
type].osd_list, osd_next, tosd)
170 mtx_unlock(&
osdm[
type].osd_list_lock);
174 osdm[
type].osd_destructors[slot - 1] = NULL;
175 if (slot ==
osdm[
type].osd_ntslots) {
178 sizeof(osd_destructor_t) *
osdm[
type].osd_ntslots, M_OSD,
182 sizeof(osd_method_t) *
osdm[
type].osd_ntslots *
183 osdm[
type].osd_nmethods, M_OSD, M_NOWAIT | M_ZERO);
188 KASSERT(
osdm[
type].osd_destructors != NULL &&
190 osdm[
type].osd_methods != NULL), (
"realloc() failed"));
191 OSD_DEBUG(
"Deregistration of the last slot (type=%u, slot=%u).",
194 OSD_DEBUG(
"Slot deregistration (type=%u, slot=%u).",
197 rm_wunlock(&
osdm[
type].osd_object_lock);
198 sx_xunlock(&
osdm[
type].osd_module_lock);
212 KASSERT(slot > 0, (
"Invalid slot."));
214 OSD_DEBUG(
"Reserving slot array (slot=%u).", slot);
215 return (
malloc(
sizeof(
void *) * slot, M_OSD, M_WAITOK | M_ZERO));
222 struct rm_priotracker tracker;
224 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
225 KASSERT(slot > 0, (
"Invalid slot."));
227 rm_rlock(&
osdm[
type].osd_object_lock, &tracker);
228 KASSERT(
osdm[
type].osd_destructors[slot - 1] != NULL, (
"Unused slot."));
230 if (slot > osd->osd_nslots) {
235 "Not allocating null slot (type=%u, slot=%u).",
237 rm_runlock(&
osdm[
type].osd_object_lock, &tracker);
253 if (osd->osd_nslots != 0) {
254 memcpy(newptr, osd->osd_slots,
255 sizeof(
void *) * osd->osd_nslots);
256 free(osd->osd_slots, M_OSD);
259 newptr =
realloc(osd->osd_slots,
sizeof(
void *) * slot,
260 M_OSD, M_NOWAIT | M_ZERO);
261 if (newptr == NULL) {
262 rm_runlock(&
osdm[
type].osd_object_lock,
267 if (osd->osd_nslots == 0) {
272 mtx_lock(&
osdm[
type].osd_list_lock);
273 LIST_INSERT_HEAD(&
osdm[
type].osd_list, osd, osd_next);
274 mtx_unlock(&
osdm[
type].osd_list_lock);
278 osd->osd_slots = newptr;
279 osd->osd_nslots = slot;
282 OSD_DEBUG(
"Setting slot value (type=%u, slot=%u, value=%p).",
type,
284 osd->osd_slots[slot - 1] =
value;
285 rm_runlock(&
osdm[
type].osd_object_lock, &tracker);
293 OSD_DEBUG(
"Discarding reserved slot array.");
300 struct rm_priotracker tracker;
303 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
304 KASSERT(slot > 0, (
"Invalid slot."));
306 rm_rlock(&
osdm[
type].osd_object_lock, &tracker);
307 KASSERT(
osdm[
type].osd_destructors[slot - 1] != NULL, (
"Unused slot."));
309 if (slot > osd->osd_nslots) {
311 OSD_DEBUG(
"Slot doesn't exist (type=%u, slot=%u).",
type, slot);
313 value = osd->osd_slots[slot - 1];
314 OSD_DEBUG(
"Returning slot value (type=%u, slot=%u, value=%p).",
317 rm_runlock(&
osdm[
type].osd_object_lock, &tracker);
324 struct rm_priotracker tracker;
326 rm_rlock(&
osdm[
type].osd_object_lock, &tracker);
328 rm_runlock(&
osdm[
type].osd_object_lock, &tracker);
336 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
337 KASSERT(slot > 0, (
"Invalid slot."));
338 KASSERT(
osdm[
type].osd_destructors[slot - 1] != NULL, (
"Unused slot."));
342 if (slot > osd->osd_nslots) {
343 OSD_DEBUG(
"Slot doesn't exist (type=%u, slot=%u).",
type, slot);
346 if (osd->osd_slots[slot - 1] != NULL) {
347 osdm[
type].osd_destructors[slot - 1](osd->osd_slots[slot - 1]);
348 osd->osd_slots[slot - 1] = NULL;
350 for (i = osd->osd_nslots - 1; i >= 0; i--) {
351 if (osd->osd_slots[i] != NULL) {
352 OSD_DEBUG(
"Slot still has a value (type=%u, slot=%u).",
361 mtx_lock(&
osdm[
type].osd_list_lock);
362 LIST_REMOVE(osd, osd_next);
364 mtx_unlock(&
osdm[
type].osd_list_lock);
365 free(osd->osd_slots, M_OSD);
366 osd->osd_slots = NULL;
368 }
else if (slot == osd->osd_nslots) {
370 osd->osd_slots =
realloc(osd->osd_slots,
371 sizeof(
void *) * (i + 1), M_OSD, M_NOWAIT | M_ZERO);
376 KASSERT(osd->osd_slots != NULL, (
"realloc() failed"));
377 osd->osd_nslots = i + 1;
378 OSD_DEBUG(
"Reducing slots array to %u (type=%u).",
379 osd->osd_nslots,
type);
386 osd_method_t methodfun;
389 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
390 KASSERT(method <
osdm[
type].osd_nmethods, (
"Invalid method."));
397 sx_slock(&
osdm[
type].osd_module_lock);
398 for (i = 0; i <
osdm[
type].osd_ntslots; i++) {
401 if (methodfun != NULL && (error = methodfun(obj,
data)) != 0)
404 sx_sunlock(&
osdm[
type].osd_module_lock);
411 struct rm_priotracker tracker;
414 KASSERT(
type >= OSD_FIRST &&
type <= OSD_LAST, (
"Invalid type."));
416 if (osd->osd_nslots == 0) {
417 KASSERT(osd->osd_slots == NULL, (
"Non-null osd_slots."));
422 rm_rlock(&
osdm[
type].osd_object_lock, &tracker);
423 for (i = 1; i <= osd->osd_nslots; i++) {
424 if (
osdm[
type].osd_destructors[i - 1] != NULL)
429 rm_runlock(&
osdm[
type].osd_object_lock, &tracker);
438 for (i = OSD_FIRST; i <= OSD_LAST; i++) {
439 sx_init(&
osdm[i].osd_module_lock,
"osd_module");
441 mtx_init(&
osdm[i].osd_list_lock,
"osd_list", NULL, MTX_DEF);
442 LIST_INIT(&
osdm[i].osd_list);
443 osdm[i].osd_destructors = NULL;
444 osdm[i].osd_ntslots = 0;
445 osdm[i].osd_methods = NULL;
device_property_type_t type
void *() malloc(size_t size, struct malloc_type *mtp, int flags)
void * realloc(void *addr, size_t size, struct malloc_type *mtp, int flags)
void free(void *addr, struct malloc_type *mtp)
static void osd_default_destructor(void *value __unused)
int osd_register(u_int type, osd_destructor_t destructor, osd_method_t *methods)
int osd_set(u_int type, struct osd *osd, u_int slot, void *value)
void osd_deregister(u_int type, u_int slot)
void osd_free_reserved(void **rsv)
void osd_del(u_int type, struct osd *osd, u_int slot)
struct osd_master osdm[OSD_LAST+1]
void ** osd_reserve(u_int slot)
static MALLOC_DEFINE(M_OSD, "osd", "Object Specific Data")
SYSCTL_INT(_debug, OID_AUTO, osd, CTLFLAG_RWTUN, &osd_debug, 0, "OSD debug level")
void * osd_get(u_int type, struct osd *osd, u_int slot)
int osd_call(u_int type, u_int method, void *obj, void *data)
static void do_osd_del(u_int type, struct osd *osd, u_int slot, int list_locked)
static void osd_init(void *arg __unused)
int osd_set_reserved(u_int type, struct osd *osd, u_int slot, void **rsv, void *value)
SYSINIT(osd, SI_SUB_LOCK, SI_ORDER_ANY, osd_init, NULL)
void osd_exit(u_int type, struct osd *osd)
void rm_init(struct rmlock *rm, const char *name)
struct rmlock osd_object_lock
struct sx osd_module_lock