1*8d741a5dSApple OSS Distributions #include <unistd.h> 2*8d741a5dSApple OSS Distributions #include <pthread.h> 3*8d741a5dSApple OSS Distributions #include <errno.h> 4*8d741a5dSApple OSS Distributions 5*8d741a5dSApple OSS Distributions #include <sys/event.h> 6*8d741a5dSApple OSS Distributions #include <mach/mach.h> 7*8d741a5dSApple OSS Distributions #include <mach/mach_port.h> 8*8d741a5dSApple OSS Distributions 9*8d741a5dSApple OSS Distributions #include <Block.h> 10*8d741a5dSApple OSS Distributions #include <darwintest.h> 11*8d741a5dSApple OSS Distributions 12*8d741a5dSApple OSS Distributions T_DECL(kqueue_nesting_level, "rdar://100277117 (Reduce kqueue nesting level so that we don't overflow kernel stack)") 13*8d741a5dSApple OSS Distributions { 14*8d741a5dSApple OSS Distributions // Create a port and register a knote for it on a kqueue 15*8d741a5dSApple OSS Distributions mach_port_t port = MACH_PORT_NULL; 16*8d741a5dSApple OSS Distributions kern_return_t kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port); 17*8d741a5dSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "allocating a port with a receive right"); 18*8d741a5dSApple OSS Distributions 19*8d741a5dSApple OSS Distributions int port_kq = kqueue(); 20*8d741a5dSApple OSS Distributions struct kevent_qos_s event = { 21*8d741a5dSApple OSS Distributions .ident = port, 22*8d741a5dSApple OSS Distributions .filter = EVFILT_MACHPORT, 23*8d741a5dSApple OSS Distributions .flags = EV_ADD | EV_ENABLE, 24*8d741a5dSApple OSS Distributions .qos = 0x00, 25*8d741a5dSApple OSS Distributions .udata = 0x66666666, 26*8d741a5dSApple OSS Distributions .fflags = MACH_RCV_MSG, 27*8d741a5dSApple OSS Distributions .xflags = 0, 28*8d741a5dSApple OSS Distributions .data = 0, 29*8d741a5dSApple OSS Distributions .ext = {}, 30*8d741a5dSApple OSS Distributions }; 31*8d741a5dSApple OSS Distributions int nevents = kevent_qos(port_kq, &event, 1, NULL, 0, NULL, NULL, 0); 32*8d741a5dSApple OSS Distributions T_EXPECT_EQ(nevents, 0, NULL); 33*8d741a5dSApple OSS Distributions 34*8d741a5dSApple OSS Distributions // Register the other kqueues 35*8d741a5dSApple OSS Distributions int child_kq = port_kq; 36*8d741a5dSApple OSS Distributions 37*8d741a5dSApple OSS Distributions for (size_t i = 0; i < 1000; i++) { 38*8d741a5dSApple OSS Distributions int kq = kqueue(); 39*8d741a5dSApple OSS Distributions struct kevent_qos_s kq_read_event = { 40*8d741a5dSApple OSS Distributions .ident = child_kq, 41*8d741a5dSApple OSS Distributions .filter = EVFILT_READ, 42*8d741a5dSApple OSS Distributions .flags = EV_ADD | EV_ENABLE, 43*8d741a5dSApple OSS Distributions .qos = 0x00, 44*8d741a5dSApple OSS Distributions .udata = 0x66666666, 45*8d741a5dSApple OSS Distributions .fflags = 0x00, 46*8d741a5dSApple OSS Distributions .xflags = 0x00, 47*8d741a5dSApple OSS Distributions .data = 0, 48*8d741a5dSApple OSS Distributions .ext = {}, 49*8d741a5dSApple OSS Distributions }; 50*8d741a5dSApple OSS Distributions 51*8d741a5dSApple OSS Distributions nevents = kevent_qos(kq, &kq_read_event, 1, NULL, 0, NULL, NULL, 0); 52*8d741a5dSApple OSS Distributions // This kevent may sometimes fail after we exceed the limit enforced by the 53*8d741a5dSApple OSS Distributions // kernel in which case, we'd just have created kqueues but not set up any 54*8d741a5dSApple OSS Distributions // knotes on them. 55*8d741a5dSApple OSS Distributions // 56*8d741a5dSApple OSS Distributions // On old-OSes prior to rdar://100277117, this would always succeed and then 57*8d741a5dSApple OSS Distributions // we'd panic when we send a message 58*8d741a5dSApple OSS Distributions child_kq = kq; 59*8d741a5dSApple OSS Distributions } 60*8d741a5dSApple OSS Distributions 61*8d741a5dSApple OSS Distributions // Send a message to the port and activate the first kqueue 62*8d741a5dSApple OSS Distributions struct { 63*8d741a5dSApple OSS Distributions mach_msg_header_t header; 64*8d741a5dSApple OSS Distributions uint64_t data; 65*8d741a5dSApple OSS Distributions } message = { 66*8d741a5dSApple OSS Distributions .header = { 67*8d741a5dSApple OSS Distributions .msgh_remote_port = port, 68*8d741a5dSApple OSS Distributions .msgh_local_port = MACH_PORT_NULL, 69*8d741a5dSApple OSS Distributions .msgh_voucher_port = MACH_PORT_NULL, 70*8d741a5dSApple OSS Distributions .msgh_size = sizeof(message), 71*8d741a5dSApple OSS Distributions .msgh_id = 0x88888888, 72*8d741a5dSApple OSS Distributions .msgh_bits = MACH_MSGH_BITS_SET(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0, 0, 0), 73*8d741a5dSApple OSS Distributions }, 74*8d741a5dSApple OSS Distributions .data = 0x8888888888888, 75*8d741a5dSApple OSS Distributions }; 76*8d741a5dSApple OSS Distributions 77*8d741a5dSApple OSS Distributions kr = mach_msg(&message.header, MACH_SEND_MSG, sizeof(message), 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); 78*8d741a5dSApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "mach_msg(SEND)"); 79*8d741a5dSApple OSS Distributions } 80