]> git.saurik.com Git - apple/libdispatch.git/blob - os/firehose_buffer_private.h
libdispatch-703.1.4.tar.gz
[apple/libdispatch.git] / os / firehose_buffer_private.h
1 /*
2 * Copyright (c) 2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21 #ifndef __FIREHOSE_BUFFER_PRIVATE__
22 #define __FIREHOSE_BUFFER_PRIVATE__
23
24 #if OS_FIREHOSE_SPI
25 #ifdef KERNEL
26 #include <stdint.h>
27 #else
28 #include <os/base.h>
29 #include <os/base_private.h>
30 #include <dispatch/dispatch.h>
31 #endif
32
33 #define OS_FIREHOSE_SPI_VERSION 20160318
34
35 /*!
36 * @group Firehose SPI
37 * SPI intended for logd only
38 * Layout of structs is subject to change without notice
39 */
40
41 #define FIREHOSE_BUFFER_CHUNK_SIZE 4096ul
42 #define FIREHOSE_BUFFER_LIBTRACE_HEADER_SIZE 2048ul
43 #define FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT 16
44
45 typedef union {
46 uint64_t fbc_atomic_pos;
47 #define FIREHOSE_BUFFER_POS_ENTRY_OFFS_INC (1ULL << 0)
48 #define FIREHOSE_BUFFER_POS_PRIVATE_OFFS_INC (1ULL << 16)
49 #define FIREHOSE_BUFFER_POS_REFCNT_INC (1ULL << 32)
50 #define FIREHOSE_BUFFER_POS_FULL_BIT (1ULL << 56)
51 #define FIREHOSE_BUFFER_POS_USABLE_FOR_STREAM(pos, stream) \
52 ((((pos).fbc_atomic_pos >> 48) & 0x1ff) == (uint16_t)stream)
53 struct {
54 uint16_t fbc_next_entry_offs;
55 uint16_t fbc_private_offs;
56 uint8_t fbc_refcnt;
57 uint8_t fbc_qos_bits;
58 uint8_t fbc_stream;
59 uint8_t fbc_flag_full : 1;
60 uint8_t fbc_flag_io : 1;
61 uint8_t _fbc_flag_unused : 6;
62 };
63 } firehose_buffer_pos_u;
64
65 typedef struct firehose_buffer_chunk_s {
66 uint8_t fbc_start[0];
67 firehose_buffer_pos_u volatile fbc_pos;
68 uint64_t fbc_timestamp;
69 uint8_t fbc_data[FIREHOSE_BUFFER_CHUNK_SIZE
70 - sizeof(firehose_buffer_pos_u)
71 - sizeof(uint64_t)];
72 } __attribute__((aligned(8))) *firehose_buffer_chunk_t;
73
74 typedef struct firehose_buffer_range_s {
75 uint16_t fbr_offset; // offset from the start of the buffer
76 uint16_t fbr_length;
77 } *firehose_buffer_range_t;
78
79 #ifdef KERNEL
80
81 // implemented by the kernel
82 extern void __firehose_buffer_push_to_logd(firehose_buffer_t fb, bool for_io);
83 extern void __firehose_critical_region_enter(void);
84 extern void __firehose_critical_region_leave(void);
85 extern void __firehose_allocate(vm_offset_t *addr, vm_size_t size);
86
87 // exported for the kernel
88 firehose_tracepoint_t
89 __firehose_buffer_tracepoint_reserve(uint64_t stamp, firehose_stream_t stream,
90 uint16_t pubsize, uint16_t privsize, uint8_t **privptr);
91
92 firehose_tracepoint_t
93 __firehose_buffer_tracepoint_reserve_with_chunk(firehose_buffer_chunk_t fbc,
94 uint64_t stamp, firehose_stream_t stream,
95 uint16_t pubsize, uint16_t privsize, uint8_t **privptr);
96
97 void
98 __firehose_buffer_tracepoint_flush(firehose_tracepoint_t vat,
99 firehose_tracepoint_id_u vatid);
100
101 void
102 __firehose_buffer_tracepoint_flush_chunk(firehose_buffer_chunk_t fbc,
103 firehose_tracepoint_t vat, firehose_tracepoint_id_u vatid);
104
105 firehose_buffer_t
106 __firehose_buffer_create(size_t *size);
107
108 void
109 __firehose_merge_updates(firehose_push_reply_t update);
110
111 #else
112
113 #define __firehose_critical_region_enter()
114 #define __firehose_critical_region_leave()
115
116 OS_EXPORT
117 const uint32_t _firehose_spi_version;
118
119 OS_ALWAYS_INLINE
120 static inline const uint8_t *
121 _firehose_tracepoint_reader_init(firehose_buffer_chunk_t fbc,
122 const uint8_t **endptr)
123 {
124 const uint8_t *start = fbc->fbc_data;
125 const uint8_t *end = fbc->fbc_start + fbc->fbc_pos.fbc_next_entry_offs;
126
127 if (end > fbc->fbc_start + FIREHOSE_BUFFER_CHUNK_SIZE) {
128 end = start;
129 }
130 *endptr = end;
131 return start;
132 }
133
134 OS_ALWAYS_INLINE
135 static inline firehose_tracepoint_t
136 _firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end)
137 {
138 const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data);
139 firehose_tracepoint_t ft;
140
141 do {
142 ft = (firehose_tracepoint_t)*ptr;
143 if (ft->ft_data >= end) {
144 // reached the end
145 return NULL;
146 }
147 if (!ft->ft_length) {
148 // tracepoint write didn't even start
149 return NULL;
150 }
151 if (ft->ft_length > end - ft->ft_data) {
152 // invalid length
153 return NULL;
154 }
155 *ptr += roundup(ft_size + ft->ft_length, 8);
156 // test whether write of the tracepoint was finished
157 } while (os_unlikely(ft->ft_id.ftid_value == 0));
158
159 return ft;
160 }
161
162 #define firehose_tracepoint_foreach(ft, fbc) \
163 for (const uint8_t *end, *p = _firehose_tracepoint_reader_init(fbc, &end); \
164 ((ft) = _firehose_tracepoint_reader_next(&p, end)); )
165
166 OS_ALWAYS_INLINE
167 static inline bool
168 firehose_buffer_range_validate(firehose_buffer_chunk_t fbc,
169 firehose_tracepoint_t ft, firehose_buffer_range_t range)
170 {
171 if (range->fbr_offset + range->fbr_length > FIREHOSE_BUFFER_CHUNK_SIZE) {
172 return false;
173 }
174 if (fbc->fbc_start + range->fbr_offset < ft->ft_data + ft->ft_length) {
175 return false;
176 }
177 return true;
178 }
179
180 #endif // !KERNEL
181
182 #endif // OS_FIREHOSE_SPI
183
184 #endif // __FIREHOSE_BUFFER_PRIVATE__