__CFRunLoopRun函数详解注释

11 阅读17分钟

在学习过程中,借助了AI来辅助分析。

苹果开源代码: CoreFoundation/CFRunLoop.c

__CFRunLoopRun函数

/* rl, rlm are locked on entrance and exit */
// rl: RunLoop 实例引用
// rlm: 当前要运行的 Mode
// seconds: 超时时间(秒),0 表示立即返回,负数或极大值表示无限等待
// - 小于等于0:立即超时
// - 小于等于TIMER_INTERVAL_LIMIT(504911232.0秒):会计算一个未来超时的时间
// - 其他情况:runloop无限运行,不超时。
// stopAfterHandle: 是否在处理一个事件后就停止
// previousMode: 上一次运行的模式(用于检测重入)
static int32_t __CFRunLoopRun(CFRunLoopRef rl, CFRunLoopModeRef rlm, CFTimeInterval seconds, Boolean stopAfterHandle, CFRunLoopModeRef previousMode) {
    // 记录开始时间戳(Time Stamp Register)
    // mach_absolute_time() 返回 CPU 时钟周期数,是 macOS 上最精确的时间测量方式
    // 用于后续计算超时和性能统计
    uint64_t startTSR = mach_absolute_time();

    // ========================================
    // 第一步:检查停止状态
    // ========================================
    
    // 检查 RunLoop 是否已被标记为停止(这个标志通过 CFRunLoopStop() 设置)
    if (__CFRunLoopIsStopped(rl)) { 
        // 清除停止标志,恢复正常状态
        __CFRunLoopUnsetStopped(rl);
        // 立即返回 "已停止" 状态码
        return kCFRunLoopRunStopped;
    } else if (rlm->_stopped) { // 检查 Mode 是否被标记为停止
        // 清除 Mode 的停止标志
        rlm->_stopped = false;
        // 立即返回 "已停止" 状态码
        return kCFRunLoopRunStopped;
    }
    
    // ========================================
    // 第二步:设置 GCD 主队列端口
    // ========================================
    
// 条件编译:如果系统支持 GCD (Grand Central Dispatch)
#if __HAS_DISPATCH__
    // 初始化 dispatch 端口为空
    // 这个端口用于接收 GCD 主队列的事件
    __CFPort dispatchPort = CFPORT_NULL;
    // 判断是否可以安全地处理 libdispatch 主队列
    // 条件分解:
    // 1. pthread_main_np() == 1:必须在主线程
    // 2. 两个子条件之一:
    //    a) HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode
    //       - 只在基础调用时处理 && 没有上一个模式(非重入)
    //    b) !HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(__CFTSDKeyIsInGCDMainQ)
    //       - 不限制基础调用 && 当前不在 GCD 主队列中执行
    Boolean libdispatchQSafe = (pthread_main_np() == 1) && ((HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && NULL == previousMode) || (!HANDLE_DISPATCH_ON_BASE_INVOCATION_ONLY && 0 == _CFGetTSD(__CFTSDKeyIsInGCDMainQ)));
    // 如果满足以下所有条件,获取 GCD 主队列端口:
    // 1. libdispatchQSafe 为 true(上面计算的)
    // 2. 当前是主 RunLoop
    // 3. 当前模式在 common modes 集合中
    // 作用:让 RunLoop 能够处理 GCD 主队列派发的任务
    if (libdispatchQSafe && (CFRunLoopGetMain() == rl) && CFSetContainsValue(rl->_commonModes, rlm->_name)) dispatchPort = _dispatch_get_main_queue_port_4CF();
#endif

    // ========================================
    // 第三步:设置 dispatch source 定时器端口
    // ========================================
    
// 条件编译:如果使用 dispatch source 作为定时器实现
// ObjC 运行时使用这个,Swift 运行时使用 mk_timer
#if USE_DISPATCH_SOURCE_FOR_TIMERS
    // 初始化模式队列端口为空
    mach_port_name_t modeQueuePort = MACH_PORT_NULL;
    // 如果当前模式有关联的 dispatch queue
    if (rlm->_queue) {
        // 获取这个队列的 Mach 端口
        // 用于接收 dispatch 定时器事件
        modeQueuePort = _dispatch_runloop_root_queue_get_port_4CF(rlm->_queue);
        // 如果获取端口失败
        if (!modeQueuePort) {
            // 这是致命错误,直接崩溃
            // 因为没有端口就无法接收定时器事件
            CRASH("Unable to get port for run loop mode queue (%d)", -1);
        }
    }
#endif

    // ========================================
    // 第四步:计算超时时间
    // ========================================

    // 终止时间戳(Time Stamp Register)
    // 0 表示立即超时,UINT64_MAX 表示无限等待
    uint64_t termTSR = 0ULL;
#if __HAS_DISPATCH__
    // 超时定时器(使用 GCD dispatch source)
    // 用于在指定时间后唤醒 RunLoop
    dispatch_source_t timeout_timer = NULL;
#endif
    // 情况1:立即超时
    // 当 seconds <= 0 时,不等待,立即检查事件后返回
    if (seconds <= 0.0) { // instant timeout
        seconds = 0.0;
        termTSR = 0ULL;
    } else if (seconds <= TIMER_INTERVAL_LIMIT) { // 情况2:正常超时 TIMER_INTERVAL_LIMIT = 504911232.0 秒(约16年)
        // 计算终止时间戳 = 开始时间 + 超时间隔
        // __CFTimeIntervalToTSR 将秒转换为 TSR 单位
        termTSR = startTSR + __CFTimeIntervalToTSR(seconds);
// 使用 GCD 创建超时定时器
#if __HAS_DISPATCH__
        // 选择合适的队列:
        // - 主线程:使用匹配主线程的队列
        // - 其他线程:使用后台队列
	dispatch_queue_t queue = (pthread_main_np() == 1) ? __CFDispatchQueueGetGenericMatchingMain() : __CFDispatchQueueGetGenericBackground();
        // 创建定时器类型的 dispatch source
        // 参数:类型、句柄(0表示自动)、掩码(0)、目标队列
	timeout_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

        // 增加 RunLoop 的引用计数
        // 因为 Block 会捕获 rl,防止过早释放
        CFRetain(rl);
        // 设置定时器触发时的事件处理 Block
        dispatch_source_set_event_handler(timeout_timer, ^{
            // 探针宏:记录因超时唤醒(DTrace)
            CFRUNLOOP_WAKEUP_FOR_TIMEOUT();
            // 内核追踪事件:记录超时唤醒
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_TIMEOUT, rl, 0, 0, 0);
            // 唤醒 RunLoop
            // 发送 Mach 消息到 _wakeUpPort
            CFRunLoopWakeUp(rl);
            // 因为间隔设置为 DISPATCH_TIME_FOREVER,所以只触发一次
            // The interval is DISPATCH_TIME_FOREVER, so this won't fire again
        });
        // 设置取消处理 Block
        // 当定时器被取消时调用
        dispatch_source_set_cancel_handler(timeout_timer, ^{
            // 释放之前 retain 的 RunLoop
            CFRelease(rl);
        });

        // 计算绝对超时时间点(纳秒)
        // 1. __CFTSRToTimeInterval(startTSR):将开始 TSR 转换为秒
        // 2. 加上超时秒数
        // 3. 乘以 10^9 转换为纳秒
        uint64_t ns_at = (uint64_t)((__CFTSRToTimeInterval(startTSR) + seconds) * 1000000000ULL);
        // 设置定时器参数:
        // - 触发时间:dispatch_time(1, ns_at) - 绝对时间
        // - 间隔:DISPATCH_TIME_FOREVER - 不重复
        // - 容差:1000 纳秒 = 1 微秒
        dispatch_source_set_timer(timeout_timer, dispatch_time(1, ns_at), DISPATCH_TIME_FOREVER, 1000ULL);
        // 启动定时器(dispatch source 创建时是挂起状态)
        dispatch_resume(timeout_timer);
#endif
    } else { // infinite timeout。情况3:无限超时,当 seconds 大于 TIMER_INTERVAL_LIMIT 时
        // 设置一个极大的值(约317年)
        seconds = 9999999999.0;
        // 终止时间设为最大值,实际上永不超时
        termTSR = UINT64_MAX;
    }
    
    // ========================================
    // 第五步:初始化循环变量
    // ========================================

    // 标记上次是否处理了 dispatch 端口
    // 初始为 true,防止第一次循环时重复检查 dispatch 端口
    Boolean didDispatchPortLastTime = true;
    // 返回值
    // 0 表示继续循环
    // 非 0 表示退出循环,值为退出原因:
    // - kCFRunLoopRunFinished: 模式为空
    // - kCFRunLoopRunStopped: 被停止
    // - kCFRunLoopRunTimedOut: 超时
    // - kCFRunLoopRunHandledSource: 处理了一个 source
    int32_t retVal = 0;
    // 开始主循环
    // 使用 do-while 确保至少执行一次
    // 通过 retVal 控制退出:retVal == 0 继续,非 0 退出
    do {
        // ========================================
        // 步骤 1: 初始化本轮循环的变量
        // ========================================
// macOS 平台特定变量
#if TARGET_OS_MAC
        // voucher 状态(用于性能追踪和调试)
        // UNCHANGED 表示初始状态,未改变
        voucher_mach_msg_state_t voucherState = VOUCHER_MACH_MSG_STATE_UNCHANGED;
        // voucher 的副本指针
        // voucher 是 macOS 的上下文追踪机制
        voucher_t voucherCopy = NULL;
#endif
        // 消息缓冲区,3KB 大小
        // 用于接收 Mach 消息
        // 如果消息超过 3KB,会动态分配更大的缓冲区
        uint8_t msg_buffer[3 * 1024];
// macOS 平台:使用 Mach 消息
#if TARGET_OS_MAC
        // Mach 消息头指针
        // 指向实际接收到的消息
        mach_msg_header_t *msg = NULL;
        // 被唤醒的 Mach 端口
        // 用于判断是哪个事件源唤醒了 RunLoop
        mach_port_t livePort = MACH_PORT_NULL;
#endif
        // 等待集合
        // 包含当前模式下所有需要监听的端口:
        // - _wakeUpPort: 手动唤醒端口
        // - _timerPort: 定时器端口
        // - Source1 的各个端口
        __CFPortSet waitSet = rlm->_portSet;

        // ========================================
        // 步骤 2: 清除忽略唤醒标志
        // ========================================
        
        // 清除 "忽略唤醒" 标志
        // 允许 CFRunLoopWakeUp 生效
        // 在处理事件期间会设置这个标志,防止虚假唤醒
        __CFRunLoopUnsetIgnoreWakeUps(rl);

        // ========================================
        // 步骤 3: 通知 Observer - BeforeTimers
        // ========================================
        
        // 检查是否有 Observer 监听 BeforeTimers 活动
        if (rlm->_observerMask & kCFRunLoopBeforeTimers) {
            // 通知所有监听 kCFRunLoopBeforeTimers 的 Observer:即将处理 Timers
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeTimers);
        }
        
        // ========================================
        // 步骤 4: 通知 Observer - BeforeSources
        // ========================================
        
        if (rlm->_observerMask & kCFRunLoopBeforeSources) {
        // 通知所有监听 kCFRunLoopBeforeSources 的 Observer:即将处理 Sources
            __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeSources);
        }
        
        // ========================================
        // 步骤 5: 处理 Blocks
        // ========================================

        // 执行通过 CFRunLoopPerformBlock 添加的 Block
        // 这些 Block 会在当前模式下执行
        // 处理完后会从队列中移除
        __CFRunLoopDoBlocks(rl, rlm);
        
        // ========================================
        // 步骤 6: 处理 Source0(手动触发的源)
        // ========================================
        
        // 处理所有已被 Signal 的 Source0
        // Source0 需要手动调用 CFRunLoopSourceSignal + CFRunLoopWakeUp
        // 返回值:是否处理了至少一个 Source0
        Boolean sourceHandledThisLoop = __CFRunLoopDoSources0(rl, rlm, stopAfterHandle);
        
        // 如果处理了 Source0
        if (sourceHandledThisLoop) {
            // 再次处理 Blocks
            // 因为 Source0 的回调可能添加了新的 Block
            __CFRunLoopDoBlocks(rl, rlm);
        }
        
        // ========================================
        // 步骤 7: 决定是否轮询
        // ========================================

        // 判断是否进行轮询(非阻塞检查)
        // 两种情况需要轮询:
        // 1. sourceHandledThisLoop: 刚处理了 Source0,可能还有事件
        // 2. termTSR == 0: 立即超时模式
        // poll = true: 不休眠,快速检查后继续
        // poll = false: 可以休眠等待
        Boolean poll = sourceHandledThisLoop || (0ULL == termTSR);

