Add unused attribute to prio heap parent
[lttng-modules.git] / lib / prio_heap / prio_heap.c
CommitLineData
f3bc08c5 1/*
162769ef
MD
2 * prio_heap.c
3 *
7369e702 4 * Priority heap containing pointers. Based on CLRS, chapter 6.
162769ef
MD
5 *
6 * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
f3bc08c5
MD
17 */
18
19#include <linux/slab.h>
7369e702 20#include "prio_heap.h"
f3bc08c5 21
8bb0ebb3 22static __attribute__((unused))
7369e702 23size_t parent(size_t i)
c9891db2 24{
7369e702
MD
25 return i >> 1;
26}
27
28static
29size_t left(size_t i)
30{
31 return i << 1;
32}
33
34static
35size_t right(size_t i)
36{
37 return (i << 1) + 1;
38}
39
40static
41int heap_grow(struct ptr_heap *heap, size_t new_len)
42{
43 void **new_ptrs;
44
45 if (heap->alloc_len >= new_len)
46 return 0;
47
48 heap->alloc_len = max_t(size_t, new_len, heap->alloc_len << 1);
49 new_ptrs = kmalloc(heap->alloc_len * sizeof(void *), heap->gfpmask);
50 if (!new_ptrs)
c9891db2 51 return -ENOMEM;
7369e702
MD
52 if (heap->ptrs)
53 memcpy(new_ptrs, heap->ptrs, heap->len * sizeof(void *));
54 kfree(heap->ptrs);
55 heap->ptrs = new_ptrs;
56 return 0;
57}
58
59static
60int heap_set_len(struct ptr_heap *heap, size_t new_len)
61{
62 int ret;
63
64 ret = heap_grow(heap, new_len);
65 if (ret)
66 return ret;
67 heap->len = new_len;
c9891db2
MD
68 return 0;
69}
70
7369e702
MD
71int heap_init(struct ptr_heap *heap, size_t alloc_len,
72 gfp_t gfpmask, int gt(void *a, void *b))
73{
74 heap->ptrs = NULL;
75 heap->len = 0;
76 heap->alloc_len = 0;
77 heap->gt = gt;
78 /*
79 * Minimum size allocated is 1 entry to ensure memory allocation
80 * never fails within heap_replace_max.
81 */
c8d547f0 82 return heap_grow(heap, max_t(size_t, 1, alloc_len));
7369e702
MD
83}
84
c9891db2
MD
85void heap_free(struct ptr_heap *heap)
86{
87 kfree(heap->ptrs);
88}
f3bc08c5 89
7369e702 90static void heapify(struct ptr_heap *heap, size_t i)
f3bc08c5 91{
7369e702
MD
92 void **ptrs = heap->ptrs;
93 size_t l, r, largest;
94
95 for (;;) {
96 l = left(i);
97 r = right(i);
98 if (l <= heap->len && ptrs[l] > ptrs[i])
99 largest = l;
100 else
101 largest = i;
102 if (r <= heap->len && ptrs[r] > ptrs[largest])
103 largest = r;
104 if (largest != i) {
105 void *tmp;
106
107 tmp = ptrs[i];
108 ptrs[i] = ptrs[largest];
109 ptrs[largest] = tmp;
110 i = largest;
111 continue;
112 } else {
113 break;
114 }
115 }
f3bc08c5
MD
116}
117
118void *heap_replace_max(struct ptr_heap *heap, void *p)
119{
120 void *res;
121 void **ptrs = heap->ptrs;
122
7369e702
MD
123 if (!heap->len) {
124 (void) heap_set_len(heap, 1);
f3bc08c5 125 ptrs[0] = p;
f3bc08c5
MD
126 return NULL;
127 }
128
129 /* Replace the current max and heapify */
130 res = ptrs[0];
131 ptrs[0] = p;
132 heapify(heap, 0);
133 return res;
134}
135
7369e702 136int heap_insert(struct ptr_heap *heap, void *p)
c9891db2
MD
137{
138 void **ptrs = heap->ptrs;
7369e702 139 int ret;
c9891db2 140
7369e702
MD
141 ret = heap_set_len(heap, heap->len + 1);
142 if (ret)
143 return ret;
144 /* Add the element to the end */
145 ptrs[heap->len - 1] = p;
146 /* rebalance */
147 heapify(heap, 0);
148 return 0;
c9891db2
MD
149}
150
f3bc08c5
MD
151void *heap_remove(struct ptr_heap *heap)
152{
153 void **ptrs = heap->ptrs;
154
7369e702 155 switch (heap->len) {
f3bc08c5
MD
156 case 0:
157 return NULL;
158 case 1:
7369e702 159 (void) heap_set_len(heap, 0);
f3bc08c5
MD
160 return ptrs[0];
161 }
f3bc08c5 162 /* Shrink, replace the current max by previous last entry and heapify */
7369e702
MD
163 heap_set_len(heap, heap->len - 1);
164 return heap_replace_max(heap, ptrs[heap->len - 1]);
f3bc08c5
MD
165}
166
167void *heap_cherrypick(struct ptr_heap *heap, void *p)
168{
169 void **ptrs = heap->ptrs;
7369e702 170 size_t pos, len = heap->len;
f3bc08c5 171
7369e702 172 for (pos = 0; pos < len; pos++)
f3bc08c5
MD
173 if (ptrs[pos] == p)
174 goto found;
175 return NULL;
176found:
7369e702
MD
177 if (heap->len == 1) {
178 (void) heap_set_len(heap, 0);
f3bc08c5
MD
179 return ptrs[0];
180 }
7369e702
MD
181 /* Replace p with previous last entry and heapify. */
182 heap_set_len(heap, heap->len - 1);
183 ptrs[pos] = ptrs[heap->len - 1];
f3bc08c5
MD
184 heapify(heap, pos);
185 return p;
186}
This page took 0.03063 seconds and 4 git commands to generate.