workq_thread_reset_pri vs bsdthread_set_self 调用链路对比

概述

本文档对比分析 XNU 内核中两个核心线程优先级调整函数的完整调用链路:

  • workq_thread_reset_pri - 工作队列优先级重置(由内核调度器调用)
  • bsdthread_set_self - BSD 线程自我设置(由 bsdthread_set_self 系统调用触发)

分析范围:仅针对 workqueue 线程(GCD 工作线程)

相关文件:


1. workq_thread_reset_pri 完整调用链路

workq_thread_reset_pri(wq, uth, req, unpark)
    │
    ├─► uth->uu_workq_pri = WORKQ_POLICY_INIT(qos)              [pthread_workqueue.c:710]
    │       └─► 设置 uth->uu_workq_pri.qos_req, qos_relprio
    │
    ├─► uth->uu_workq_flags &= ~UT_WORKQ_OUTSIDE_QOS           [pthread_workqueue.c:711]
    │
    └─► thread_set_preadopt_thread_group(th, tg)               [pthread_workqueue.c:819]
            │
            ├─► splsched()                                      关闭中断
            │
            ├─► thread_lock(thread)                             获取 thread lock
            │
            ├─► thread_compute_resolved_thread_group(...)        计算 resolved thread_group
            │
            ├─► thread_group_retain(tg)                         增加引用计数
            │
            ├─► thread_group_deallocate_safe(old_tg)            释放旧 thread_group
            │
            ├─► thread->preadopt_thread_group = tg              [thread_group.c:928-935]
            │       └─► 设置preadopt_thread_group
            │
            ├─► thread->thread_group = resolved_tg              [thread_group.c:948+]
            │       └─► **修改 thread->thread_group**
            │
            ├─► thread_unlock(thread)
            └─► splx(s)

继续:thread_set_workq_pri 分支

workq_thread_reset_pri
    └─► thread_set_workq_pri(th, qos, priority, policy)        [pthread_workqueue.c:822]
            │
            ├─► splsched()
            ├─► thread_lock(thread)
            │
            ├─► proc_set_thread_policy_spinlocked(..., TASK_POLICY_QOS_AND_RELPRIO, ...)
            │       │
            │       ├─► thread_set_requested_policy_spinlocked(...)  [thread_policy.c:2054]
            │       │       │
            │       │       └─► thread->requested_policy.thrp_qos = value     [thread_policy.c:2130]
            │       │       └─► thread->requested_policy.thrp_qos_relprio = v2 [thread_policy.c:2131]
            │       │       └─► thread->requested_policy = requested         [thread_policy.c:2200]
            │       │
            │       └─► thread_policy_update_spinlocked(...)       [thread_policy.c:1597]
            │               │
            │               └─► thread_policy_update_internal_spinlocked(...) [thread_policy.c:1623]
            │                       │
            │                       ├─► thread_update_qos_cpu_time_locked()
            │                       │       └─► thread->vtimer_qos_save = ...
            │                       │
            │                       ├─► thread->effective_policy = next       [thread_policy.c:1844]
            │                       │       └─► **修改 effective_policy**
            │                       │
            │                       ├─► thread_recompute_priority(thread)    [thread_policy.c:1054]
            │                       │       │
            │                       │       └─► sched_set_thread_base_priority(thread, priority) [priority.c:285]
            │                       │               │
            │                       │               ├─► thread->req_base_pri = priority      [priority.c:297]
            │                       │               ├─► thread->base_pri = priority          [priority.c:301]
            │                       │               │       └─► **修改 thread->base_pri**
            │                       │               │
            │                       │               └─► thread_recompute_sched_pri(...)      [priority.c:383]
            │                       │                       │
            │                       │                       └─► set_sched_pri(thread, new_priority) [sched_prim.c:5898]
            │                       │                               │
            │                       │                               ├─► thread_run_queue_remove(thread) [sched_prim.c:5930]
            │                       │                               │       └─► **可能触发 runqueue 迁移**
            │                       │                               │
            │                       │                               ├─► thread->sched_pri = new_priority   [sched_prim.c:5933]
            │                       │                               │       └─► **修改 thread->sched_pri**
            │                       │                               │
            │                       │                               └─► thread_run_queue_reinsert(...)     [sched_prim.c:5956]
            │                       │
            │                       └─► [turnstile 更新: pend_token->tpt_update_turnstile]
            │
            ├─► proc_set_thread_policy_spinlocked(..., TASK_POLICY_QOS_WORKQ_OVERRIDE, ...)
            │       └─► 清除 workq override
            │
            ├─► thread_unlock(thread)
            └─► splx(s)

2. bsdthread_set_self 完整调用链路

bsdthread_set_self(p, th, priority, voucher, flags)
    │
    └─► workq_lock_spin(wq)                                   [pthread_workqueue.c:2472]
            └─► os_unfair_lock_lock_with_options(&wq->wq_lock, 0)

继续:workq_thread_update_bucket 分支