// 如果支持 GCD
#if __HAS_DISPATCH__
        // 条件:
        // 1. dispatchPort 有效(主线程 + common mode)
        // 2. 上次不是因为 dispatch 唤醒的
        // 目的:避免 dispatch 端口"饥饿"其他事件源
        if (CFPORT_NULL != dispatchPort && !didDispatchPortLastTime) {
// macOS: 使用 mach_msg 检查
#if TARGET_OS_MAC
            // 指向消息缓冲区
            msg = (mach_msg_header_t *)msg_buffer;
            // 零超时检查 dispatch 端口是否有消息
            // 参数:
            // - dispatchPort: 要检查的端口
            // - &msg: 消息缓冲区指针的地址
            // - sizeof(msg_buffer): 缓冲区大小
            // - &livePort: 输出唤醒的端口
            // - 0: 超时时间为 0(立即返回)
            // - &voucherState: voucher 状态
            // - NULL: voucher 副本(不需要)
            // - rl, rlm: 用于追踪
            if (__CFRunLoopServiceMachPort(dispatchPort, &msg, sizeof(msg_buffer), &livePort, 0, &voucherState, NULL, rl, rlm)) {
                // 如果有消息,跳转到消息处理
                // 跳过后面的休眠,直接处理
                goto handle_msg;
            }
#endif
        }
#endif

        // 重置标志
        // 下一轮循环可以再次检查 dispatch 端口
        didDispatchPortLastTime = false;
        
        // ========================================
        // 步骤 9: 准备休眠
        // ========================================

        // 如果不是轮询模式 && 有 Observer 监听 BeforeWaiting
        // 通知即将休眠
        // 【重要】这是处理自动释放池的关键时机
        if (!poll && (rlm->_observerMask & kCFRunLoopBeforeWaiting)) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopBeforeWaiting);
        
        // 设置休眠标志
        // 标记 RunLoop 即将进入休眠状态
        __CFRunLoopSetSleeping(rl);

        // 【警告】此后到被唤醒前,不应该执行任何用户回调
        // 因为线程即将阻塞
        // do not do any user callouts after this point (after notifying of sleeping)

        // 必须在每次循环迭代时推送本地端口
        // 因为这个模式可能被重入运行,我们不希望这些端口被服务
        // Must push the local-to-this-activation ports in on every loop
        // iteration, as this mode could be run re-entrantly and we don't
        // want these ports to get serviced.
#if __HAS_DISPATCH__
        // 将 dispatch 端口插入到等待集合
        // 让 mach_msg 能够等待它
        // 每次循环都要插入,因为可能重入
        __CFPortSetInsert(dispatchPort, waitSet);
#endif
        // 解锁 Mode
        // 准备休眠前必须解锁,否则其他线程无法操作
	__CFRunLoopModeUnlock(rlm);
        // 解锁 RunLoop
        // 允许其他线程调用 CFRunLoopWakeUp 等函数
	__CFRunLoopUnlock(rl);

        // 记录休眠开始时间
        // 如果是轮询模式,不记录(设为 0)
        // 用于后续统计休眠时长
        CFAbsoluteTime sleepStart = poll ? 0.0 : CFAbsoluteTimeGetCurrent();

        // ========================================
        // 步骤 10: 休眠等待(核心!)
        // ========================================
        // 【这是 RunLoop 的核心:线程在这里阻塞】
        
// macOS 平台:使用 mach_msg() 等待
#if TARGET_OS_MAC
// 如果使用 dispatch source 作为定时器
#if USE_DISPATCH_SOURCE_FOR_TIMERS
        // 内部循环:处理 dispatch 定时器队列
        do {
            // 重置消息指针
            msg = (mach_msg_header_t *)msg_buffer;
            
            // 【核心】调用 mach_msg() 等待端口消息
            // 参数:
            // - waitSet: 等待的端口集合(包含所有监听的端口)
            // - &msg: 消息缓冲区指针的地址
            // - sizeof(msg_buffer): 缓冲区大小
            // - &livePort: 输出被唤醒的端口
            // - poll ? 0 : TIMEOUT_INFINITY: 超时时间
            //   * poll=true: 0(立即返回)
            //   * poll=false: TIMEOUT_INFINITY(永久等待)
            // - &voucherState, &voucherCopy: voucher 追踪
            // - rl, rlm: 用于调试追踪
            // 
            // 【线程在这里阻塞,不消耗 CPU,直到:】
            // - 收到 Mach 消息
            // - 超时
            __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy, rl, rlm);
            
            // 如果唤醒源是模式队列端口(dispatch 定时器)
            if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) {
                // 排空内部队列。如果某个回调 Block 设置了 timerFired 标志,跳出并服务定时器
                // Drain the internal queue. If one of the callout blocks sets the timerFired flag, break out and service the timer.
                // 执行队列中的所有任务
                // 这些任务可能设置 _timerFired 标志
                while (_dispatch_runloop_root_queue_perform_4CF(rlm->_queue));
                // 如果定时器已触发
                if (rlm->_timerFired) {
                    // 保持 livePort 为队列端口,稍后服务定时器
                    // Leave livePort as the queue port, and service timers below
                    // 清除标志
                    rlm->_timerFired = false;
                    // 跳出内部循环,去处理定时器
                    break;
                } else {
                    // 定时器未触发,可能是其他 dispatch 任务
                    // 如果消息使用了动态分配的缓冲区,释放它
                    if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
                }
            } else { // 唤醒源不是队列端口
                // Go ahead and leave the inner loop.
                // 跳出内部循环
                break;
            }
        } while (1); // 无限循环,通过 break 跳出
