]> git.saurik.com Git - apple/libdispatch.git/blob - os/firehose_buffer_private.h
libdispatch-703.50.37.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_LIBTRACE_HEADER_SIZE 2048ul
42 #define FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT 16
43
44 typedef struct firehose_buffer_range_s {
45 uint16_t fbr_offset; // offset from the start of the buffer
46 uint16_t fbr_length;
47 } *firehose_buffer_range_t;
48
49 #ifdef KERNEL
50
51 typedef struct firehose_chunk_s *firehose_chunk_t;
52
53 // implemented by the kernel
54 extern void __firehose_buffer_push_to_logd(firehose_buffer_t fb, bool for_io);
55 extern void __firehose_critical_region_enter(void);
56 extern void __firehose_critical_region_leave(void);
57 extern void __firehose_allocate(vm_offset_t *addr, vm_size_t size);
58
59 // exported for the kernel
60 firehose_tracepoint_t
61 __firehose_buffer_tracepoint_reserve(uint64_t stamp, firehose_stream_t stream,
62 uint16_t pubsize, uint16_t privsize, uint8_t **privptr);
63
64 void
65 __firehose_buffer_tracepoint_flush(firehose_tracepoint_t vat,
66 firehose_tracepoint_id_u vatid);
67
68 firehose_buffer_t
69 __firehose_buffer_create(size_t *size);
70
71 void
72 __firehose_merge_updates(firehose_push_reply_t update);
73
74 #else
75
76 #define __firehose_critical_region_enter()
77 #define __firehose_critical_region_leave()
78
79 OS_EXPORT
80 const uint32_t _firehose_spi_version;
81
82 OS_ALWAYS_INLINE
83 static inline const uint8_t *
84 _firehose_tracepoint_reader_init(firehose_chunk_t fc, const uint8_t **endptr)
85 {
86 const uint8_t *start = fc->fc_data;
87 const uint8_t *end = fc->fc_start + fc->fc_pos.fcp_next_entry_offs;
88
89 if (end > fc->fc_start + FIREHOSE_CHUNK_SIZE) {
90 end = start;
91 }
92 *endptr = end;
93 return start;
94 }
95
96 OS_ALWAYS_INLINE
97 static inline firehose_tracepoint_t
98 _firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end)
99 {
100 const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data);
101 struct ft_unaligned_s {
102 struct firehose_tracepoint_s ft;
103 } __attribute__((packed, aligned(1))) *uft;
104
105 do {
106 uft = (struct ft_unaligned_s *)*ptr;
107 if (uft->ft.ft_data >= end) {
108 // reached the end
109 return NULL;
110 }
111 if (!uft->ft.ft_length) {
112 // tracepoint write didn't even start
113 return NULL;
114 }
115 if (uft->ft.ft_length > end - uft->ft.ft_data) {
116 // invalid length
117 return NULL;
118 }
119 *ptr += roundup(ft_size + uft->ft.ft_length, 8);
120 // test whether write of the tracepoint was finished
121 } while (os_unlikely(uft->ft.ft_id.ftid_value == 0));
122
123 return (firehose_tracepoint_t)uft;
124 }
125
126 #define firehose_tracepoint_foreach(ft, fbc) \
127 for (const uint8_t *end, *p = _firehose_tracepoint_reader_init(fbc, &end); \
128 ((ft) = _firehose_tracepoint_reader_next(&p, end)); )
129
130 OS_ALWAYS_INLINE
131 static inline bool
132 firehose_buffer_range_validate(firehose_chunk_t fc, firehose_tracepoint_t ft,
133 firehose_buffer_range_t range)
134 {
135 if (range->fbr_offset + range->fbr_length > FIREHOSE_CHUNK_SIZE) {
136 return false;
137 }
138 if (fc->fc_start + range->fbr_offset < ft->ft_data + ft->ft_length) {
139 return false;
140 }
141 return true;
142 }
143
144 #endif // !KERNEL
145
146 #endif // OS_FIREHOSE_SPI
147
148 #endif // __FIREHOSE_BUFFER_PRIVATE__