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 * 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 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 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 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 * 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 * 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