在 Innovus 多线程实现流程中,偶尔会遇到以下连续报错并伴随工具崩溃:

1
2
3
4
5
6
job list is not empty:
**ERROR: (MEMPOOL-112): Memory error: no thread specific data,
    mem_thread_init should be called in mem_thread_create (0:00 line 360 EINVAL #1)
**ERROR: (MEMPOOL-112): Memory error: id number is wrong(_thread_number)
    in mem_thread_create (0:00 line 371 EINVAL #2)
Innovus terminated by internal (SEGV) error/signal

本文对该错误的来源、根因及修复方向进行系统梳理。


1. MEMPOOL-112 是什么

MEMPOOL 是 Cadence 底层内存池(Memory Pool)管理子系统的消息前缀,被 Innovus、Genus、Voltus、Xcelium 等多个工具共用。该子系统负责为每个线程分配和管理线程本地存储(TLS,Thread-Local Storage)中的内存块。

MEMPOOL-112 对应两种具体场景:

消息 含义
no thread specific data, mem_thread_init should be called in mem_thread_create 某线程已被创建,但其 TLS 内存池从未初始化(缺少 mem_thread_init 调用)
id number is wrong(_thread_number) in mem_thread_create 线程编号无效,内存池无法找到对应的 TLS 槽位

两条错误接连出现,意味着线程池内部状态已经不一致,后续任何内存访问都可能触发 SEGV。


2. 根本原因分析

2.1 前置信号:job list is not empty

job list is not empty 是触发崩溃前的关键前置日志。它表明:上一个多线程命令(如 place_opt_designoptDesign 等)的工作线程池尚未全部回收,新的命令又尝试重建线程池,导致线程生命周期管理出现竞争。

2.2 MEMPOOL-112 的触发机制

Innovus 在多 CPU 模式下(由 setMultiCpuUsage 控制)会复用一个工作线程池。正常流程:

1
2
3
4
pthread_create(new_thread)
  └─> mem_thread_init()   ← 初始化该线程的 TLS 内存池
        └─> 线程开始执行任务
              └─> 任务结束,mem_thread_destroy() 释放 TLS

当线程池状态异常时(前一批任务未收尾、线程编号计数器溢出、或工具内部 bug),新创建的线程没有经过 mem_thread_init 就尝试使用内存池,立即报 MEMPOOL-112,随后 SEGV。

2.3 已知 Cadence Bug

在 Cadence ASK 的 INNOVUS21.17 Hotfix(Article 20498262)中,明确列有:

CCMPR02575911place_opt_design run aborts with ERROR MEMPOOL-112 using 64CPUs

该 CCR 已在 INNOVUS 21.1 ISR4 中修复。其触发条件与本文所描述的错误完全吻合:使用 setMultiCpuUsage -localCpu 64 时,place_opt_design 执行期间线程池状态异常,触发 MEMPOOL-112 并随即 SEGV。

此外,同类 SEGV 崩溃还包括:

  • CCMPR02300016optDesign -postRoute -setup -hold 期间 SEGV(INNOVUS21 早期版本)
  • CCMPR02592614 — Crash observed during ccopt_design
  • CCMPR02431543routeDesign SEGV due to poorly defined rc_corner
  • CCMPR02474522 — SEGV on sroute for padPin

3. 排查与修复步骤

步骤 1:确认 Innovus 版本,优先升级

1
innovus -version

若版本低于 INNOVUS 21.1 ISR4,强烈建议升级。CCMPR02575911(place_opt_design 64 CPU MEMPOOL-112 崩溃)已在该版本中修复。升级后验证方式:重跑出错的 place_opt_design 步骤,确认不再出现 job list is not empty 前置日志。

步骤 2:降低并发线程数,隔离问题

1
2
# 从当前值逐步减少,定位是否为多线程竞争引起
setMultiCpuUsage -localCpu 2

若单线程或少线程下问题消失,基本确认为多线程竞争 bug,需要 hotfix。

步骤 3:检查系统进程资源限制

1
2
3
ulimit -u    # 最大用户进程数,建议 >= 4096
ulimit -s    # 栈大小,建议 unlimited
ulimit -a    # 查看所有限制

ulimit -u 过小,操作系统会拒绝创建新线程,导致线程池状态异常。

步骤 4:排查 LD_PRELOAD 冲突

第三方内存分配器(如 tcmallocjemalloc)与 Cadence 内部 MEMPOOL 可能发生冲突:

1
2
3
4
env | grep LD_PRELOAD
# 若有自定义分配器,尝试临时取消
unset LD_PRELOAD
innovus -batch -files run.tcl

步骤 5:避免在任务列表非空时继续执行

job list is not empty 出现后不要强行继续。确认上一个命令是否有异步子任务(如分布式任务、-parallel 选项),等待其完成后再执行下一步。

步骤 6:提交 Cadence SR

若以上措施均无法解决,准备以下信息提交 Cadence 支持请求:

  • 完整的 innovus.log(包含 SEGV 前的 stack trace)
  • 正在运行的 Tcl 命令(出错时执行的是哪条命令)
  • setMultiCpuUsage 的设置
  • Innovus 版本号及操作系统版本
  • 引用 CCR:CCMPR02575911place_opt_design MEMPOOL-112 using 64CPUs)

4. 小结

检查项 说明
Innovus 版本 升级至 21.1 ISR4+,CCMPR02575911 已修复 64CPU 场景崩溃
setMultiCpuUsage 尝试减少 CPU 数,隔离多线程竞争
ulimit -u / -s 确保系统进程数和栈大小足够
LD_PRELOAD 排查第三方内存分配器干扰
前置日志 注意 job list is not empty,等待任务收尾再继续

MEMPOOL-112 本质上是线程生命周期管理缺陷,通常由工具 bug 或资源不足触发,用户侧可操作的空间有限,尽快升级版本或联系 Cadence 是最可靠的解决路径。