summaryrefslogtreecommitdiffstats
path: root/include/linux/idr.h
blob: 8a0f452d766d0ac9d56c1cc0202f318bdb2f69b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * include/linux/idr.h
 * 
 * 2002-10-18  written by Jim Houston jim.houston@ccur.com
 *	Copyright (C) 2002 by Concurrent Computer Corporation
 *
 * Small id to pointer translation service avoiding fixed sized
 * tables.
 */

#ifndef __IDR_H__
#define __IDR_H__

#include <errno.h>
#include <linux/list.h>

struct idr {
	int			id;
	void			*ptr;
	struct list_head	list;
};

#define DEFINE_IDR(name)	\
	struct idr name = { .list = LIST_HEAD_INIT((name).list) }

#define __idr_for_each_entry(head, idr) \
	list_for_each_entry((idr), &(head)->list, list)

static inline struct idr *__idr_find(struct idr *head, int id)
{
	struct idr *idr;

	__idr_for_each_entry(head, idr) {
		if (idr->id == id)
			return idr;
	}

	return NULL;
}

static inline void *idr_find(struct idr *head, int id)
{
	struct idr *idr = __idr_find(head, id);

	return idr ? idr->ptr : NULL;
}

static inline int idr_alloc_one(struct idr *head, void *ptr, int start)
{
	struct idr *idr;

	if (__idr_find(head, start))
		return -EBUSY;

	idr = malloc(sizeof(*idr));

	idr->id = start;
	idr->ptr = ptr;

	list_add(&idr->list, &head->list);

	return start;
}

static inline void idr_init(struct idr *idr)
{
	INIT_LIST_HEAD(&idr->list);
}

static inline void idr_remove(struct idr *head, int id)
{
	struct idr *idr = __idr_find(head, id);

	list_del(&idr->list);
	free(idr);
}

#endif /* __IDR_H__ */