1 #include <mach/port.h> 2 #include <mach/mach.h> 3 #include <sys/event.h> 4 #include <dispatch/dispatch.h> 5 #include <pthread/workqueue_private.h> 6 #include <darwintest.h> 7 8 T_GLOBAL_META( 9 T_META_NAMESPACE("xnu.workq"), 10 T_META_RADAR_COMPONENT_NAME("xnu"), 11 T_META_RADAR_COMPONENT_VERSION("workq"), 12 T_META_RUN_CONCURRENTLY(true)); 13 14 T_DECL(thread_request_83476290, 15 "test that mach_msg_trap causes a thread request") 16 { 17 mach_port_t mp, rp; 18 kern_return_t kr; 19 dispatch_source_t ds; 20 dispatch_queue_t dq; 21 int kq; 22 23 mach_port_options_t opts = { 24 .flags = MPO_INSERT_SEND_RIGHT, 25 }; 26 27 kr = mach_port_construct(mach_task_self(), &opts, 0, &mp); 28 T_ASSERT_MACH_SUCCESS(kr, "create receive right %x", mp); 29 30 kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &rp); 31 T_ASSERT_MACH_SUCCESS(kr, "create reply port right %x", rp); 32 33 dq = dispatch_queue_create_with_target("tr.q", DISPATCH_QUEUE_SERIAL, NULL); 34 ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, mp, 0, dq); 35 dispatch_source_set_event_handler(ds, ^{ 36 T_PASS("received the event"); 37 T_END; 38 }); 39 dispatch_activate(ds); 40 41 T_LOG("wait 1ms for the existing dispatch thread to park again"); 42 usleep(1000); 43 44 kq = kqueue(); 45 T_ASSERT_POSIX_SUCCESS(kq, "kqueue()"); 46 47 /* 48 * Now use the threads that were on the pool to make sure the process 49 * is starved 50 */ 51 dispatch_async(dispatch_get_global_queue(0, 0), ^{ 52 usleep(1000); 53 struct kevent_qos_s ke = { 54 .ident = 1, 55 .filter = EVFILT_USER, 56 .fflags = NOTE_TRIGGER, 57 }; 58 int rc = kevent_qos(kq, &ke, 1, NULL, 0, NULL, NULL, 0); 59 T_ASSERT_POSIX_SUCCESS(rc, "NOTE_TRIGGER"); 60 pause(); 61 }); 62 63 struct kevent_qos_s ke = { 64 .ident = 1, 65 .filter = EVFILT_USER, 66 .flags = EV_ADD | EV_CLEAR, 67 }; 68 69 T_LOG("block in kevent, call mach_msg with 5s timeout"); 70 (void)kevent_qos(kq, &ke, 1, &ke, 1, NULL, NULL, 0); 71 72 mach_msg_header_t hdr = { 73 .msgh_remote_port = mp, 74 .msgh_local_port = rp, 75 .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_COPY_SEND, 76 MACH_MSG_TYPE_MAKE_SEND_ONCE, 0, 0), 77 .msgh_id = 1, 78 .msgh_size = sizeof(hdr), 79 }; 80 81 kr = mach_msg(&hdr, MACH_SEND_MSG | MACH_RCV_MSG | MACH_RCV_TIMEOUT, 82 sizeof(hdr), sizeof(hdr), rp, 5000, 0); 83 T_FAIL("mach_msg returned: %#x", kr); 84 } 85