#else // 不使用 dispatch source,直接使用 mk_timer
        // 重置消息指针
        msg = (mach_msg_header_t *)msg_buffer;
        // 等待 Mach 消息
        // 线程在这里阻塞
        __CFRunLoopServiceMachPort(waitSet, &msg, sizeof(msg_buffer), &livePort, poll ? 0 : TIMEOUT_INFINITY, &voucherState, &voucherCopy, rl, rlm);
#endif

#endif
        
        // ========================================
        // 步骤 11: 被唤醒,重新加锁
        // ========================================
        // 【线程被唤醒,继续执行】
        
        // 重新锁定 RunLoop
        __CFRunLoopLock(rl);
        // 重新锁定 Mode
        __CFRunLoopModeLock(rlm);

        // 更新休眠时间统计
        // 如果是轮询模式,不计入(加 0)
        // 否则计算实际休眠时长
        rl->_sleepTime += (poll ? 0.0 : (CFAbsoluteTimeGetCurrent() - sleepStart));

        // 必须在每次循环迭代时移除本地端口
        // 原因:
        // 1. 模式可能被重入运行,我们不希望这些端口被服务
        // 2. 不希望函数返回时这些端口还留在集合中
        // Must remove the local-to-this-activation ports in on every loop
        // iteration, as this mode could be run re-entrantly and we don't
        // want these ports to get serviced. Also, we don't want them left
        // in there if this function returns.
#if __HAS_DISPATCH__
        // 从等待集合中移除 dispatch 端口
        // 与之前的 Insert 对应
        __CFPortSetRemove(dispatchPort, waitSet);
