mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Add more IDR and IDA related functions to the LinuxKPI.
Obtained from: kmacy @ MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
f8221002a5
commit
fd42d62378
2 changed files with 179 additions and 2 deletions
|
|
@ -63,15 +63,23 @@ struct idr {
|
|||
int next_cyclic_id;
|
||||
};
|
||||
|
||||
#define DEFINE_IDR(name) \
|
||||
/* NOTE: It is the applications responsibility to destroy the IDR */
|
||||
#define DEFINE_IDR(name) \
|
||||
struct idr name; \
|
||||
SYSINIT(name##_idr_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, \
|
||||
idr_init, &(name));
|
||||
idr_init, &(name))
|
||||
|
||||
/* NOTE: It is the applications responsibility to destroy the IDA */
|
||||
#define DEFINE_IDA(name) \
|
||||
struct ida name; \
|
||||
SYSINIT(name##_ida_sysinit, SI_SUB_DRIVERS, SI_ORDER_FIRST, \
|
||||
ida_init, &(name))
|
||||
|
||||
#define idr_preload(x) do { } while (0)
|
||||
#define idr_preload_end() do { } while (0)
|
||||
|
||||
void *idr_find(struct idr *idp, int id);
|
||||
void *idr_get_next(struct idr *idp, int *nextid);
|
||||
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
|
||||
int idr_get_new(struct idr *idp, void *ptr, int *id);
|
||||
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
|
||||
|
|
@ -82,5 +90,39 @@ void idr_destroy(struct idr *idp);
|
|||
void idr_init(struct idr *idp);
|
||||
int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t);
|
||||
int idr_alloc_cyclic(struct idr *idp, void *ptr, int start, int end, gfp_t);
|
||||
int idr_for_each(struct idr *idp, int (*fn)(int id, void *p, void *data), void *data);
|
||||
|
||||
#define idr_for_each_entry(idp, entry, id) \
|
||||
for ((id) = 0; ((entry) = idr_get_next(idp, &(id))) != NULL; ++(id))
|
||||
|
||||
#define IDA_CHUNK_SIZE 128 /* 128 bytes per chunk */
|
||||
#define IDA_BITMAP_LONGS (IDA_CHUNK_SIZE / sizeof(long) - 1)
|
||||
#define IDA_BITMAP_BITS (IDA_BITMAP_LONGS * sizeof(long) * 8)
|
||||
|
||||
struct ida_bitmap {
|
||||
long nr_busy;
|
||||
unsigned long bitmap[IDA_BITMAP_LONGS];
|
||||
};
|
||||
|
||||
struct ida {
|
||||
struct idr idr;
|
||||
struct ida_bitmap *free_bitmap;
|
||||
};
|
||||
|
||||
int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
|
||||
int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
|
||||
void ida_remove(struct ida *ida, int id);
|
||||
void ida_destroy(struct ida *ida);
|
||||
void ida_init(struct ida *ida);
|
||||
|
||||
int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
|
||||
gfp_t gfp_mask);
|
||||
void ida_simple_remove(struct ida *ida, unsigned int id);
|
||||
|
||||
static inline int
|
||||
ida_get_new(struct ida *ida, int *p_id)
|
||||
{
|
||||
return (ida_get_new_above(ida, 0, p_id));
|
||||
}
|
||||
|
||||
#endif /* _LINUX_IDR_H_ */
|
||||
|
|
|
|||
|
|
@ -227,6 +227,24 @@ idr_find(struct idr *idr, int id)
|
|||
return (res);
|
||||
}
|
||||
|
||||
void *
|
||||
idr_get_next(struct idr *idr, int *nextidp)
|
||||
{
|
||||
void *res = NULL;
|
||||
int id = *nextidp;
|
||||
|
||||
mtx_lock(&idr->lock);
|
||||
for (; id <= idr_max(idr); id++) {
|
||||
res = idr_find_locked(idr, id);
|
||||
if (res == NULL)
|
||||
continue;
|
||||
*nextidp = id;
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&idr->lock);
|
||||
return (res);
|
||||
}
|
||||
|
||||
int
|
||||
idr_pre_get(struct idr *idr, gfp_t gfp_mask)
|
||||
{
|
||||
|
|
@ -487,6 +505,12 @@ idr_get_new_above(struct idr *idr, void *ptr, int starting_id, int *idp)
|
|||
return (retval);
|
||||
}
|
||||
|
||||
int
|
||||
ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
|
||||
{
|
||||
return (idr_get_new_above(&ida->idr, NULL, starting_id, p_id));
|
||||
}
|
||||
|
||||
static int
|
||||
idr_alloc_locked(struct idr *idr, void *ptr, int start, int end)
|
||||
{
|
||||
|
|
@ -540,3 +564,114 @@ idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
|
|||
mtx_unlock(&idr->lock);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static int
|
||||
idr_for_each_layer(struct idr_layer *il, int layer,
|
||||
int (*f)(int id, void *p, void *data), void *data)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
if (il == NULL)
|
||||
return (0);
|
||||
if (layer == 0) {
|
||||
for (i = 0; i < IDR_SIZE; i++) {
|
||||
if (il->ary[i] == NULL)
|
||||
continue;
|
||||
err = f(i, il->ary[i], data);
|
||||
if (err)
|
||||
return (err);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; i < IDR_SIZE; i++) {
|
||||
if (il->ary[i] == NULL)
|
||||
continue;
|
||||
err = idr_for_each_layer(il->ary[i], layer - 1, f, data);
|
||||
if (err)
|
||||
return (err);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
idr_for_each(struct idr *idp, int (*f)(int id, void *p, void *data), void *data)
|
||||
{
|
||||
int err;
|
||||
|
||||
mtx_lock(&idp->lock);
|
||||
err = idr_for_each_layer(idp->top, idp->layers - 1, f, data);
|
||||
mtx_unlock(&idp->lock);
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
ida_pre_get(struct ida *ida, gfp_t flags)
|
||||
{
|
||||
if (idr_pre_get(&ida->idr, flags) == 0)
|
||||
return (0);
|
||||
|
||||
if (ida->free_bitmap == NULL) {
|
||||
ida->free_bitmap =
|
||||
malloc(sizeof(struct ida_bitmap), M_IDR, flags);
|
||||
}
|
||||
return (ida->free_bitmap != NULL);
|
||||
}
|
||||
|
||||
int
|
||||
ida_simple_get(struct ida *ida, unsigned int start, unsigned int end,
|
||||
gfp_t flags)
|
||||
{
|
||||
int ret, id;
|
||||
unsigned int max;
|
||||
|
||||
MPASS((int)start >= 0);
|
||||
MPASS((int)end >= 0);
|
||||
|
||||
if (end == 0)
|
||||
max = 0x80000000;
|
||||
else {
|
||||
MPASS(end > start);
|
||||
max = end - 1;
|
||||
}
|
||||
again:
|
||||
if (!ida_pre_get(ida, flags))
|
||||
return (-ENOMEM);
|
||||
|
||||
if ((ret = ida_get_new_above(ida, start, &id)) == 0) {
|
||||
if (id > max) {
|
||||
ida_remove(ida, id);
|
||||
ret = -ENOSPC;
|
||||
} else {
|
||||
ret = id;
|
||||
}
|
||||
}
|
||||
if (__predict_false(ret == -EAGAIN))
|
||||
goto again;
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
ida_simple_remove(struct ida *ida, unsigned int id)
|
||||
{
|
||||
idr_remove(&ida->idr, id);
|
||||
}
|
||||
|
||||
void
|
||||
ida_remove(struct ida *ida, int id)
|
||||
{
|
||||
idr_remove(&ida->idr, id);
|
||||
}
|
||||
|
||||
void
|
||||
ida_init(struct ida *ida)
|
||||
{
|
||||
idr_init(&ida->idr);
|
||||
}
|
||||
|
||||
void
|
||||
ida_destroy(struct ida *ida)
|
||||
{
|
||||
idr_destroy(&ida->idr);
|
||||
free(ida->free_bitmap, M_IDR);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue