3de09a8310ebb26e5e5b2c90056234436573f05b
[lttng-tools.git] / src / common / index-allocator.c
1 /*
2 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include <assert.h>
9 #include <inttypes.h>
10
11 #include <urcu.h>
12 #include <urcu/list.h>
13
14 #include "macros.h"
15 #include "error.h"
16
17 #include "index-allocator.h"
18
19 struct lttng_index_allocator {
20 struct cds_list_head unused_list;
21 uint64_t size;
22 uint64_t position;
23 };
24
25 struct lttng_index {
26 uint64_t index;
27 struct cds_list_head head;
28 };
29
30 struct lttng_index_allocator *lttng_index_allocator_create(
31 uint64_t index_count)
32 {
33 struct lttng_index_allocator *allocator = NULL;
34
35 allocator = zmalloc(sizeof(*allocator));
36 if (!allocator) {
37 PERROR("Failed to allocate index allocator");
38 goto end;
39 }
40
41 allocator->size = index_count;
42 allocator->position = 0;
43
44 CDS_INIT_LIST_HEAD(&allocator->unused_list);
45
46 end:
47 return allocator;
48 }
49
50 uint64_t lttng_index_allocator_get_index_count(struct lttng_index_allocator *allocator)
51 {
52 return allocator->size;
53 }
54
55 enum lttng_index_allocator_status lttng_index_allocator_alloc(
56 struct lttng_index_allocator *allocator,
57 uint64_t *allocated_index)
58 {
59 enum lttng_index_allocator_status status =
60 LTTNG_INDEX_ALLOCATOR_STATUS_OK;
61
62 if (cds_list_empty(&allocator->unused_list)) {
63 if (allocator->position >= allocator->size) {
64 /* No indices left. */
65 status = LTTNG_INDEX_ALLOCATOR_STATUS_EMPTY;
66 goto end;
67 }
68
69 *allocated_index = allocator->position++;
70 } else {
71 struct lttng_index *index;
72
73 index = cds_list_first_entry(&allocator->unused_list,
74 typeof(*index), head);
75 cds_list_del(&index->head);
76 *allocated_index = index->index;
77 free(index);
78 }
79
80 end:
81 return status;
82 }
83
84 enum lttng_index_allocator_status lttng_index_allocator_release(
85 struct lttng_index_allocator *allocator, uint64_t idx)
86 {
87 struct lttng_index *index = NULL;
88 enum lttng_index_allocator_status status =
89 LTTNG_INDEX_ALLOCATOR_STATUS_OK;
90
91 assert(idx < allocator->size);
92
93 index = zmalloc(sizeof(*index));
94 if (!index) {
95 PERROR("Failed to allocate free index queue");
96 status = LTTNG_INDEX_ALLOCATOR_STATUS_ERROR;
97 goto end;
98 }
99
100 index->index = idx;
101 cds_list_add_tail(&index->head, &allocator->unused_list);
102
103 end:
104 return status;
105 }
106
107 void lttng_index_allocator_destroy(struct lttng_index_allocator *allocator)
108 {
109 struct lttng_index *index = NULL, *tmp_index = NULL;
110
111 if (!allocator) {
112 return;
113 }
114
115 if (lttng_index_allocator_get_index_count(allocator) > 0) {
116 WARN("Destroying index allocator with %" PRIu64
117 " slot indexes still in use",
118 lttng_index_allocator_get_index_count(allocator));
119 }
120
121 cds_list_for_each_entry_safe(index, tmp_index,
122 &allocator->unused_list, head) {
123 cds_list_del(&index->head);
124 free(index);
125 }
126
127 free(allocator);
128 }
This page took 0.030604 seconds and 3 git commands to generate.