Skip to content

Commit dcdacda

Browse files
committed
Merge libdispatch-749
Signed-off-by: Daniel A. Steffen <dsteffen@apple.com>
1 parent ff7dc5b commit dcdacda

13 files changed

+136
-119
lines changed

os/firehose_buffer_private.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,27 +99,29 @@ static inline firehose_tracepoint_t
9999
_firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end)
100100
{
101101
const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data);
102-
firehose_tracepoint_t ft;
102+
struct ft_unaligned_s {
103+
struct firehose_tracepoint_s ft;
104+
} __attribute__((packed, aligned(1))) *uft;
103105

104106
do {
105-
ft = (firehose_tracepoint_t)*ptr;
106-
if (ft->ft_data >= end) {
107+
uft = (struct ft_unaligned_s *)*ptr;
108+
if (uft->ft.ft_data >= end) {
107109
// reached the end
108110
return NULL;
109111
}
110-
if (!ft->ft_length) {
112+
if (!uft->ft.ft_length) {
111113
// tracepoint write didn't even start
112114
return NULL;
113115
}
114-
if (ft->ft_length > end - ft->ft_data) {
116+
if (uft->ft.ft_length > end - uft->ft.ft_data) {
115117
// invalid length
116118
return NULL;
117119
}
118-
*ptr += roundup(ft_size + ft->ft_length, 8);
120+
*ptr += roundup(ft_size + uft->ft.ft_length, 8);
119121
// test whether write of the tracepoint was finished
120-
} while (os_unlikely(ft->ft_id.ftid_value == 0));
122+
} while (os_unlikely(uft->ft.ft_id.ftid_value == 0));
121123

122-
return ft;
124+
return (firehose_tracepoint_t)uft;
123125
}
124126

125127
#define firehose_tracepoint_foreach(ft, fbc) \

os/voucher_activity_private.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@
4242
#define OS_VOUCHER_EXPORT OS_EXPORT
4343
#endif
4444

45-
#define __VOUCHER_ACTIVITY_IGNORE_DEPRECATION_PUSH \
46-
_Pragma("clang diagnostic push") \
47-
_Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
48-
#define __VOUCHER_ACTIVITY_IGNORE_DEPRECATION_POP \
49-
_Pragma("clang diagnostic pop")
50-
5145
__BEGIN_DECLS
5246

5347
/*!
@@ -273,11 +267,12 @@ voucher_activity_trace_with_private_strings(firehose_stream_t stream,
273267
const void *privdata, size_t privlen);
274268

275269
typedef const struct voucher_activity_hooks_s {
276-
#define VOUCHER_ACTIVITY_HOOKS_VERSION 3
270+
#define VOUCHER_ACTIVITY_HOOKS_VERSION 4
277271
long vah_version;
278272
mach_port_t (*vah_get_logd_port)(void);
279273
dispatch_mach_handler_function_t vah_debug_channel_handler;
280274
kern_return_t (*vah_get_reconnect_info)(mach_vm_address_t *, mach_vm_size_t *);
275+
void (*vah_metadata_init)(void *metadata_buffer, size_t size);
281276
} *voucher_activity_hooks_t;
282277

283278
/*!

src/allocator.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -274,22 +274,16 @@ mark_bitmap_as_full_if_still_full(volatile bitmap_t *supermap,
274274
dispatch_assert(bitmap_index < BITMAPS_PER_SUPERMAP);
275275
#endif
276276
const bitmap_t mask = BITMAP_C(1) << bitmap_index;
277-
bitmap_t s, s_new, s_masked;
277+
bitmap_t s, s_new;
278278

279-
if (!bitmap_is_full(*bitmap)) {
280-
return;
281-
}
282-
s_new = *supermap;
283-
for (;;) {
284-
// No barriers because supermaps are only advisory, they
285-
// don't protect access to other memory.
286-
s = s_new;
287-
s_masked = s | mask;
288-
if (os_atomic_cmpxchgvw(supermap, s, s_masked, &s_new, relaxed) ||
289-
!bitmap_is_full(*bitmap)) {
290-
return;
279+
// No barriers because supermaps are only advisory, they
280+
// don't protect access to other memory.
281+
os_atomic_rmw_loop(supermap, s, s_new, relaxed, {
282+
if (!bitmap_is_full(*bitmap)) {
283+
os_atomic_rmw_loop_give_up(return);
291284
}
292-
}
285+
s_new = s | mask;
286+
});
293287
}
294288

295289
#pragma mark -

src/event/event_config.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,19 @@
8888
# endif
8989

9090
# if !defined(NOTE_MEMORYSTATUS_PROC_LIMIT_WARN) || \
91-
!DISPATCH_HOST_SUPPORTS_OSX(101200)
91+
!DISPATCH_MIN_REQUIRED_OSX_AT_LEAST(101200)
9292
# undef NOTE_MEMORYSTATUS_PROC_LIMIT_WARN
9393
# define NOTE_MEMORYSTATUS_PROC_LIMIT_WARN 0
9494
# endif // NOTE_MEMORYSTATUS_PROC_LIMIT_WARN
9595

9696
# if !defined(NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL) || \
97-
!DISPATCH_HOST_SUPPORTS_OSX(101200)
97+
!DISPATCH_MIN_REQUIRED_OSX_AT_LEAST(101200)
9898
# undef NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL
9999
# define NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL 0
100100
# endif // NOTE_MEMORYSTATUS_PROC_LIMIT_CRITICAL
101101

102102
# ifndef DISPATCH_KEVENT_TREAT_ENOENT_AS_EINPROGRESS
103-
# if TARGET_OS_MAC && !DISPATCH_HOST_SUPPORTS_OSX(101200)
103+
# if TARGET_OS_MAC && !DISPATCH_MIN_REQUIRED_OSX_AT_LEAST(101200)
104104
// deferred delete can return bogus ENOENTs on older kernels
105105
# define DISPATCH_KEVENT_TREAT_ENOENT_AS_EINPROGRESS 1
106106
# else

src/firehose/firehose.defs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ register(
3535
comm_recvp : mach_port_move_receive_t;
3636
comm_sendp : mach_port_make_send_t;
3737
extra_info_port : mach_port_move_send_t;
38-
extra_info_size : mach_vm_size_t
38+
extra_info_size : mach_vm_size_t;
39+
ServerAuditToken atoken : audit_token_t
3940
);
4041

4142
routine

src/firehose/firehose_server.c

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ firehose_client_notify(firehose_client_t fc, mach_port_t reply_port)
7474
firehose_atomic_max2o(fc, fc_io_sent_flushed_pos,
7575
push_reply.fpr_io_flushed_pos, relaxed);
7676

77-
if (fc->fc_is_kernel) {
77+
if (!fc->fc_pid) {
7878
if (ioctl(server_config.fs_kernel_fd, LOGFLUSHED, &push_reply) < 0) {
7979
dispatch_assume_zero(errno);
8080
}
@@ -209,18 +209,25 @@ firehose_client_drain(firehose_client_t fc, mach_port_t port, uint32_t flags)
209209
ref = (flushed + count) & FIREHOSE_RING_POS_IDX_MASK;
210210
ref = os_atomic_load(&fbh_ring[ref], relaxed);
211211
ref &= FIREHOSE_RING_POS_IDX_MASK;
212-
} while (fc->fc_is_kernel && !ref);
212+
} while (!fc->fc_pid && !ref);
213213
count++;
214214
if (!ref) {
215215
_dispatch_debug("Ignoring invalid page reference in ring: %d", ref);
216216
continue;
217217
}
218218

219219
fbc = firehose_buffer_ref_to_chunk(fb, ref);
220+
if (fbc->fc_pos.fcp_stream == firehose_stream_metadata) {
221+
// serialize with firehose_client_metadata_stream_peek
222+
os_unfair_lock_lock(&fc->fc_lock);
223+
}
220224
server_config.fs_handler(fc, evt, fbc);
221225
if (slowpath(snapshot)) {
222226
snapshot->handler(fc, evt, fbc);
223227
}
228+
if (fbc->fc_pos.fcp_stream == firehose_stream_metadata) {
229+
os_unfair_lock_unlock(&fc->fc_lock);
230+
}
224231
// clients not using notifications (single threaded) always drain fully
225232
// because they use all their limit, always
226233
} while (!fc->fc_use_notifs || count < DRAIN_BATCH_SIZE || snapshot);
@@ -238,7 +245,7 @@ firehose_client_drain(firehose_client_t fc, mach_port_t port, uint32_t flags)
238245
client_flushed = os_atomic_load2o(&fb->fb_header,
239246
fbh_ring_tail.frp_mem_flushed, relaxed);
240247
}
241-
if (fc->fc_is_kernel) {
248+
if (!fc->fc_pid) {
242249
// will fire firehose_client_notify() because port is MACH_PORT_DEAD
243250
port = fc->fc_sendp;
244251
} else if (!port && client_flushed == sent_flushed && fc->fc_use_notifs) {
@@ -253,7 +260,7 @@ firehose_client_drain(firehose_client_t fc, mach_port_t port, uint32_t flags)
253260
if (port) {
254261
firehose_client_notify(fc, port);
255262
}
256-
if (fc->fc_is_kernel) {
263+
if (!fc->fc_pid) {
257264
if (!(flags & FIREHOSE_DRAIN_POLL)) {
258265
// see firehose_client_kernel_source_handle_event
259266
dispatch_resume(fc->fc_kernel_source);
@@ -283,7 +290,7 @@ firehose_client_drain(firehose_client_t fc, mach_port_t port, uint32_t flags)
283290
// from now on all IO/mem drains depending on `for_io` will be no-op
284291
// (needs_<for_io>_snapshot: false, memory_corrupted: true). we can safely
285292
// silence the corresponding source of drain wake-ups.
286-
if (!fc->fc_is_kernel) {
293+
if (fc->fc_pid) {
287294
dispatch_source_cancel(for_io ? fc->fc_io_source : fc->fc_mem_source);
288295
}
289296
}
@@ -502,7 +509,7 @@ firehose_client_resume(firehose_client_t fc,
502509
dispatch_assert_queue(server_config.fs_io_drain_queue);
503510
TAILQ_INSERT_TAIL(&server_config.fs_clients, fc, fc_entry);
504511
server_config.fs_handler(fc, FIREHOSE_EVENT_CLIENT_CONNECTED, (void *)fcci);
505-
if (fc->fc_is_kernel) {
512+
if (!fc->fc_pid) {
506513
dispatch_activate(fc->fc_kernel_source);
507514
} else {
508515
dispatch_mach_connect(fc->fc_mach_channel,
@@ -553,14 +560,15 @@ _firehose_client_create(firehose_buffer_t fb)
553560
}
554561

555562
static firehose_client_t
556-
firehose_client_create(firehose_buffer_t fb,
563+
firehose_client_create(firehose_buffer_t fb, pid_t pid,
557564
mach_port_t comm_recvp, mach_port_t comm_sendp)
558565
{
559566
uint64_t unique_pid = fb->fb_header.fbh_uniquepid;
560567
firehose_client_t fc = _firehose_client_create(fb);
561568
dispatch_mach_t dm;
562569
dispatch_source_t ds;
563570

571+
fc->fc_pid = pid;
564572
ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_OR, 0, 0,
565573
server_config.fs_mem_drain_queue);
566574
_os_object_retain_internal_inline(&fc->fc_as_os_object);
@@ -622,7 +630,6 @@ firehose_kernel_client_create(void)
622630
}
623631

624632
fc = _firehose_client_create((firehose_buffer_t)(uintptr_t)fb_map.fbmi_addr);
625-
fc->fc_is_kernel = true;
626633
ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)fd, 0,
627634
fs->fs_ipc_queue);
628635
dispatch_set_context(ds, fc);
@@ -663,12 +670,9 @@ uint64_t
663670
firehose_client_get_unique_pid(firehose_client_t fc, pid_t *pid_out)
664671
{
665672
firehose_buffer_header_t fbh = &fc->fc_buffer->fb_header;
666-
if (fc->fc_is_kernel) {
667-
if (pid_out) *pid_out = 0;
668-
return 0;
669-
}
670-
if (pid_out) *pid_out = fbh->fbh_pid ?: ~(pid_t)0;
671-
return fbh->fbh_uniquepid ?: ~0ull;
673+
if (pid_out) *pid_out = fc->fc_pid;
674+
if (!fc->fc_pid) return 0;
675+
return fbh->fbh_uniquepid ? fbh->fbh_uniquepid : ~0ull;
672676
}
673677

674678
void *
@@ -800,47 +804,42 @@ firehose_server_copy_queue(firehose_server_queue_t which)
800804

801805
void
802806
firehose_client_metadata_stream_peek(firehose_client_t fc,
803-
firehose_event_t context, bool (^peek_should_start)(void),
807+
OS_UNUSED firehose_event_t context, bool (^peek_should_start)(void),
804808
bool (^peek)(firehose_chunk_t fbc))
805809
{
806-
if (context != FIREHOSE_EVENT_MEM_BUFFER_RECEIVED) {
807-
return dispatch_sync(server_config.fs_mem_drain_queue, ^{
808-
firehose_client_metadata_stream_peek(fc,
809-
FIREHOSE_EVENT_MEM_BUFFER_RECEIVED, peek_should_start, peek);
810-
});
811-
}
810+
os_unfair_lock_lock(&fc->fc_lock);
812811

813-
if (peek_should_start && !peek_should_start()) {
814-
return;
815-
}
816-
817-
firehose_buffer_t fb = fc->fc_buffer;
818-
firehose_buffer_header_t fbh = &fb->fb_header;
819-
uint64_t bitmap = fbh->fbh_bank.fbb_metadata_bitmap;
812+
if (peek_should_start && peek_should_start()) {
813+
firehose_buffer_t fb = fc->fc_buffer;
814+
firehose_buffer_header_t fbh = &fb->fb_header;
815+
uint64_t bitmap = fbh->fbh_bank.fbb_metadata_bitmap;
820816

821-
while (bitmap) {
822-
uint16_t ref = firehose_bitmap_first_set(bitmap);
823-
firehose_chunk_t fbc = firehose_buffer_ref_to_chunk(fb, ref);
824-
uint16_t fbc_length = fbc->fc_pos.fcp_next_entry_offs;
817+
while (bitmap) {
818+
uint16_t ref = firehose_bitmap_first_set(bitmap);
819+
firehose_chunk_t fbc = firehose_buffer_ref_to_chunk(fb, ref);
820+
uint16_t fbc_length = fbc->fc_pos.fcp_next_entry_offs;
825821

826-
bitmap &= ~(1ULL << ref);
827-
if (fbc->fc_start + fbc_length <= fbc->fc_data) {
828-
// this page has its "recycle-requeue" done, but hasn't gone
829-
// through "recycle-reuse", or it has no data, ditch it
830-
continue;
831-
}
832-
if (!((firehose_tracepoint_t)fbc->fc_data)->ft_length) {
833-
// this thing has data, but the first tracepoint is unreadable
834-
// so also just ditch it
835-
continue;
836-
}
837-
if (fbc->fc_pos.fcp_stream != firehose_stream_metadata) {
838-
continue;
839-
}
840-
if (!peek(fbc)) {
841-
break;
822+
bitmap &= ~(1ULL << ref);
823+
if (fbc->fc_start + fbc_length <= fbc->fc_data) {
824+
// this page has its "recycle-requeue" done, but hasn't gone
825+
// through "recycle-reuse", or it has no data, ditch it
826+
continue;
827+
}
828+
if (!((firehose_tracepoint_t)fbc->fc_data)->ft_length) {
829+
// this thing has data, but the first tracepoint is unreadable
830+
// so also just ditch it
831+
continue;
832+
}
833+
if (fbc->fc_pos.fcp_stream != firehose_stream_metadata) {
834+
continue;
835+
}
836+
if (!peek(fbc)) {
837+
break;
838+
}
842839
}
843840
}
841+
842+
os_unfair_lock_unlock(&fc->fc_lock);
844843
}
845844

846845
OS_NOINLINE OS_COLD
@@ -925,7 +924,7 @@ firehose_snapshot_start(void *ctxt)
925924
// 1. mark all the clients participating in the current snapshot
926925
// and enter the group for each bit set
927926
TAILQ_FOREACH(fci, &server_config.fs_clients, fc_entry) {
928-
if (fci->fc_is_kernel) {
927+
if (!fci->fc_pid) {
929928
#if TARGET_OS_SIMULATOR
930929
continue;
931930
#endif
@@ -965,7 +964,7 @@ firehose_snapshot_start(void *ctxt)
965964
// were removed from the list have already left the group
966965
// (see firehose_client_finalize())
967966
TAILQ_FOREACH(fcj, &server_config.fs_clients, fc_entry) {
968-
if (fcj->fc_is_kernel) {
967+
if (!fcj->fc_pid) {
969968
#if !TARGET_OS_SIMULATOR
970969
firehose_client_kernel_source_handle_event(fcj);
971970
#endif
@@ -1028,7 +1027,8 @@ kern_return_t
10281027
firehose_server_register(mach_port_t server_port OS_UNUSED,
10291028
mach_port_t mem_port, mach_vm_size_t mem_size,
10301029
mach_port_t comm_recvp, mach_port_t comm_sendp,
1031-
mach_port_t extra_info_port, mach_vm_size_t extra_info_size)
1030+
mach_port_t extra_info_port, mach_vm_size_t extra_info_size,
1031+
audit_token_t atoken)
10321032
{
10331033
mach_vm_address_t base_addr = 0;
10341034
firehose_client_t fc = NULL;
@@ -1077,7 +1077,9 @@ firehose_server_register(mach_port_t server_port OS_UNUSED,
10771077
fcci.fcci_size = (size_t)extra_info_size;
10781078
}
10791079

1080-
fc = firehose_client_create((firehose_buffer_t)base_addr,
1080+
pid_t pid = (pid_t)atoken.val[5]; // same as audit_token_to_pid()
1081+
if (pid == 0) pid = ~0;
1082+
fc = firehose_client_create((firehose_buffer_t)base_addr, pid,
10811083
comm_recvp, comm_sendp);
10821084
dispatch_async(server_config.fs_io_drain_queue, ^{
10831085
firehose_client_resume(fc, &fcci);

src/firehose/firehose_server_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ struct firehose_client_s {
5353
dispatch_source_t fc_mem_source;
5454
mach_port_t fc_recvp;
5555
mach_port_t fc_sendp;
56+
os_unfair_lock fc_lock;
57+
pid_t fc_pid;
5658
bool fc_use_notifs;
5759
bool fc_memory_corrupted;
5860
bool fc_needs_io_snapshot;
5961
bool fc_needs_mem_snapshot;
60-
bool fc_is_kernel;
6162
};
6263

6364
void

0 commit comments

Comments
 (0)