xref: /xnu-10063.121.3/osfmk/kern/compact_id.h (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /*
2*2c2f96dcSApple OSS Distributions  * Copyright (c) 2022 Apple Inc. All rights reserved.
3*2c2f96dcSApple OSS Distributions  *
4*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*2c2f96dcSApple OSS Distributions  *
6*2c2f96dcSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*2c2f96dcSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*2c2f96dcSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*2c2f96dcSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*2c2f96dcSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*2c2f96dcSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*2c2f96dcSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*2c2f96dcSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*2c2f96dcSApple OSS Distributions  *
15*2c2f96dcSApple OSS Distributions  * Please obtain a copy of the License at
16*2c2f96dcSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*2c2f96dcSApple OSS Distributions  *
18*2c2f96dcSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*2c2f96dcSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*2c2f96dcSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*2c2f96dcSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*2c2f96dcSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*2c2f96dcSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*2c2f96dcSApple OSS Distributions  * limitations under the License.
25*2c2f96dcSApple OSS Distributions  *
26*2c2f96dcSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*2c2f96dcSApple OSS Distributions  */
28*2c2f96dcSApple OSS Distributions 
29*2c2f96dcSApple OSS Distributions #ifndef _KERN_COMPACT_ID_H_
30*2c2f96dcSApple OSS Distributions #define _KERN_COMPACT_ID_H_
31*2c2f96dcSApple OSS Distributions 
32*2c2f96dcSApple OSS Distributions #include <stdbool.h>
33*2c2f96dcSApple OSS Distributions #include <stdint.h>
34*2c2f96dcSApple OSS Distributions #include <kern/bits.h>
35*2c2f96dcSApple OSS Distributions #include <kern/startup.h>
36*2c2f96dcSApple OSS Distributions #include <kern/locks.h>
37*2c2f96dcSApple OSS Distributions 
38*2c2f96dcSApple OSS Distributions __BEGIN_DECLS
39*2c2f96dcSApple OSS Distributions #pragma GCC visibility push(hidden)
40*2c2f96dcSApple OSS Distributions 
41*2c2f96dcSApple OSS Distributions #define COMPACT_ID_SHIFT_BASE     (10)
42*2c2f96dcSApple OSS Distributions #define COMPACT_ID_COUNT_BASE     (1u << COMPACT_ID_SHIFT_BASE)
43*2c2f96dcSApple OSS Distributions #define COMPACT_ID_SLAB_COUNT     (12)
44*2c2f96dcSApple OSS Distributions #define COMPACT_ID_MAX            ((COMPACT_ID_COUNT_BASE << (COMPACT_ID_SLAB_COUNT - 1)) - 1u)
45*2c2f96dcSApple OSS Distributions 
46*2c2f96dcSApple OSS Distributions typedef uint32_t                  compact_id_t;
47*2c2f96dcSApple OSS Distributions typedef struct compact_id_table  *compact_id_table_t;
48*2c2f96dcSApple OSS Distributions 
49*2c2f96dcSApple OSS Distributions /*
50*2c2f96dcSApple OSS Distributions  * @struct compact_id_table
51*2c2f96dcSApple OSS Distributions  *
52*2c2f96dcSApple OSS Distributions  * @discussion
53*2c2f96dcSApple OSS Distributions  * A compact ID table contains an array of COMPACT_ID_SLAB_COUNT
54*2c2f96dcSApple OSS Distributions  * compact_id_slab slabs.
55*2c2f96dcSApple OSS Distributions  *
56*2c2f96dcSApple OSS Distributions  * Each slab contains a different number of values, depending on its position
57*2c2f96dcSApple OSS Distributions  * within the cidt_slabs.
58*2c2f96dcSApple OSS Distributions  *
59*2c2f96dcSApple OSS Distributions  * The entries in the table are never deallocated once created,
60*2c2f96dcSApple OSS Distributions  * which allows to access the table without holding a lock.
61*2c2f96dcSApple OSS Distributions  *
62*2c2f96dcSApple OSS Distributions  * Slots within each slab can be re-used once an association
63*2c2f96dcSApple OSS Distributions  * with a prior value has been released.
64*2c2f96dcSApple OSS Distributions  *
65*2c2f96dcSApple OSS Distributions  * The first 2 entries will have COMPACT_ID_COUNT_BASE entries,
66*2c2f96dcSApple OSS Distributions  * all others will have size COMPACT_ID_COUNT_BASE * 2^(index - 1).
67*2c2f96dcSApple OSS Distributions  *
68*2c2f96dcSApple OSS Distributions  * |BASE|BASE|2BASE|4BASE|...|2^(MAX-2)BASE|
69*2c2f96dcSApple OSS Distributions  *   0    1     2     3          MAX-1
70*2c2f96dcSApple OSS Distributions  *
71*2c2f96dcSApple OSS Distributions  * This can allow a maximum capacity of BASE(2^(MAX-1)) values
72*2c2f96dcSApple OSS Distributions  *
73*2c2f96dcSApple OSS Distributions  * Because COMPACT_ID_COUNT_BASE is a power of 2, it lets us
74*2c2f96dcSApple OSS Distributions  * lookup into the tables very efficiently: each table slab
75*2c2f96dcSApple OSS Distributions  * contains all the compact IDs between subsequent power of 2
76*2c2f96dcSApple OSS Distributions  * of COMPACT_ID_COUNT_BASE.
77*2c2f96dcSApple OSS Distributions  *
78*2c2f96dcSApple OSS Distributions  * |0 -> (B-1)|B -> (2B-1)|2B -> (4B-1)|...|2^(MAX-2)B -> ((2^(MAX-1)B)-1)|
79*2c2f96dcSApple OSS Distributions  *      0          1            2                        MAX-1
80*2c2f96dcSApple OSS Distributions  *
81*2c2f96dcSApple OSS Distributions  * By observing the most significant bit of a given compact ID,
82*2c2f96dcSApple OSS Distributions  * we can compute its slab index very efficiently:
83*2c2f96dcSApple OSS Distributions  *
84*2c2f96dcSApple OSS Distributions  * slab_index = clz(COMPACT_ID_COUNT_BASE) - clz(ctid | (COMPACT_ID_COUNT_BASE - 1)) + 1
85*2c2f96dcSApple OSS Distributions  *
86*2c2f96dcSApple OSS Distributions  * Note: because we expect lookups to be common,
87*2c2f96dcSApple OSS Distributions  *       cidt_array isn't the real array but shifted
88*2c2f96dcSApple OSS Distributions  *       so that dereferencing it with the compact ID
89*2c2f96dcSApple OSS Distributions  *       works for any slab.
90*2c2f96dcSApple OSS Distributions  */
91*2c2f96dcSApple OSS Distributions struct compact_id_table {
92*2c2f96dcSApple OSS Distributions 	/*
93*2c2f96dcSApple OSS Distributions 	 * slabs first saves one instruction per compact_id_resolve()
94*2c2f96dcSApple OSS Distributions 	 */
95*2c2f96dcSApple OSS Distributions 	void                  **cidt_array[COMPACT_ID_SLAB_COUNT];
96*2c2f96dcSApple OSS Distributions 	bitmap_t               *cidt_bitmap[COMPACT_ID_SLAB_COUNT];
97*2c2f96dcSApple OSS Distributions 	lck_mtx_t               cidt_lock;
98*2c2f96dcSApple OSS Distributions 	struct thread          *cidt_allocator;
99*2c2f96dcSApple OSS Distributions 	bool                    cidt_waiters;
100*2c2f96dcSApple OSS Distributions 	uint32_t                cidt_count;
101*2c2f96dcSApple OSS Distributions 	compact_id_t            cidt_first_free;
102*2c2f96dcSApple OSS Distributions };
103*2c2f96dcSApple OSS Distributions 
104*2c2f96dcSApple OSS Distributions extern void compact_id_table_init(
105*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table);
106*2c2f96dcSApple OSS Distributions 
107*2c2f96dcSApple OSS Distributions extern void **compact_id_resolve(
108*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table,
109*2c2f96dcSApple OSS Distributions 	compact_id_t            compact_id) __pure2;
110*2c2f96dcSApple OSS Distributions 
111*2c2f96dcSApple OSS Distributions extern compact_id_t compact_id_get_locked(
112*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table,
113*2c2f96dcSApple OSS Distributions 	compact_id_t            limit,
114*2c2f96dcSApple OSS Distributions 	void                   *value);
115*2c2f96dcSApple OSS Distributions 
116*2c2f96dcSApple OSS Distributions extern compact_id_t compact_id_get(
117*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table,
118*2c2f96dcSApple OSS Distributions 	compact_id_t            limit,
119*2c2f96dcSApple OSS Distributions 	void                   *value);
120*2c2f96dcSApple OSS Distributions 
121*2c2f96dcSApple OSS Distributions extern void *compact_id_put(
122*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table,
123*2c2f96dcSApple OSS Distributions 	compact_id_t            compact_id);
124*2c2f96dcSApple OSS Distributions 
125*2c2f96dcSApple OSS Distributions extern void compact_id_for_each(
126*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table,
127*2c2f96dcSApple OSS Distributions 	uint32_t                stride,
128*2c2f96dcSApple OSS Distributions 	bool                  (^cb)(void *v));
129*2c2f96dcSApple OSS Distributions 
130*2c2f96dcSApple OSS Distributions extern void compact_id_table_lock(
131*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table);
132*2c2f96dcSApple OSS Distributions 
133*2c2f96dcSApple OSS Distributions extern void compact_id_table_unlock(
134*2c2f96dcSApple OSS Distributions 	compact_id_table_t      table);
135*2c2f96dcSApple OSS Distributions 
136*2c2f96dcSApple OSS Distributions #define COMPACT_ID_TABLE_DEFINE(class, var) \
137*2c2f96dcSApple OSS Distributions 	static void *var##_array0[COMPACT_ID_COUNT_BASE];                       \
138*2c2f96dcSApple OSS Distributions 	static bitmap_t var##_bits0[BITMAP_LEN(COMPACT_ID_COUNT_BASE)] = {      \
139*2c2f96dcSApple OSS Distributions 	        [0 ... BITMAP_LEN(COMPACT_ID_COUNT_BASE) - 1] = ~0ull,          \
140*2c2f96dcSApple OSS Distributions 	};                                                                      \
141*2c2f96dcSApple OSS Distributions 	class struct compact_id_table var = {                                   \
142*2c2f96dcSApple OSS Distributions 	        .cidt_bitmap[0] = var##_bits0,                                  \
143*2c2f96dcSApple OSS Distributions 	        .cidt_array[0]  = var##_array0,                                 \
144*2c2f96dcSApple OSS Distributions 	};                                                                      \
145*2c2f96dcSApple OSS Distributions 	STARTUP_ARG(LOCKS, STARTUP_RANK_THIRD, compact_id_table_init, &var)
146*2c2f96dcSApple OSS Distributions 
147*2c2f96dcSApple OSS Distributions #pragma GCC visibility pop
148*2c2f96dcSApple OSS Distributions __END_DECLS
149*2c2f96dcSApple OSS Distributions 
150*2c2f96dcSApple OSS Distributions #endif /* _KERN_COMPACT_ID_H_ */
151