#endif
        
        // 设置忽略唤醒标志
        // 防止在处理事件期间的额外唤醒
        __CFRunLoopSetIgnoreWakeUps(rl);

        // 现在可以再次执行用户回调了
        // user callouts now OK again
        
        // 清除休眠标志
        // 标记 RunLoop 已醒来
        __CFRunLoopUnsetSleeping(rl);
        
        // 如果不是轮询模式 && 有 Observer 监听 AfterWaiting
        // 通知刚从休眠中醒来
        if (!poll && (rlm->_observerMask & kCFRunLoopAfterWaiting)) __CFRunLoopDoObservers(rl, rlm, kCFRunLoopAfterWaiting);

        // 跳转标签
        // 如果之前检查 dispatch 端口有消息,会跳转到这里
        handle_msg:;
        // 再次设置忽略唤醒标志
        // 确保在处理消息期间不被干扰
        __CFRunLoopSetIgnoreWakeUps(rl);

        // ========================================
        // 步骤 13: 根据唤醒源分发事件
        // ========================================
        
        // 情况 1: 没有唤醒源(不应该发生)
        if (CFPORT_NULL == livePort) {
            // 探针:记录无原因唤醒
            CFRUNLOOP_WAKEUP_FOR_NOTHING();
            // 内核追踪:记录无原因唤醒事件
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_NOTHING, rl, rlm, livePort, 0);
            // 不处理任何事情
            // handle nothing
        } else if (livePort == rl->_wakeUpPort) { // 情况 2: 被 CFRunLoopWakeUp 手动唤醒
            // 探针:记录手动唤醒
            CFRUNLOOP_WAKEUP_FOR_WAKEUP();
            // 内核追踪:记录手动唤醒事件
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_WAKEUP, rl, rlm, livePort, 0);
            // macOS 上不需要特殊处理
            // 只是唤醒,让循环继续执行
            // do nothing on Mac OS
        }
// 如果使用 dispatch source 作为定时器
#if USE_DISPATCH_SOURCE_FOR_TIMERS
        else if (modeQueuePort != MACH_PORT_NULL && livePort == modeQueuePort) { // 情况 3: 被 dispatch source 定时器唤醒
            // 探针:记录定时器唤醒
            CFRUNLOOP_WAKEUP_FOR_TIMER();
            // 内核追踪:记录定时器唤醒事件
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_TIMER, rl, rlm, livePort, 0);
            // 处理所有到期的定时器
            // 参数:rl, rlm, 当前时间戳
            // 返回:是否处理了至少一个定时器
            if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
                // 重新装备下一个定时器,因为显然我们提前触发了
                // (可能是系统唤醒太早)
                // Re-arm the next timer, because we apparently fired early
                // 设置下一个最近的定时器
                __CFArmNextTimerInMode(rlm, rl);
            }
        }
#endif
        else if (rlm->_timerPort != CFPORT_NULL && livePort == rlm->_timerPort) { // 情况 4: 被 mk_timer(内核定时器)唤醒
            // 探针:记录定时器唤醒
            CFRUNLOOP_WAKEUP_FOR_TIMER();
            
            // 在 Windows 上,我们观察到定时器端口在我们请求的时间之前被设置的问题。
            // 例如,我们设置触发时间为 TSR 167646765860,但实际观察到在 TSR 167646764145 触发,提前了 1715 个时钟周期。
            // 结果是,当 __CFRunLoopDoTimers 检查是否有定时器应该触发时,看起来对下一个定时器来说"太早了",没有定时器被处理。
            // On Windows, we have observed an issue where the timer port is set before the time which we requested it to be set. For example, we set the fire time to be TSR 167646765860, but it is actually observed firing at TSR 167646764145, which is 1715 ticks early. The result is that, when __CFRunLoopDoTimers checks to see if any of the run loop timers should be firing, it appears to be 'too early' for the next timer, and no timers are handled.
            // 在这种情况下,定时器端口已被自动重置,如果我们不重新装备它,那么除非有东西调整定时器列表(如添加或移除定时器),否则将永远不会再服务定时器。
            // 解决方法是:如果 CFRunLoopDoTimers 没有处理定时器,就在这里重置定时器。Bug 编号: 9308754
            // In this case, the timer port has been automatically reset (since it was returned from MsgWaitForMultipleObjectsEx), and if we do not re-arm it, then no timers will ever be serviced again unless something adjusts the timer list (e.g. adding or removing timers). The fix for the issue is to reset the timer here if CFRunLoopDoTimers did not handle a timer itself. 9308754
            // 处理定时器
            // 如果没有处理任何定时器(提前唤醒)
            if (!__CFRunLoopDoTimers(rl, rlm, mach_absolute_time())) {
                // 重新装备下一个定时器
                // Re-arm the next timer
                // 因为我们将重置相同的定时器,使用相同的截止时间,
                // 我们需要重置这些值,以便装备下一个定时器的代码
                // 能正确找到列表中的下一个定时器并装备底层定时器
                // Since we'll be resetting the same timer as before
                // with the same deadlines, we need to reset these
                // values so that the arm next timer code can
                // correctly find the next timer in the list and arm
                // the underlying timer.
                // 重置软截止时间为最大值
                rlm->_timerSoftDeadline = UINT64_MAX;
                // 重置硬截止时间为最大值
                rlm->_timerHardDeadline = UINT64_MAX;
                // 重新装备定时器
                __CFArmNextTimerInMode(rlm, rl);
            }
        }
        
        // GCD 主队列处理
        /* --- DISPATCHES  --- */
        