bsdthread_set_self
    └─► workq_thread_update_bucket(p, wq, uth, old_pri, new_pri, force_run)
            │
            ├─► wq->wq_thactive_bucket_priority[...] += delta    [pthread_workqueue.c]
            │       └─► **修改 wq->wq_thactive_bucket_priority[]**
            │
            ├─► wq->wq_constrained_threads_scheduled++/--        [pthread_workqueue.c:2498,2503]
            │       └─► **修改 wq_constrained_threads_scheduled**
            │
            └─► _wq_cooperative_queue_scheduled_count_dec/inc()  [pthread_workqueue.c:2507,2508]
                    └─► **修改 cooperative 计数**

bsdthread_set_self
    └─► workq_unlock(wq)                                      [pthread_workqueue.c:2520]
            └─► os_unfair_lock_unlock(&wq->wq_lock)

继续:thread_policy_set_internal 分支

bsdthread_set_self
    └─► thread_policy_set_internal(th, THREAD_QOS_POLICY, ...)  [pthread_workqueue.c:2535]
            │
            ├─► thread_mtx_lock(thread)                        [thread_policy.c:350]
            │
            ├─► [THREAD_QOS_POLICY case]                       [thread_policy.c:591-618]
            │       │
            │       └─► proc_set_thread_policy_locked(...)
            │               │
            │               └─► proc_set_thread_policy_spinlocked(...)
            │                       │
            │                       ├─► thread_set_requested_policy_spinlocked(...)
            │                       │       └─► thread->requested_policy.thrp_qos = value
            │                       │       └─► thread->requested_policy.thrp_qos_relprio = value2
            │                       │
            │                       └─► thread_policy_update_internal_spinlocked(...)
            │                               │
            │                               ├─► thread->effective_policy = next
            │                               ├─► thread_recompute_priority(...)
            │                               │       └─► sched_set_thread_base_priority(...)
            │                               │               └─► thread_recompute_sched_pri(...)
            │                               │                       └─► set_sched_pri(...)
            │                               │                               ├─► thread_run_queue_remove (可能)
            │                               │                               ├─► thread->sched_pri = ...
            │                               │                               └─► thread_run_queue_reinsert (可能)
            │                               │
            │                               └─► [turnstile 更新]
            │
            └─► thread_mtx_unlock(thread)

3. 修改变量完整对比

3.1 uthread 结构体

变量 workq_thread_reset_pri bsdthread_set_self
uu_workq_pri ✅ 完整替换 [710] ✅ qos_req/qos_override [2475,2488]
uu_workq_flags ✅ 清除 UT_WORKQ_OUTSIDE_QOS [711] ❌
uu_kqr_bound ❌ ✅ 可能解绑 [2379]
uu_save.park_data ✅ [714-716] ❌

3.2 thread 结构体

变量 workq_thread_reset_pri bsdthread_set_self
preadopt_thread_group ✅ 设置/清除 [928-935] ❌
thread_group ✅ 设置 resolved_tg [948+] ❌
requested_policy.thrp_qos ✅ [2130] ✅ [615]
requested_policy.thrp_qos_relprio ✅ [2131] ✅ [616]
effective_policy ✅ [1844] ✅ [1844]
base_pri ✅ [301] ✅ [301]
sched_pri ✅ [5933] ✅ [5933]
voucher ❌ ✅ [2544]

3.3 workqueue 结构体

变量 workq_thread_reset_pri bsdthread_set_self
wq_constrained_threads_scheduled ❌ ✅ [2498,2503]
wq_thactive_bucket_priority[] ✅ (间接) ✅
wq_cooperative_queue_scheduled_count ❌ ✅ [2507,2508]

4. 关键差异总结

操作 workq_thread_reset_pri bsdthread_set_self
thread_group/preadopt_thread_group ✅ ❌
os_unfair_lock (wq) ❌ ✅
thread_run_queue_remove ✅ (可能) ❌
workq_thread_update_bucket ✅ (间接) ✅ (直接)
voucher 设置 ❌ ✅

性能影响

  • workq_thread_reset_pri:更重量级,涉及 thread_group 操作和可能的 runqueue 迁移
  • bsdthread_set_self:更轻量,仅修改 QoS 策略和 wq 计数

5. 适用场景

函数 调用场景 用途
workq_thread_reset_pri 内核工作队列调度 工作线程取新任务时调整优先级
bsdthread_set_self 用户态 API 调用 GCD _pthread_set_properties_self() 设置 QoS

6. 参考调用命令

# 反汇编 workq_thread_reset_pri
lldb -b -o "target create --arch arm64e \"$KDK\"" -o "dis -n workq_thread_reset_pri -c 200"

# 反汇编 thread_set_preadopt_thread_group
lldb -b -o "target create --arch arm64e \"$KDK\"" -o "dis -n thread_set_preadopt_thread_group -c 200"

# 反汇编 thread_set_workq_pri
lldb -b -o "target create --arch arm64e \"$KDK\"" -o "dis -n thread_set_workq_pri -c 100"

# 反汇编 bsdthread_set_self
lldb -b -o "target create --arch arm64e \"$KDK\"" -o "dis -n bsdthread_set_self -c 300"

# 反汇编 set_sched_pri
lldb -b -o "target create --arch arm64e \"$KDK\"" -o "dis -n set_sched_pri -c 80"
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容