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