#if __HAS_DISPATCH__
        else if (livePort == dispatchPort) { // 情况 5: 被 GCD 主队列唤醒
            // 探针:记录 dispatch 唤醒
            CFRUNLOOP_WAKEUP_FOR_DISPATCH();
            // 内核追踪:记录 dispatch 唤醒事件
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_DISPATCH, rl, rlm, livePort, 0);
            
            // 执行 GCD 任务时必须解锁,防止死锁
            // 解锁 Mode
            __CFRunLoopModeUnlock(rlm);
            // 解锁 RunLoop
            __CFRunLoopUnlock(rl);
            // 设置线程特定数据:标记当前正在 GCD 主队列中执行
            // 值 6 是一个标记值
            _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)6, NULL);

            // 开始自动释放池(如果需要)
            CFRUNLOOP_ARP_BEGIN(NULL)
            // 追踪:开始调用 dispatch
            cf_trace(KDEBUG_EVENT_CFRL_IS_CALLING_DISPATCH | DBG_FUNC_START, rl, rlm, msg, livePort);
            // 【关键】执行 GCD 主队列上的所有待处理任务
            // 这个宏展开为 _dispatch_main_queue_callback_4CF(msg)
            __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__(msg);
            // 追踪:结束调用 dispatch
            cf_trace(KDEBUG_EVENT_CFRL_IS_CALLING_DISPATCH | DBG_FUNC_END, rl, rlm, msg, livePort);
            // 结束自动释放池
            CFRUNLOOP_ARP_END()

            // 清除线程特定数据:标记已退出 GCD 主队列
            _CFSetTSD(__CFTSDKeyIsInGCDMainQ, (void *)0, NULL);
            // 重新加锁 RunLoop
            __CFRunLoopLock(rl);
            // 重新加锁 Mode
            __CFRunLoopModeLock(rlm);
            // 标记处理了事件
            sourceHandledThisLoop = true;
            // 标记上次是 dispatch 端口唤醒的
            // 下次循环会跳过 dispatch 端口检查,避免饥饿
            didDispatchPortLastTime = true;
        }
