xref: /xnu-11417.140.69/tools/lldbmacros/core/iterators.py (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1*43a90889SApple OSS Distributions"""
2*43a90889SApple OSS DistributionsXNU Collection iterators
3*43a90889SApple OSS Distributions"""
4*43a90889SApple OSS Distributionsfrom .cvalue import gettype
5*43a90889SApple OSS Distributionsfrom .standard import xnu_format
6*43a90889SApple OSS Distributions
7*43a90889SApple OSS Distributionsfrom abc import ABCMeta, abstractmethod, abstractproperty
8*43a90889SApple OSS Distributions
9*43a90889SApple OSS Distributions
10*43a90889SApple OSS Distributions#
11*43a90889SApple OSS Distributions# Note to implementers
12*43a90889SApple OSS Distributions# ~~~~~~~~~~~~~~~~~~~~
13*43a90889SApple OSS Distributions#
14*43a90889SApple OSS Distributions# Iterators must be named iter_* in accordance with typical python API naming
15*43a90889SApple OSS Distributions#
16*43a90889SApple OSS Distributions# The "root" or "head" of the collection must be passed by reference
17*43a90889SApple OSS Distributions# and not by pointer.
18*43a90889SApple OSS Distributions#
19*43a90889SApple OSS Distributions# Returned elements must be references to the element type,
20*43a90889SApple OSS Distributions# and not pointers.
21*43a90889SApple OSS Distributions#
22*43a90889SApple OSS Distributions# Intrusive data types should ask for an "element type" (as an SBType),
23*43a90889SApple OSS Distributions# and a field name or path, and use SBType.xContainerOfTransform
24*43a90889SApple OSS Distributions# to cache the transform to apply for the entire iteration.
25*43a90889SApple OSS Distributions#
26*43a90889SApple OSS Distributions
27*43a90889SApple OSS Distributions
28*43a90889SApple OSS Distributionsdef iter_linked_list(head_value, next_field_or_path,
29*43a90889SApple OSS Distributions        first_field_or_path = None):
30*43a90889SApple OSS Distributions    """
31*43a90889SApple OSS Distributions    Iterates a NULL-terminated linked list.
32*43a90889SApple OSS Distributions
33*43a90889SApple OSS Distributions        Assuming these C types:
34*43a90889SApple OSS Distributions
35*43a90889SApple OSS Distributions            struct container {
36*43a90889SApple OSS Distributions                struct node *list1_head;
37*43a90889SApple OSS Distributions                struct node *list2_head;
38*43a90889SApple OSS Distributions            }
39*43a90889SApple OSS Distributions
40*43a90889SApple OSS Distributions            struct node {
41*43a90889SApple OSS Distributions                struct node *next;
42*43a90889SApple OSS Distributions            }
43*43a90889SApple OSS Distributions
44*43a90889SApple OSS Distributions        and "v" is an SBValue to a `struct container` type,
45*43a90889SApple OSS Distributions        enumerating list1 is:
46*43a90889SApple OSS Distributions
47*43a90889SApple OSS Distributions            iter_linked_list(v, 'next', 'list1_head')
48*43a90889SApple OSS Distributions
49*43a90889SApple OSS Distributions        if "v" is a `struct node *` directly, then the enumeration
50*43a90889SApple OSS Distributions        becomes:
51*43a90889SApple OSS Distributions
52*43a90889SApple OSS Distributions            iter_linked_list(v, 'next')
53*43a90889SApple OSS Distributions
54*43a90889SApple OSS Distributions
55*43a90889SApple OSS Distributions    @param head_value (SBValue)
56*43a90889SApple OSS Distributions        a reference to the list head.
57*43a90889SApple OSS Distributions
58*43a90889SApple OSS Distributions    @param next_field_or_path (str)
59*43a90889SApple OSS Distributions        The name of (or path to if starting with '.')
60*43a90889SApple OSS Distributions        the field linking to the next element.
61*43a90889SApple OSS Distributions
62*43a90889SApple OSS Distributions    @param first_field_or_path (str or None)
63*43a90889SApple OSS Distributions        The name of (or path to if starting with '.')
64*43a90889SApple OSS Distributions        the field from @c head_value holding the pointer
65*43a90889SApple OSS Distributions        to the first element of the list.
66*43a90889SApple OSS Distributions    """
67*43a90889SApple OSS Distributions
68*43a90889SApple OSS Distributions    if first_field_or_path is None:
69*43a90889SApple OSS Distributions        elt = head_value
70*43a90889SApple OSS Distributions    elif first_field_or_path[0] == '.':
71*43a90889SApple OSS Distributions        elt = head_value.chkGetValueForExpressionPath(first_field_or_path)
72*43a90889SApple OSS Distributions    else:
73*43a90889SApple OSS Distributions        elt = head_value.chkGetChildMemberWithName(first_field_or_path)
74*43a90889SApple OSS Distributions
75*43a90889SApple OSS Distributions    if next_field_or_path[0] == '.':
76*43a90889SApple OSS Distributions        while elt.GetValueAsAddress():
77*43a90889SApple OSS Distributions            elt = elt.Dereference()
78*43a90889SApple OSS Distributions            yield elt
79*43a90889SApple OSS Distributions            elt = elt.chkGetValueForExpressionPath(next_field_or_path)
80*43a90889SApple OSS Distributions    else:
81*43a90889SApple OSS Distributions        while elt.GetValueAsAddress():
82*43a90889SApple OSS Distributions            elt = elt.Dereference()
83*43a90889SApple OSS Distributions            yield elt
84*43a90889SApple OSS Distributions            elt = elt.chkGetChildMemberWithName(next_field_or_path)
85*43a90889SApple OSS Distributions
86*43a90889SApple OSS Distributions
87*43a90889SApple OSS Distributionsdef iter_queue_entries(head_value, elt_type, field_name_or_path, backwards=False):
88*43a90889SApple OSS Distributions    """
89*43a90889SApple OSS Distributions    Iterate over a queue of entries (<kern/queue.h> method 1)
90*43a90889SApple OSS Distributions
91*43a90889SApple OSS Distributions    @param head_value (SBValue)
92*43a90889SApple OSS Distributions        a reference to the list head (queue_head_t)
93*43a90889SApple OSS Distributions
94*43a90889SApple OSS Distributions    @param elt_type (SBType)
95*43a90889SApple OSS Distributions        The type of the elements on the chain
96*43a90889SApple OSS Distributions
97*43a90889SApple OSS Distributions    @param field_name_or_path (str)
98*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
99*43a90889SApple OSS Distributions        containing the struct mpsc_queue_chain linkage.
100*43a90889SApple OSS Distributions
101*43a90889SApple OSS Distributions    @param backwards (bool)
102*43a90889SApple OSS Distributions         Whether the walk is forward or backwards
103*43a90889SApple OSS Distributions    """
104*43a90889SApple OSS Distributions
105*43a90889SApple OSS Distributions    stop = head_value.GetLoadAddress()
106*43a90889SApple OSS Distributions    elt  = head_value
107*43a90889SApple OSS Distributions    key  = 'prev' if backwards else 'next'
108*43a90889SApple OSS Distributions
109*43a90889SApple OSS Distributions    transform = elt_type.xContainerOfTransform(field_name_or_path)
110*43a90889SApple OSS Distributions
111*43a90889SApple OSS Distributions    while True:
112*43a90889SApple OSS Distributions        elt  = elt.chkGetChildMemberWithName(key)
113*43a90889SApple OSS Distributions        addr = elt.GetValueAsAddress()
114*43a90889SApple OSS Distributions        if addr == 0 or addr == stop:
115*43a90889SApple OSS Distributions            break
116*43a90889SApple OSS Distributions        elt = elt.Dereference()
117*43a90889SApple OSS Distributions        yield transform(elt)
118*43a90889SApple OSS Distributions
119*43a90889SApple OSS Distributions
120*43a90889SApple OSS Distributionsdef iter_queue(head_value, elt_type, field_name_or_path, backwards=False, unpack=None):
121*43a90889SApple OSS Distributions    """
122*43a90889SApple OSS Distributions    Iterate over queue of elements (<kern/queue.h> method 2)
123*43a90889SApple OSS Distributions
124*43a90889SApple OSS Distributions    @param head_value (SBValue)
125*43a90889SApple OSS Distributions        A reference to the list head (queue_head_t)
126*43a90889SApple OSS Distributions
127*43a90889SApple OSS Distributions    @param elt_type (SBType)
128*43a90889SApple OSS Distributions        The type of the elements on the chain
129*43a90889SApple OSS Distributions
130*43a90889SApple OSS Distributions    @param field_name_or_path (str)
131*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
132*43a90889SApple OSS Distributions        containing the struct mpsc_queue_chain linkage.
133*43a90889SApple OSS Distributions
134*43a90889SApple OSS Distributions    @param backwards (bool)
135*43a90889SApple OSS Distributions         Whether the walk is forward or backwards
136*43a90889SApple OSS Distributions
137*43a90889SApple OSS Distributions    @param unpack (Function or None)
138*43a90889SApple OSS Distributions        A function to unpack the pointer or None.
139*43a90889SApple OSS Distributions    """
140*43a90889SApple OSS Distributions
141*43a90889SApple OSS Distributions    stop = head_value.GetLoadAddress()
142*43a90889SApple OSS Distributions    elt  = head_value
143*43a90889SApple OSS Distributions    key  = '.prev' if backwards else '.next'
144*43a90889SApple OSS Distributions    addr = elt.xGetScalarByPath(key)
145*43a90889SApple OSS Distributions    if field_name_or_path[0] == '.':
146*43a90889SApple OSS Distributions        path = field_name_or_path + key
147*43a90889SApple OSS Distributions    else:
148*43a90889SApple OSS Distributions        path = "." + field_name_or_path + key
149*43a90889SApple OSS Distributions
150*43a90889SApple OSS Distributions    while True:
151*43a90889SApple OSS Distributions        if unpack is not None:
152*43a90889SApple OSS Distributions            addr = unpack(addr)
153*43a90889SApple OSS Distributions        if addr == 0 or addr == stop:
154*43a90889SApple OSS Distributions            break
155*43a90889SApple OSS Distributions
156*43a90889SApple OSS Distributions        elt  = elt.xCreateValueFromAddress('element', addr, elt_type)
157*43a90889SApple OSS Distributions        addr = elt.xGetScalarByPath(path)
158*43a90889SApple OSS Distributions        yield elt
159*43a90889SApple OSS Distributions
160*43a90889SApple OSS Distributions
161*43a90889SApple OSS Distributionsdef iter_circle_queue(head_value, elt_type, field_name_or_path, backwards=False):
162*43a90889SApple OSS Distributions    """
163*43a90889SApple OSS Distributions    Iterate over a queue of entries (<kern/circle_queue.h>)
164*43a90889SApple OSS Distributions
165*43a90889SApple OSS Distributions    @param head_value (SBValue)
166*43a90889SApple OSS Distributions        a reference to the list head (circle_queue_head_t)
167*43a90889SApple OSS Distributions
168*43a90889SApple OSS Distributions    @param elt_type (SBType)
169*43a90889SApple OSS Distributions        The type of the elements on the chain
170*43a90889SApple OSS Distributions
171*43a90889SApple OSS Distributions    @param field_name_or_path (str)
172*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
173*43a90889SApple OSS Distributions        containing the struct mpsc_queue_chain linkage.
174*43a90889SApple OSS Distributions
175*43a90889SApple OSS Distributions    @param backwards (bool)
176*43a90889SApple OSS Distributions         Whether the walk is forward or backwards
177*43a90889SApple OSS Distributions    """
178*43a90889SApple OSS Distributions
179*43a90889SApple OSS Distributions    elt  = head_value.chkGetChildMemberWithName('head')
180*43a90889SApple OSS Distributions    stop = elt.GetValueAsAddress()
181*43a90889SApple OSS Distributions    key  = 'prev' if backwards else 'next'
182*43a90889SApple OSS Distributions
183*43a90889SApple OSS Distributions    transform = elt_type.xContainerOfTransform(field_name_or_path)
184*43a90889SApple OSS Distributions
185*43a90889SApple OSS Distributions    if stop:
186*43a90889SApple OSS Distributions        if backwards:
187*43a90889SApple OSS Distributions            elt  = elt.chkGetValueForExpressionPath('->prev')
188*43a90889SApple OSS Distributions            stop = elt.GetValueAsAddress()
189*43a90889SApple OSS Distributions
190*43a90889SApple OSS Distributions        while True:
191*43a90889SApple OSS Distributions            elt = elt.Dereference()
192*43a90889SApple OSS Distributions            yield transform(elt)
193*43a90889SApple OSS Distributions
194*43a90889SApple OSS Distributions            elt  = elt.chkGetChildMemberWithName(key)
195*43a90889SApple OSS Distributions            addr = elt.GetValueAsAddress()
196*43a90889SApple OSS Distributions            if addr == 0 or addr == stop:
197*43a90889SApple OSS Distributions                break
198*43a90889SApple OSS Distributions
199*43a90889SApple OSS Distributions
200*43a90889SApple OSS Distributionsdef iter_mpsc_queue(head_value, elt_type, field_name_or_path):
201*43a90889SApple OSS Distributions    """
202*43a90889SApple OSS Distributions    Iterates a struct mpsc_queue_head
203*43a90889SApple OSS Distributions
204*43a90889SApple OSS Distributions    @param head_value (SBValue)
205*43a90889SApple OSS Distributions        A struct mpsc_queue_head value.
206*43a90889SApple OSS Distributions
207*43a90889SApple OSS Distributions    @param elt_type (SBType)
208*43a90889SApple OSS Distributions        The type of the elements on the chain.
209*43a90889SApple OSS Distributions
210*43a90889SApple OSS Distributions    @param field_name_or_path (str)
211*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
212*43a90889SApple OSS Distributions        containing the struct mpsc_queue_chain linkage.
213*43a90889SApple OSS Distributions
214*43a90889SApple OSS Distributions    @returns (generator)
215*43a90889SApple OSS Distributions        An iterator for the MPSC queue.
216*43a90889SApple OSS Distributions    """
217*43a90889SApple OSS Distributions
218*43a90889SApple OSS Distributions    transform = elt_type.xContainerOfTransform(field_name_or_path)
219*43a90889SApple OSS Distributions
220*43a90889SApple OSS Distributions    return (transform(e) for e in iter_linked_list(
221*43a90889SApple OSS Distributions        head_value, 'mpqc_next', '.mpqh_head.mpqc_next'
222*43a90889SApple OSS Distributions    ))
223*43a90889SApple OSS Distributions
224*43a90889SApple OSS Distributions
225*43a90889SApple OSS Distributionsclass iter_priority_queue(object):
226*43a90889SApple OSS Distributions    """
227*43a90889SApple OSS Distributions    Iterates any of the priority queues from <kern/priority_queue.h>
228*43a90889SApple OSS Distributions
229*43a90889SApple OSS Distributions    @param head_value (SBValue)
230*43a90889SApple OSS Distributions        A struct priority_queue* value.
231*43a90889SApple OSS Distributions
232*43a90889SApple OSS Distributions    @param elt_type (SBType)
233*43a90889SApple OSS Distributions        The type of the elements on the chain.
234*43a90889SApple OSS Distributions
235*43a90889SApple OSS Distributions    @param field_name_or_path (str)
236*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
237*43a90889SApple OSS Distributions        containing the struct priority_queue_entry* linkage.
238*43a90889SApple OSS Distributions
239*43a90889SApple OSS Distributions    @returns (generator)
240*43a90889SApple OSS Distributions        An iterator for the priority queue.
241*43a90889SApple OSS Distributions    """
242*43a90889SApple OSS Distributions
243*43a90889SApple OSS Distributions    def __init__(self, head_value, elt_type, field_name_or_path):
244*43a90889SApple OSS Distributions        self.transform = elt_type.xContainerOfTransform(field_name_or_path)
245*43a90889SApple OSS Distributions
246*43a90889SApple OSS Distributions        self.gen   = iter_linked_list(head_value, 'next', 'pq_root')
247*43a90889SApple OSS Distributions        self.queue = []
248*43a90889SApple OSS Distributions
249*43a90889SApple OSS Distributions    def __iter__(self):
250*43a90889SApple OSS Distributions        return self
251*43a90889SApple OSS Distributions
252*43a90889SApple OSS Distributions    def __next__(self):
253*43a90889SApple OSS Distributions        queue = self.queue
254*43a90889SApple OSS Distributions        elt   = next(self.gen, None)
255*43a90889SApple OSS Distributions
256*43a90889SApple OSS Distributions        if elt is None:
257*43a90889SApple OSS Distributions            if not len(queue):
258*43a90889SApple OSS Distributions                raise StopIteration
259*43a90889SApple OSS Distributions            elt = queue.pop()
260*43a90889SApple OSS Distributions            self.gen = iter_linked_list(elt, 'next', 'next')
261*43a90889SApple OSS Distributions
262*43a90889SApple OSS Distributions        addr = elt.xGetScalarByName('child')
263*43a90889SApple OSS Distributions        if addr:
264*43a90889SApple OSS Distributions            queue.append(elt.xCreateValueFromAddress(
265*43a90889SApple OSS Distributions                None, addr & 0xffffffffffffffff, elt.GetType()))
266*43a90889SApple OSS Distributions
267*43a90889SApple OSS Distributions        return self.transform(elt)
268*43a90889SApple OSS Distributions
269*43a90889SApple OSS Distributionsdef iter_SLIST_HEAD(head_value, link_field):
270*43a90889SApple OSS Distributions    """ Specialized version of iter_linked_list() for <sys/queue.h> SLIST_HEAD """
271*43a90889SApple OSS Distributions
272*43a90889SApple OSS Distributions    next_path = ".{}.sle_next".format(link_field)
273*43a90889SApple OSS Distributions    return (e for e in iter_linked_list(head_value, next_path, "slh_first"))
274*43a90889SApple OSS Distributions
275*43a90889SApple OSS Distributionsdef iter_LIST_HEAD(head_value, link_field):
276*43a90889SApple OSS Distributions    """ Specialized version of iter_linked_list() for <sys/queue.h> LIST_HEAD """
277*43a90889SApple OSS Distributions
278*43a90889SApple OSS Distributions    next_path = ".{}.le_next".format(link_field)
279*43a90889SApple OSS Distributions    return (e for e in iter_linked_list(head_value, next_path, "lh_first"))
280*43a90889SApple OSS Distributions
281*43a90889SApple OSS Distributionsdef iter_STAILQ_HEAD(head_value, link_field):
282*43a90889SApple OSS Distributions    """ Specialized version of iter_linked_list() for <sys/queue.h> STAILQ_HEAD """
283*43a90889SApple OSS Distributions
284*43a90889SApple OSS Distributions    next_path = ".{}.stqe_next".format(link_field)
285*43a90889SApple OSS Distributions    return (e for e in iter_linked_list(head_value, next_path, "stqh_first"))
286*43a90889SApple OSS Distributions
287*43a90889SApple OSS Distributionsdef iter_TAILQ_HEAD(head_value, link_field):
288*43a90889SApple OSS Distributions    """ Specialized version of iter_linked_list() for <sys/queue.h> TAILQ_HEAD """
289*43a90889SApple OSS Distributions
290*43a90889SApple OSS Distributions    next_path = ".{}.tqe_next".format(link_field)
291*43a90889SApple OSS Distributions    return (e for e in iter_linked_list(head_value, next_path, "tqh_first"))
292*43a90889SApple OSS Distributions
293*43a90889SApple OSS Distributionsdef iter_SYS_QUEUE_HEAD(head_value, link_field):
294*43a90889SApple OSS Distributions    """ Specialized version of iter_linked_list() for any <sys/queue> *_HEAD """
295*43a90889SApple OSS Distributions
296*43a90889SApple OSS Distributions    field  = head_value.rawGetType().GetFieldAtIndex(0).GetName()
297*43a90889SApple OSS Distributions    next_path = ".{}.{}e_next".format(link_field, field.partition('_')[0])
298*43a90889SApple OSS Distributions    return (e for e in iter_linked_list(head_value, next_path, field))
299*43a90889SApple OSS Distributions
300*43a90889SApple OSS Distributions
301*43a90889SApple OSS Distributionsclass RB_HEAD(object):
302*43a90889SApple OSS Distributions    """
303*43a90889SApple OSS Distributions    Class providing utilities to manipulate a collection made with RB_HEAD()
304*43a90889SApple OSS Distributions    """
305*43a90889SApple OSS Distributions
306*43a90889SApple OSS Distributions    def __init__(self, rbh_root_value, link_field, cmp):
307*43a90889SApple OSS Distributions        """
308*43a90889SApple OSS Distributions        Create an rb-tree wrapper
309*43a90889SApple OSS Distributions
310*43a90889SApple OSS Distributions        @param rbh_root_value (SBValue)
311*43a90889SApple OSS Distributions            A value to an RB_HEAD() field
312*43a90889SApple OSS Distributions
313*43a90889SApple OSS Distributions        @param link_field (str)
314*43a90889SApple OSS Distributions            The name of the RB_ENTRY() field in the elements
315*43a90889SApple OSS Distributions
316*43a90889SApple OSS Distributions        @param cmp (function)
317*43a90889SApple OSS Distributions            The comparison function between a linked element,
318*43a90889SApple OSS Distributions            and a key
319*43a90889SApple OSS Distributions        """
320*43a90889SApple OSS Distributions
321*43a90889SApple OSS Distributions        self.root_sbv = rbh_root_value.chkGetChildMemberWithName('rbh_root')
322*43a90889SApple OSS Distributions        self.field    = link_field
323*43a90889SApple OSS Distributions        self.cmp      = cmp
324*43a90889SApple OSS Distributions        self.etype    = self.root_sbv.GetType().GetPointeeType()
325*43a90889SApple OSS Distributions
326*43a90889SApple OSS Distributions    def _parent(self, elt):
327*43a90889SApple OSS Distributions        RB_COLOR_MASK = 0x1
328*43a90889SApple OSS Distributions
329*43a90889SApple OSS Distributions        path   = "." + self.field + ".rbe_parent"
330*43a90889SApple OSS Distributions        parent = elt.chkGetValueForExpressionPath(path)
331*43a90889SApple OSS Distributions        paddr  = parent.GetValueAsAddress()
332*43a90889SApple OSS Distributions
333*43a90889SApple OSS Distributions        if paddr == 0:
334*43a90889SApple OSS Distributions            return None, 0
335*43a90889SApple OSS Distributions
336*43a90889SApple OSS Distributions        if paddr & RB_COLOR_MASK == 0:
337*43a90889SApple OSS Distributions            return parent.Dereference(), paddr
338*43a90889SApple OSS Distributions
339*43a90889SApple OSS Distributions        paddr &= ~RB_COLOR_MASK
340*43a90889SApple OSS Distributions        return parent.xCreateValueFromAddress(None, paddr, self.etype), paddr
341*43a90889SApple OSS Distributions
342*43a90889SApple OSS Distributions    def _sibling(self, elt, rbe_left, rbe_right):
343*43a90889SApple OSS Distributions
344*43a90889SApple OSS Distributions        field = self.field
345*43a90889SApple OSS Distributions        lpath = "." + field + rbe_left
346*43a90889SApple OSS Distributions        rpath = "." + field + rbe_right
347*43a90889SApple OSS Distributions
348*43a90889SApple OSS Distributions        e_r = elt.chkGetValueForExpressionPath(rpath)
349*43a90889SApple OSS Distributions        if e_r.GetValueAsAddress():
350*43a90889SApple OSS Distributions            #
351*43a90889SApple OSS Distributions            # IF (RB_RIGHT(elm, field)) {
352*43a90889SApple OSS Distributions            #     elm = RB_RIGHT(elm, field);
353*43a90889SApple OSS Distributions            #     while (RB_LEFT(elm, field))
354*43a90889SApple OSS Distributions            #         elm = RB_LEFT(elm, field);
355*43a90889SApple OSS Distributions            #
356*43a90889SApple OSS Distributions
357*43a90889SApple OSS Distributions            path = "->" + field + rbe_left
358*43a90889SApple OSS Distributions            res = e_r
359*43a90889SApple OSS Distributions            e_l = res.chkGetValueForExpressionPath(path)
360*43a90889SApple OSS Distributions            while e_l.GetValueAsAddress():
361*43a90889SApple OSS Distributions                res = e_l
362*43a90889SApple OSS Distributions                e_l = res.chkGetValueForExpressionPath(path)
363*43a90889SApple OSS Distributions
364*43a90889SApple OSS Distributions            return res.Dereference()
365*43a90889SApple OSS Distributions
366*43a90889SApple OSS Distributions        eaddr = elt.GetLoadAddress()
367*43a90889SApple OSS Distributions        e_p, paddr = self._parent(elt)
368*43a90889SApple OSS Distributions
369*43a90889SApple OSS Distributions        if paddr:
370*43a90889SApple OSS Distributions            #
371*43a90889SApple OSS Distributions            # IF (RB_GETPARENT(elm) &&
372*43a90889SApple OSS Distributions            #     (elm == RB_LEFT(RB_GETPARENT(elm), field)))
373*43a90889SApple OSS Distributions            #         elm = RB_GETPARENT(elm)
374*43a90889SApple OSS Distributions            #
375*43a90889SApple OSS Distributions
376*43a90889SApple OSS Distributions            if e_p.xGetScalarByPath(lpath) == eaddr:
377*43a90889SApple OSS Distributions                return e_p
378*43a90889SApple OSS Distributions
379*43a90889SApple OSS Distributions            #
380*43a90889SApple OSS Distributions            # WHILE (RB_GETPARENT(elm) &&
381*43a90889SApple OSS Distributions            #     (elm == RB_RIGHT(RB_GETPARENT(elm), field)))
382*43a90889SApple OSS Distributions            #         elm = RB_GETPARENT(elm);
383*43a90889SApple OSS Distributions            # elm = RB_GETPARENT(elm);
384*43a90889SApple OSS Distributions            #
385*43a90889SApple OSS Distributions
386*43a90889SApple OSS Distributions            while paddr:
387*43a90889SApple OSS Distributions                if e_p.xGetScalarByPath(rpath) != eaddr:
388*43a90889SApple OSS Distributions                    return e_p
389*43a90889SApple OSS Distributions
390*43a90889SApple OSS Distributions                eaddr = paddr
391*43a90889SApple OSS Distributions                e_p, paddr = self._parent(e_p)
392*43a90889SApple OSS Distributions
393*43a90889SApple OSS Distributions        return None
394*43a90889SApple OSS Distributions
395*43a90889SApple OSS Distributions    def _find(self, key):
396*43a90889SApple OSS Distributions        elt = self.root_sbv
397*43a90889SApple OSS Distributions        f   = self.field
398*43a90889SApple OSS Distributions        le  = None
399*43a90889SApple OSS Distributions        ge  = None
400*43a90889SApple OSS Distributions
401*43a90889SApple OSS Distributions        while elt.GetValueAsAddress():
402*43a90889SApple OSS Distributions            elt = elt.Dereference()
403*43a90889SApple OSS Distributions            rc  = self.cmp(elt, key)
404*43a90889SApple OSS Distributions            if rc == 0:
405*43a90889SApple OSS Distributions                return elt, elt, elt
406*43a90889SApple OSS Distributions
407*43a90889SApple OSS Distributions            if rc < 0:
408*43a90889SApple OSS Distributions                ge  = elt
409*43a90889SApple OSS Distributions                elt = elt.chkGetValueForExpressionPath("->" + f + ".rbe_left")
410*43a90889SApple OSS Distributions            else:
411*43a90889SApple OSS Distributions                le  = elt
412*43a90889SApple OSS Distributions                elt = elt.chkGetValueForExpressionPath("->" + f + ".rbe_right")
413*43a90889SApple OSS Distributions
414*43a90889SApple OSS Distributions        return le, None, ge
415*43a90889SApple OSS Distributions
416*43a90889SApple OSS Distributions    def _minmax(self, direction):
417*43a90889SApple OSS Distributions        """ Returns the first element in the tree """
418*43a90889SApple OSS Distributions
419*43a90889SApple OSS Distributions        elt  = self.root_sbv
420*43a90889SApple OSS Distributions        res  = None
421*43a90889SApple OSS Distributions        path = "->" + self.field + direction
422*43a90889SApple OSS Distributions
423*43a90889SApple OSS Distributions        while elt.GetValueAsAddress():
424*43a90889SApple OSS Distributions            res = elt
425*43a90889SApple OSS Distributions            elt = elt.chkGetValueForExpressionPath(path)
426*43a90889SApple OSS Distributions
427*43a90889SApple OSS Distributions        return res.Dereference() if res is not None else None
428*43a90889SApple OSS Distributions
429*43a90889SApple OSS Distributions    def find_lt(self, key):
430*43a90889SApple OSS Distributions        """ Find the element smaller than the specified key """
431*43a90889SApple OSS Distributions
432*43a90889SApple OSS Distributions        elt, _, _ = self._find(key)
433*43a90889SApple OSS Distributions        return self.prev(elt) if elt is not None else None
434*43a90889SApple OSS Distributions
435*43a90889SApple OSS Distributions    def find_le(self, key):
436*43a90889SApple OSS Distributions        """ Find the element smaller or equal to the specified key """
437*43a90889SApple OSS Distributions
438*43a90889SApple OSS Distributions        elt, _, _ = self._find(key)
439*43a90889SApple OSS Distributions        return elt
440*43a90889SApple OSS Distributions
441*43a90889SApple OSS Distributions    def find(self, key):
442*43a90889SApple OSS Distributions        """ Find the element with the specified key """
443*43a90889SApple OSS Distributions
444*43a90889SApple OSS Distributions        _, elt, _ = self._find(key)
445*43a90889SApple OSS Distributions        return elt
446*43a90889SApple OSS Distributions
447*43a90889SApple OSS Distributions    def find_ge(self, key):
448*43a90889SApple OSS Distributions        """ Find the element greater or equal to the specified key """
449*43a90889SApple OSS Distributions
450*43a90889SApple OSS Distributions        _, _, elt = self._find(key)
451*43a90889SApple OSS Distributions        return elt
452*43a90889SApple OSS Distributions
453*43a90889SApple OSS Distributions    def find_gt(self, key):
454*43a90889SApple OSS Distributions        """ Find the element greater than the specified key """
455*43a90889SApple OSS Distributions
456*43a90889SApple OSS Distributions        _, _, elt = self._find(key)
457*43a90889SApple OSS Distributions        return self.next(elt.Dereference()) if elt is not None else None
458*43a90889SApple OSS Distributions
459*43a90889SApple OSS Distributions    def first(self):
460*43a90889SApple OSS Distributions        """ Returns the first element in the tree """
461*43a90889SApple OSS Distributions
462*43a90889SApple OSS Distributions        return self._minmax(".rbe_left")
463*43a90889SApple OSS Distributions
464*43a90889SApple OSS Distributions    def last(self):
465*43a90889SApple OSS Distributions        """ Returns the last element in the tree """
466*43a90889SApple OSS Distributions
467*43a90889SApple OSS Distributions        return self._minmax(".rbe_right")
468*43a90889SApple OSS Distributions
469*43a90889SApple OSS Distributions    def next(self, elt):
470*43a90889SApple OSS Distributions        """ Returns the next element in rbtree order or None """
471*43a90889SApple OSS Distributions
472*43a90889SApple OSS Distributions        return self._sibling(elt, ".rbe_left", ".rbe_right")
473*43a90889SApple OSS Distributions
474*43a90889SApple OSS Distributions    def prev(self, elt):
475*43a90889SApple OSS Distributions        """ Returns the next element in rbtree order or None """
476*43a90889SApple OSS Distributions
477*43a90889SApple OSS Distributions        return self._sibling(elt, ".rbe_right", ".rbe_left")
478*43a90889SApple OSS Distributions
479*43a90889SApple OSS Distributions    def iter(self, min_key=None, max_key=None):
480*43a90889SApple OSS Distributions        """
481*43a90889SApple OSS Distributions        Iterates all elements in this red-black tree
482*43a90889SApple OSS Distributions        with min_key <= key < max_key
483*43a90889SApple OSS Distributions        """
484*43a90889SApple OSS Distributions
485*43a90889SApple OSS Distributions        e = self.first() if min_key is None else self.find_ge(min_key)
486*43a90889SApple OSS Distributions
487*43a90889SApple OSS Distributions        if max_key is None:
488*43a90889SApple OSS Distributions            while e is not None:
489*43a90889SApple OSS Distributions                yield e
490*43a90889SApple OSS Distributions                e = self.next(e)
491*43a90889SApple OSS Distributions        else:
492*43a90889SApple OSS Distributions            cmp = self.cmp
493*43a90889SApple OSS Distributions            while e is not None and cmp(e, max_key) >= 0:
494*43a90889SApple OSS Distributions                yield e
495*43a90889SApple OSS Distributions                e = self.next(e)
496*43a90889SApple OSS Distributions
497*43a90889SApple OSS Distributions    def __iter__(self):
498*43a90889SApple OSS Distributions        return self.iter()
499*43a90889SApple OSS Distributions
500*43a90889SApple OSS Distributions
501*43a90889SApple OSS Distributionsdef iter_RB_HEAD(rbh_root_value, link_field):
502*43a90889SApple OSS Distributions    """ Conveniency wrapper for RB_HEAD iteration """
503*43a90889SApple OSS Distributions
504*43a90889SApple OSS Distributions    return RB_HEAD(rbh_root_value, link_field, None).iter()
505*43a90889SApple OSS Distributions
506*43a90889SApple OSS Distributions
507*43a90889SApple OSS Distributionsdef iter_smr_queue(head_value, elt_type, field_name_or_path):
508*43a90889SApple OSS Distributions    """
509*43a90889SApple OSS Distributions    Iterate over an SMR queue of entries (<kern/smr.h>)
510*43a90889SApple OSS Distributions
511*43a90889SApple OSS Distributions    @param head_value (SBValue)
512*43a90889SApple OSS Distributions        a reference to the list head (struct smrq_*_head)
513*43a90889SApple OSS Distributions
514*43a90889SApple OSS Distributions    @param elt_type (SBType)
515*43a90889SApple OSS Distributions        The type of the elements on the chain
516*43a90889SApple OSS Distributions
517*43a90889SApple OSS Distributions    @param field_name_or_path (str)
518*43a90889SApple OSS Distributions        The name of (or path to if starting with '.') the field
519*43a90889SApple OSS Distributions        containing the struct mpsc_queue_chain linkage.
520*43a90889SApple OSS Distributions    """
521*43a90889SApple OSS Distributions
522*43a90889SApple OSS Distributions    transform = elt_type.xContainerOfTransform(field_name_or_path)
523*43a90889SApple OSS Distributions
524*43a90889SApple OSS Distributions    return (transform(e) for e in iter_linked_list(
525*43a90889SApple OSS Distributions        head_value, '.next.__smr_ptr', '.first.__smr_ptr'
526*43a90889SApple OSS Distributions    ))
527*43a90889SApple OSS Distributions
528*43a90889SApple OSS Distributionsclass _Hash(object, metaclass=ABCMeta):
529*43a90889SApple OSS Distributions    @abstractproperty
530*43a90889SApple OSS Distributions    def buckets(self):
531*43a90889SApple OSS Distributions        """
532*43a90889SApple OSS Distributions        Returns the number of buckets in the hash table
533*43a90889SApple OSS Distributions        """
534*43a90889SApple OSS Distributions        pass
535*43a90889SApple OSS Distributions
536*43a90889SApple OSS Distributions    @abstractproperty
537*43a90889SApple OSS Distributions    def count(self):
538*43a90889SApple OSS Distributions        """
539*43a90889SApple OSS Distributions        Returns the number of elements in the hash table
540*43a90889SApple OSS Distributions        """
541*43a90889SApple OSS Distributions        pass
542*43a90889SApple OSS Distributions
543*43a90889SApple OSS Distributions    @abstractproperty
544*43a90889SApple OSS Distributions    def rehashing(self):
545*43a90889SApple OSS Distributions        """
546*43a90889SApple OSS Distributions        Returns whether the hash is currently rehashing
547*43a90889SApple OSS Distributions        """
548*43a90889SApple OSS Distributions        pass
549*43a90889SApple OSS Distributions
550*43a90889SApple OSS Distributions    @abstractmethod
551*43a90889SApple OSS Distributions    def iter(self, detailed=False):
552*43a90889SApple OSS Distributions        """
553*43a90889SApple OSS Distributions        @param detailed (bool)
554*43a90889SApple OSS Distributions            whether to enumerate just elements, or show bucket info too
555*43a90889SApple OSS Distributions            when bucket info is requested, enumeration returns a tuple of:
556*43a90889SApple OSS Distributions            (0, bucket, index_in_bucket, element)
557*43a90889SApple OSS Distributions        """
558*43a90889SApple OSS Distributions        pass
559*43a90889SApple OSS Distributions
560*43a90889SApple OSS Distributions    def __iter__(self):
561*43a90889SApple OSS Distributions        return self.iter()
562*43a90889SApple OSS Distributions
563*43a90889SApple OSS Distributions    def describe(self):
564*43a90889SApple OSS Distributions        fmt = (
565*43a90889SApple OSS Distributions            "Hash table info\n"
566*43a90889SApple OSS Distributions            " address              : {1:#x}\n"
567*43a90889SApple OSS Distributions            " element count        : {0.count}\n"
568*43a90889SApple OSS Distributions            " bucket count         : {0.buckets}\n"
569*43a90889SApple OSS Distributions            " rehashing            : {0.rehashing}"
570*43a90889SApple OSS Distributions        )
571*43a90889SApple OSS Distributions        print(xnu_format(fmt, self, self.hash_value.GetLoadAddress()))
572*43a90889SApple OSS Distributions
573*43a90889SApple OSS Distributions        if self.rehashing:
574*43a90889SApple OSS Distributions            print()
575*43a90889SApple OSS Distributions            return
576*43a90889SApple OSS Distributions
577*43a90889SApple OSS Distributions        b_len = {}
578*43a90889SApple OSS Distributions        for _, b_idx, e_idx, _ in self.iter(detailed=True):
579*43a90889SApple OSS Distributions            b_len[b_idx] = e_idx + 1
580*43a90889SApple OSS Distributions
581*43a90889SApple OSS Distributions        stats = {i: 0 for i in range(max(b_len.values()) + 1) }
582*43a90889SApple OSS Distributions        for v in b_len.values():
583*43a90889SApple OSS Distributions            stats[v] += 1
584*43a90889SApple OSS Distributions        stats[0] = self.buckets - len(b_len)
585*43a90889SApple OSS Distributions
586*43a90889SApple OSS Distributions        fmt = (
587*43a90889SApple OSS Distributions            " histogram            :\n"
588*43a90889SApple OSS Distributions            "  {:>4}  {:>6}  {:>6}  {:>6}  {:>5}"
589*43a90889SApple OSS Distributions        )
590*43a90889SApple OSS Distributions        print(xnu_format(fmt, "size", "count", "(cum)", "%", "(cum)"))
591*43a90889SApple OSS Distributions
592*43a90889SApple OSS Distributions        fmt = "  {:>4,d}  {:>6,d}  {:>6,d}  {:>6.1%}  {:>5.0%}"
593*43a90889SApple OSS Distributions        tot = 0
594*43a90889SApple OSS Distributions        for sz, n in stats.items():
595*43a90889SApple OSS Distributions            tot += n
596*43a90889SApple OSS Distributions            print(xnu_format(fmt, sz, n, tot, n / self.buckets, tot / self.buckets))
597*43a90889SApple OSS Distributions
598*43a90889SApple OSS Distributions
599*43a90889SApple OSS Distributionsclass SMRHash(_Hash):
600*43a90889SApple OSS Distributions    """
601*43a90889SApple OSS Distributions    Class providing utilities to manipulate SMR hash tables
602*43a90889SApple OSS Distributions    """
603*43a90889SApple OSS Distributions
604*43a90889SApple OSS Distributions    def __init__(self, hash_value, traits_value):
605*43a90889SApple OSS Distributions        """
606*43a90889SApple OSS Distributions        Create an smr hash table iterator
607*43a90889SApple OSS Distributions
608*43a90889SApple OSS Distributions        @param hash_value (SBValue)
609*43a90889SApple OSS Distributions            a reference to a struct smr_hash instance.
610*43a90889SApple OSS Distributions
611*43a90889SApple OSS Distributions        @param traits_value (SBValue)
612*43a90889SApple OSS Distributions            a reference to the traits for this hash table
613*43a90889SApple OSS Distributions        """
614*43a90889SApple OSS Distributions        super().__init__()
615*43a90889SApple OSS Distributions        self.hash_value = hash_value
616*43a90889SApple OSS Distributions        self.traits_value = traits_value
617*43a90889SApple OSS Distributions
618*43a90889SApple OSS Distributions    @property
619*43a90889SApple OSS Distributions    def buckets(self):
620*43a90889SApple OSS Distributions        hash_arr = self.hash_value.xGetScalarByName('smrh_array')
621*43a90889SApple OSS Distributions        return 1 << (64 - ((hash_arr >> 48) & 0x00ff))
622*43a90889SApple OSS Distributions
623*43a90889SApple OSS Distributions    @property
624*43a90889SApple OSS Distributions    def count(self):
625*43a90889SApple OSS Distributions        return self.hash_value.xGetScalarByName('smrh_count')
626*43a90889SApple OSS Distributions
627*43a90889SApple OSS Distributions    @property
628*43a90889SApple OSS Distributions    def rehashing(self):
629*43a90889SApple OSS Distributions        return self.hash_value.xGetScalarByName('smrh_resizing')
630*43a90889SApple OSS Distributions
631*43a90889SApple OSS Distributions    def iter(self, detailed=False):
632*43a90889SApple OSS Distributions        obj_null = self.traits_value.chkGetChildMemberWithName('smrht_obj_type')
633*43a90889SApple OSS Distributions        obj_ty   = obj_null.GetType().GetArrayElementType().GetPointeeType()
634*43a90889SApple OSS Distributions        lnk_offs = self.traits_value.xGetScalarByPath('.smrht.link_offset')
635*43a90889SApple OSS Distributions        hash_arr = self.hash_value.xGetScalarByName('smrh_array')
636*43a90889SApple OSS Distributions        hash_sz  = 1 << (64 - ((hash_arr >> 48) & 0x00ff))
637*43a90889SApple OSS Distributions        hash_arr = obj_null.xCreateValueFromAddress(None,
638*43a90889SApple OSS Distributions            hash_arr | 0xffff000000000000, gettype('struct smrq_slist_head'));
639*43a90889SApple OSS Distributions
640*43a90889SApple OSS Distributions        if detailed:
641*43a90889SApple OSS Distributions            return (
642*43a90889SApple OSS Distributions                (0, head_idx, e_idx, e.xCreateValueFromAddress(None, e.GetLoadAddress() - lnk_offs, obj_ty))
643*43a90889SApple OSS Distributions                for head_idx, head in enumerate(hash_arr.xIterSiblings(0, hash_sz))
644*43a90889SApple OSS Distributions                for e_idx, e in enumerate(iter_linked_list(head, '.next.__smr_ptr', '.first.__smr_ptr'))
645*43a90889SApple OSS Distributions            )
646*43a90889SApple OSS Distributions
647*43a90889SApple OSS Distributions        return (
648*43a90889SApple OSS Distributions            e.xCreateValueFromAddress(None, e.GetLoadAddress() - lnk_offs, obj_ty)
649*43a90889SApple OSS Distributions            for head in hash_arr.xIterSiblings(0, hash_sz)
650*43a90889SApple OSS Distributions            for e in iter_linked_list(head, '.next.__smr_ptr', '.first.__smr_ptr')
651*43a90889SApple OSS Distributions        )
652*43a90889SApple OSS Distributions
653*43a90889SApple OSS Distributions
654*43a90889SApple OSS Distributionsclass SMRScalableHash(_Hash):
655*43a90889SApple OSS Distributions
656*43a90889SApple OSS Distributions    def __init__(self, hash_value, traits_value):
657*43a90889SApple OSS Distributions        """
658*43a90889SApple OSS Distributions        Create an smr hash table iterator
659*43a90889SApple OSS Distributions
660*43a90889SApple OSS Distributions        @param hash_value (SBValue)
661*43a90889SApple OSS Distributions            a reference to a struct smr_shash instance.
662*43a90889SApple OSS Distributions
663*43a90889SApple OSS Distributions        @param traits_value (SBValue)
664*43a90889SApple OSS Distributions            a reference to the traits for this hash table
665*43a90889SApple OSS Distributions        """
666*43a90889SApple OSS Distributions        super().__init__()
667*43a90889SApple OSS Distributions        self.hash_value = hash_value
668*43a90889SApple OSS Distributions        self.traits_value = traits_value
669*43a90889SApple OSS Distributions
670*43a90889SApple OSS Distributions    @property
671*43a90889SApple OSS Distributions    def buckets(self):
672*43a90889SApple OSS Distributions        shift = self.hash_value.xGetScalarByPath('.smrsh_state.curshift')
673*43a90889SApple OSS Distributions        return (0xffffffff >> shift) + 1;
674*43a90889SApple OSS Distributions
675*43a90889SApple OSS Distributions    @property
676*43a90889SApple OSS Distributions    def count(self):
677*43a90889SApple OSS Distributions        sbv      = self.hash_value.chkGetChildMemberWithName('smrsh_count')
678*43a90889SApple OSS Distributions        addr     = sbv.GetValueAsAddress()
679*43a90889SApple OSS Distributions        target   = sbv.GetTarget()
680*43a90889SApple OSS Distributions        ncpus    = target.chkFindFirstGlobalVariable('zpercpu_early_count').xGetValueAsInteger()
681*43a90889SApple OSS Distributions        pg_shift = target.chkFindFirstGlobalVariable('page_shift').xGetValueAsInteger()
682*43a90889SApple OSS Distributions
683*43a90889SApple OSS Distributions        return sum(
684*43a90889SApple OSS Distributions            target.xReadInt64(addr + (cpu << pg_shift))
685*43a90889SApple OSS Distributions            for cpu in range(ncpus)
686*43a90889SApple OSS Distributions        )
687*43a90889SApple OSS Distributions
688*43a90889SApple OSS Distributions    @property
689*43a90889SApple OSS Distributions    def rehashing(self):
690*43a90889SApple OSS Distributions        curidx = self.hash_value.xGetScalarByPath('.smrsh_state.curidx');
691*43a90889SApple OSS Distributions        newidx = self.hash_value.xGetScalarByPath('.smrsh_state.newidx');
692*43a90889SApple OSS Distributions        return curidx != newidx
693*43a90889SApple OSS Distributions
694*43a90889SApple OSS Distributions    def iter(self, detailed=False):
695*43a90889SApple OSS Distributions        """
696*43a90889SApple OSS Distributions        @param detailed (bool)
697*43a90889SApple OSS Distributions            whether to enumerate just elements, or show bucket info too
698*43a90889SApple OSS Distributions            when bucket info is requested, enumeration returns a tuple of:
699*43a90889SApple OSS Distributions            (table_index, bucket, index_in_bucket, element)
700*43a90889SApple OSS Distributions        """
701*43a90889SApple OSS Distributions
702*43a90889SApple OSS Distributions        hash_value   = self.hash_value
703*43a90889SApple OSS Distributions        traits_value = self.traits_value
704*43a90889SApple OSS Distributions
705*43a90889SApple OSS Distributions        obj_null = traits_value.chkGetChildMemberWithName('smrht_obj_type')
706*43a90889SApple OSS Distributions        obj_ty   = obj_null.GetType().GetArrayElementType().GetPointeeType()
707*43a90889SApple OSS Distributions        lnk_offs = traits_value.xGetScalarByPath('.smrht.link_offset')
708*43a90889SApple OSS Distributions        hashes   = []
709*43a90889SApple OSS Distributions
710*43a90889SApple OSS Distributions        curidx   = hash_value.xGetScalarByPath('.smrsh_state.curidx');
711*43a90889SApple OSS Distributions        newidx   = hash_value.xGetScalarByPath('.smrsh_state.newidx');
712*43a90889SApple OSS Distributions        arrays   = hash_value.chkGetChildMemberWithName('smrsh_array')
713*43a90889SApple OSS Distributions
714*43a90889SApple OSS Distributions        array    = arrays.chkGetChildAtIndex(curidx)
715*43a90889SApple OSS Distributions        shift    = hash_value.xGetScalarByPath('.smrsh_state.curshift')
716*43a90889SApple OSS Distributions        hashes.append((curidx, array.Dereference(), shift))
717*43a90889SApple OSS Distributions        if newidx != curidx:
718*43a90889SApple OSS Distributions            array    = arrays.chkGetChildAtIndex(newidx)
719*43a90889SApple OSS Distributions            shift    = hash_value.xGetScalarByPath('.smrsh_state.newshift')
720*43a90889SApple OSS Distributions            hashes.append((newidx, array.Dereference(), shift))
721*43a90889SApple OSS Distributions
722*43a90889SApple OSS Distributions        seen = set()
723*43a90889SApple OSS Distributions
724*43a90889SApple OSS Distributions        def _iter_smr_shash_bucket(head):
725*43a90889SApple OSS Distributions            addr  = head.xGetScalarByName('lck_ptr_bits')
726*43a90889SApple OSS Distributions            tg    = head.GetTarget()
727*43a90889SApple OSS Distributions
728*43a90889SApple OSS Distributions            while addr & 1 == 0:
729*43a90889SApple OSS Distributions                addr &= 0xfffffffffffffffe
730*43a90889SApple OSS Distributions                e = head.xCreateValueFromAddress(None, addr - lnk_offs, obj_ty)
731*43a90889SApple OSS Distributions                if addr not in seen:
732*43a90889SApple OSS Distributions                    seen.add(addr)
733*43a90889SApple OSS Distributions                    yield e
734*43a90889SApple OSS Distributions                addr = tg.xReadULong(addr);
735*43a90889SApple OSS Distributions
736*43a90889SApple OSS Distributions        if detailed:
737*43a90889SApple OSS Distributions            return (
738*43a90889SApple OSS Distributions                (hash_idx, head_idx, e_idx, e)
739*43a90889SApple OSS Distributions                for hash_idx, hash_arr, hash_shift in hashes
740*43a90889SApple OSS Distributions                for head_idx, head in enumerate(hash_arr.xIterSiblings(
741*43a90889SApple OSS Distributions                    0, 1 + (0xffffffff >> hash_shift)))
742*43a90889SApple OSS Distributions                for e_idx, e in enumerate(_iter_smr_shash_bucket(head))
743*43a90889SApple OSS Distributions            )
744*43a90889SApple OSS Distributions
745*43a90889SApple OSS Distributions        return (
746*43a90889SApple OSS Distributions            e
747*43a90889SApple OSS Distributions            for hash_idx, hash_arr, hash_shift in hashes
748*43a90889SApple OSS Distributions            for head in hash_arr.xIterSiblings(
749*43a90889SApple OSS Distributions                0, 1 + (0xffffffff >> hash_shift))
750*43a90889SApple OSS Distributions            for e in _iter_smr_shash_bucket(head)
751*43a90889SApple OSS Distributions        )
752*43a90889SApple OSS Distributions
753*43a90889SApple OSS Distributions
754*43a90889SApple OSS Distributions__all__ = [
755*43a90889SApple OSS Distributions    iter_linked_list.__name__,
756*43a90889SApple OSS Distributions    iter_queue_entries.__name__,
757*43a90889SApple OSS Distributions    iter_queue.__name__,
758*43a90889SApple OSS Distributions    iter_circle_queue.__name__,
759*43a90889SApple OSS Distributions
760*43a90889SApple OSS Distributions    iter_mpsc_queue.__name__,
761*43a90889SApple OSS Distributions
762*43a90889SApple OSS Distributions    iter_priority_queue.__name__,
763*43a90889SApple OSS Distributions
764*43a90889SApple OSS Distributions    iter_SLIST_HEAD.__name__,
765*43a90889SApple OSS Distributions    iter_LIST_HEAD.__name__,
766*43a90889SApple OSS Distributions    iter_STAILQ_HEAD.__name__,
767*43a90889SApple OSS Distributions    iter_TAILQ_HEAD.__name__,
768*43a90889SApple OSS Distributions    iter_SYS_QUEUE_HEAD.__name__,
769*43a90889SApple OSS Distributions    iter_RB_HEAD.__name__,
770*43a90889SApple OSS Distributions    RB_HEAD.__name__,
771*43a90889SApple OSS Distributions
772*43a90889SApple OSS Distributions    iter_smr_queue.__name__,
773*43a90889SApple OSS Distributions    SMRHash.__name__,
774*43a90889SApple OSS Distributions    SMRScalableHash.__name__,
775*43a90889SApple OSS Distributions]
776