1*09e6105fSMark Johnston /*
2*09e6105fSMark Johnston * CDDL HEADER START
3*09e6105fSMark Johnston *
4*09e6105fSMark Johnston * This file and its contents are supplied under the terms of the
5*09e6105fSMark Johnston * Common Development and Distribution License ("CDDL"), version 1.0.
6*09e6105fSMark Johnston * You may only use this file in accordance with the terms of version
7*09e6105fSMark Johnston * 1.0 of the CDDL.
8*09e6105fSMark Johnston *
9*09e6105fSMark Johnston * A full copy of the text of the CDDL should have accompanied this
10*09e6105fSMark Johnston * source. A copy of the CDDL is also available via the Internet at
11*09e6105fSMark Johnston * http://www.illumos.org/license/CDDL.
12*09e6105fSMark Johnston *
13*09e6105fSMark Johnston * CDDL HEADER END
14*09e6105fSMark Johnston */
15*09e6105fSMark Johnston
16*09e6105fSMark Johnston /*
17*09e6105fSMark Johnston * Copyright (c) 2012 by Delphix. All rights reserved.
18*09e6105fSMark Johnston */
19*09e6105fSMark Johnston
20*09e6105fSMark Johnston #include <dtrace.h>
21*09e6105fSMark Johnston #include <dt_impl.h>
22*09e6105fSMark Johnston #include <dt_pq.h>
23*09e6105fSMark Johnston #include <assert.h>
24*09e6105fSMark Johnston
25*09e6105fSMark Johnston /*
26*09e6105fSMark Johnston * Create a new priority queue.
27*09e6105fSMark Johnston *
28*09e6105fSMark Johnston * size is the maximum number of items that will be stored in the priority
29*09e6105fSMark Johnston * queue at one time.
30*09e6105fSMark Johnston */
31*09e6105fSMark Johnston dt_pq_t *
dt_pq_init(dtrace_hdl_t * dtp,uint_t size,dt_pq_value_f value_cb,void * cb_arg)32*09e6105fSMark Johnston dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg)
33*09e6105fSMark Johnston {
34*09e6105fSMark Johnston dt_pq_t *p;
35*09e6105fSMark Johnston assert(size > 1);
36*09e6105fSMark Johnston
37*09e6105fSMark Johnston if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL)
38*09e6105fSMark Johnston return (NULL);
39*09e6105fSMark Johnston
40*09e6105fSMark Johnston p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0]));
41*09e6105fSMark Johnston if (p->dtpq_items == NULL) {
42*09e6105fSMark Johnston dt_free(dtp, p);
43*09e6105fSMark Johnston return (NULL);
44*09e6105fSMark Johnston }
45*09e6105fSMark Johnston
46*09e6105fSMark Johnston p->dtpq_hdl = dtp;
47*09e6105fSMark Johnston p->dtpq_size = size;
48*09e6105fSMark Johnston p->dtpq_last = 1;
49*09e6105fSMark Johnston p->dtpq_value = value_cb;
50*09e6105fSMark Johnston p->dtpq_arg = cb_arg;
51*09e6105fSMark Johnston
52*09e6105fSMark Johnston return (p);
53*09e6105fSMark Johnston }
54*09e6105fSMark Johnston
55*09e6105fSMark Johnston void
dt_pq_fini(dt_pq_t * p)56*09e6105fSMark Johnston dt_pq_fini(dt_pq_t *p)
57*09e6105fSMark Johnston {
58*09e6105fSMark Johnston dtrace_hdl_t *dtp = p->dtpq_hdl;
59*09e6105fSMark Johnston
60*09e6105fSMark Johnston dt_free(dtp, p->dtpq_items);
61*09e6105fSMark Johnston dt_free(dtp, p);
62*09e6105fSMark Johnston }
63*09e6105fSMark Johnston
64*09e6105fSMark Johnston static uint64_t
dt_pq_getvalue(dt_pq_t * p,uint_t index)65*09e6105fSMark Johnston dt_pq_getvalue(dt_pq_t *p, uint_t index)
66*09e6105fSMark Johnston {
67*09e6105fSMark Johnston void *item = p->dtpq_items[index];
68*09e6105fSMark Johnston return (p->dtpq_value(item, p->dtpq_arg));
69*09e6105fSMark Johnston }
70*09e6105fSMark Johnston
71*09e6105fSMark Johnston void
dt_pq_insert(dt_pq_t * p,void * item)72*09e6105fSMark Johnston dt_pq_insert(dt_pq_t *p, void *item)
73*09e6105fSMark Johnston {
74*09e6105fSMark Johnston uint_t i;
75*09e6105fSMark Johnston
76*09e6105fSMark Johnston assert(p->dtpq_last < p->dtpq_size);
77*09e6105fSMark Johnston
78*09e6105fSMark Johnston i = p->dtpq_last++;
79*09e6105fSMark Johnston p->dtpq_items[i] = item;
80*09e6105fSMark Johnston
81*09e6105fSMark Johnston while (i > 1 && dt_pq_getvalue(p, i) < dt_pq_getvalue(p, i / 2)) {
82*09e6105fSMark Johnston void *tmp = p->dtpq_items[i];
83*09e6105fSMark Johnston p->dtpq_items[i] = p->dtpq_items[i / 2];
84*09e6105fSMark Johnston p->dtpq_items[i / 2] = tmp;
85*09e6105fSMark Johnston i /= 2;
86*09e6105fSMark Johnston }
87*09e6105fSMark Johnston }
88*09e6105fSMark Johnston
89*09e6105fSMark Johnston /*
90*09e6105fSMark Johnston * Return elements from the priority queue. *cookie should be zero when first
91*09e6105fSMark Johnston * called. Returns NULL when there are no more elements.
92*09e6105fSMark Johnston */
93*09e6105fSMark Johnston void *
dt_pq_walk(dt_pq_t * p,uint_t * cookie)94*09e6105fSMark Johnston dt_pq_walk(dt_pq_t *p, uint_t *cookie)
95*09e6105fSMark Johnston {
96*09e6105fSMark Johnston (*cookie)++;
97*09e6105fSMark Johnston if (*cookie >= p->dtpq_last)
98*09e6105fSMark Johnston return (NULL);
99*09e6105fSMark Johnston
100*09e6105fSMark Johnston return (p->dtpq_items[*cookie]);
101*09e6105fSMark Johnston }
102*09e6105fSMark Johnston
103*09e6105fSMark Johnston void *
dt_pq_pop(dt_pq_t * p)104*09e6105fSMark Johnston dt_pq_pop(dt_pq_t *p)
105*09e6105fSMark Johnston {
106*09e6105fSMark Johnston uint_t i = 1;
107*09e6105fSMark Johnston void *ret;
108*09e6105fSMark Johnston
109*09e6105fSMark Johnston assert(p->dtpq_last > 0);
110*09e6105fSMark Johnston
111*09e6105fSMark Johnston if (p->dtpq_last == 1)
112*09e6105fSMark Johnston return (NULL);
113*09e6105fSMark Johnston
114*09e6105fSMark Johnston ret = p->dtpq_items[1];
115*09e6105fSMark Johnston
116*09e6105fSMark Johnston p->dtpq_last--;
117*09e6105fSMark Johnston p->dtpq_items[1] = p->dtpq_items[p->dtpq_last];
118*09e6105fSMark Johnston p->dtpq_items[p->dtpq_last] = NULL;
119*09e6105fSMark Johnston
120*09e6105fSMark Johnston for (;;) {
121*09e6105fSMark Johnston uint_t lc = i * 2;
122*09e6105fSMark Johnston uint_t rc = i * 2 + 1;
123*09e6105fSMark Johnston uint_t c;
124*09e6105fSMark Johnston uint64_t v;
125*09e6105fSMark Johnston void *tmp;
126*09e6105fSMark Johnston
127*09e6105fSMark Johnston if (lc >= p->dtpq_last)
128*09e6105fSMark Johnston break;
129*09e6105fSMark Johnston
130*09e6105fSMark Johnston if (rc >= p->dtpq_last) {
131*09e6105fSMark Johnston c = lc;
132*09e6105fSMark Johnston v = dt_pq_getvalue(p, lc);
133*09e6105fSMark Johnston } else {
134*09e6105fSMark Johnston uint64_t lv = dt_pq_getvalue(p, lc);
135*09e6105fSMark Johnston uint64_t rv = dt_pq_getvalue(p, rc);
136*09e6105fSMark Johnston
137*09e6105fSMark Johnston if (lv < rv) {
138*09e6105fSMark Johnston c = lc;
139*09e6105fSMark Johnston v = lv;
140*09e6105fSMark Johnston } else {
141*09e6105fSMark Johnston c = rc;
142*09e6105fSMark Johnston v = rv;
143*09e6105fSMark Johnston }
144*09e6105fSMark Johnston }
145*09e6105fSMark Johnston
146*09e6105fSMark Johnston if (v >= dt_pq_getvalue(p, i))
147*09e6105fSMark Johnston break;
148*09e6105fSMark Johnston
149*09e6105fSMark Johnston tmp = p->dtpq_items[i];
150*09e6105fSMark Johnston p->dtpq_items[i] = p->dtpq_items[c];
151*09e6105fSMark Johnston p->dtpq_items[c] = tmp;
152*09e6105fSMark Johnston
153*09e6105fSMark Johnston i = c;
154*09e6105fSMark Johnston }
155*09e6105fSMark Johnston
156*09e6105fSMark Johnston return (ret);
157*09e6105fSMark Johnston }
158