#endif
        // Source1 处理(基于端口的源)
        /* --- SOURCE1S  --- */
        
        else { // 情况 6: 被 Source1 唤醒
            // 探针:记录 Source 唤醒
            CFRUNLOOP_WAKEUP_FOR_SOURCE();
            // 内核追踪:记录 Source 唤醒事件
            cf_trace(KDEBUG_EVENT_CFRL_DID_WAKEUP_FOR_SOURCE, rl, rlm, 0, 0);
            // 根据端口查找对应的 Source1
            // 从 Mode 的 _portToV1SourceMap 字典中查找
            CFRunLoopSourceRef rls = __CFRunLoopModeFindSourceForMachPort(rl, rlm, livePort);
            // 如果找到了对应的 Source1
            if (rls) {
// macOS: 传递 Mach 消息给 Source1
#if TARGET_OS_MAC
                // 回复消息指针(如果 Source1 需要回复)
                mach_msg_header_t *reply = NULL;
                // 处理 Source1
                // 参数:rl, rlm, source, 消息, 消息大小, 回复消息指针
                // 返回:是否处理了 Source
                // 使用 || 保留之前的 sourceHandledThisLoop 值
                sourceHandledThisLoop = __CFRunLoopDoSource1(rl, rlm, rls, msg, msg->msgh_size, &reply) || sourceHandledThisLoop;
                // 如果 Source1 产生了回复消息
                if (NULL != reply) {
                    // 发送回复消息
                    // 参数:消息, 选项(仅发送), 发送大小, 接收大小, 接收端口, 超时, 通知端口
                    (void)mach_msg(reply, MACH_SEND_MSG, reply->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
                    // 释放回复消息内存
                    CFAllocatorDeallocate(kCFAllocatorSystemDefault, reply);
                }
#endif
            } else { // 找不到对应的 Source1(异常情况)
                // 记录错误日志
                os_log_error(_CFOSLog(), "__CFRunLoopModeFindSourceForMachPort returned NULL for mode '%@' livePort: %u", rlm->_name, livePort);
            }
            
        }
        
        // 再次处理 Blocks
        /* --- BLOCKS --- */
        
#if TARGET_OS_MAC
        // 如果消息使用了动态分配的缓冲区(超过 3KB)
        // 释放动态分配的内存
        if (msg && msg != (mach_msg_header_t *)msg_buffer) free(msg);
#endif
        
        // 再次执行 Blocks
        // 因为上面的事件处理可能添加了新的 Block
        __CFRunLoopDoBlocks(rl, rlm);
        
        // ========================================
        // 步骤 14: 检查退出条件
        // ========================================
        
        // 条件 1: 处理了事件 && 要求处理后停止
        if (sourceHandledThisLoop && stopAfterHandle) {
            // 返回值:已处理 Source
            // 这个模式用于 CFRunLoopRunInMode 的 returnAfterSourceHandled 参数
            retVal = kCFRunLoopRunHandledSource;
        } else if (termTSR < mach_absolute_time()) { // 条件 2: 当前时间超过了终止时间
            // 返回值:超时
            retVal = kCFRunLoopRunTimedOut;
        } else if (__CFRunLoopIsStopped(rl)) { // 条件 3: RunLoop 被标记为停止, 通过 CFRunLoopStop() 设置
            // 清除停止标志
            __CFRunLoopUnsetStopped(rl);
            // 返回值:已停止
            retVal = kCFRunLoopRunStopped;
        } else if (rlm->_stopped) { // 条件 4: Mode 被标记为停止
            // 清除 Mode 停止标志
            rlm->_stopped = false;
            // 返回值:已停止
            retVal = kCFRunLoopRunStopped;
        } else if (__CFRunLoopModeIsEmpty(rl, rlm, previousMode)) { // 条件 5: Mode 为空(没有 Source/Timer/Observer)
            // 返回值:已完成(Mode 为空)
            retVal = kCFRunLoopRunFinished;
        }
            
    // 如果 retVal 仍为 0,继续循环
    } while (0 == retVal);
    
    // ========================================
    // 步骤 15: 清理并返回
    // ========================================
    
#if __HAS_DISPATCH__
    // 如果创建了超时定时器
    if (timeout_timer) {
        // 取消定时器
        // 会触发 cancel_handler,释放 RunLoop 引用
        dispatch_source_cancel(timeout_timer);
        dispatch_release(timeout_timer);
    }
#endif
    
    // 返回退出原因
    // 可能的值:
    // - kCFRunLoopRunFinished: 模式为空
    // - kCFRunLoopRunStopped: 被停止
    // - kCFRunLoopRunTimedOut: 超时
    // - kCFRunLoopRunHandledSource: 处理了 Source 后退出
    return retVal;
}