【发布时间】:2020-01-06 19:50:23
【问题描述】:
我正在使用 gdb 调试由 C 程序使用 dlopen() 和 dlsym() 加载的共享对象。共享对象是用 NASM 编写的,它是用 DWARF 调试符号编译的。我在 Ubuntu 18.04 上运行。
我希望每个线程在创建后完全停止,以便在继续之前创建所有四个线程。所以我用“set scheduler-locking on”或“set scheduler-locking step”开始调试会话。
据我了解 gdb 命令“set scheduler-locking on”,它应该允许我创建一个线程,然后切换回线程 1(主线程)并创建另一个线程,依此类推,直到所有线程都已创建的。
在 NASM 代码中,我在标签 Test_fn: 处设置了一个断点:(参见下面的代码)。当线程到达该断点时,它会停止(这是线程创建后的第一个断点)。然后我切换回线程 1(主线程)并“继续”实例化下一个线程(主线程仍在 Init_Cores 的 label_0 部分)。线程 1 将执行代码(如果我单步执行它),但在创建下一个线程之前的某个时刻,它会死锁,并且总是死锁。
我也尝试过单步创建线程(避免“继续”),但它仍然死锁。
根据Employed Russian 在How to continue one thread at a time when debugging a multithreaded program in GDB? 的回答,这可能会发生,但他并没有说它会一直发生。无论我使用“设置调度程序锁定”还是“设置调度程序锁定步骤”,我都会遇到死锁。
也许这是因为它是一个共享对象,但其他一切都适用于共享对象,所以我认为这不是问题所在。
这是 NASM 代码。同样的问题也适用于 C 或 C++ 代码,特别是为什么当我在新线程上到达断点时 gdb 死锁,然后切换回线程 1 以继续创建线程。线程 2(第一个创建的线程)应该在调度程序锁定打开时停止。
; Header Section
[BITS 64]
[default rel]
global Main_Entry_fn
extern pthread_create, pthread_join, pthread_exit, pthread_self, sched_getcpu
global FreeMem_fn
extern malloc, realloc, free
extern sprintf
section .data align=16
X_ctr: dq 0
data_master_ptr: dq 0
initial_dynamic_length: dq 0
XMM_Stack: dq 0, 0, 0, 0, 0, 0, 0
ThreadID: dq 0
X_ptr: dq 0
X_length: dq 0
X: dq 0
collect_ptr: dq 0
collect_length: dq 0
collect_ctr: dq 0
even_squares_list_ptrs: dq 0, 0, 0, 0
even_squares_list_ctr: dq 0
even_squares_list_length: dq 0
Number_Of_Cores: dq 4
pthread_attr_t: dq 0
pthread_arg: dq 0
Join_Ret_Val: dq 0
tcounter: dq 0
sched_getcpu_array: times 4 dq 0
ThreadIDLocked: dq 0
spin_lock_core: times 4 dq 0
extra_test_array: times 4 dq 0
spin_lock_iter: times 4 dq 0
spin_lock_base_addr: dq 0
; __________
section .text
Init_Cores_fn:
%include "/opt/P01_SH/_Include_Utilities/Buffer_Pointer_Arrays.asm"
mov rax,[Number_Of_Cores]
mov rbx,8
mul rbx
mov [Number_Of_Cores],rax
; _____
; Create Threads
label_0:
; THREAD 1 WORKS IN THIS SECTION TO CREATE THREADS
mov rdi,ThreadID ; ThreadCount
mov rsi,pthread_attr_t ; Thread Attributes
mov rdx,Test_fn ; Function Pointer
mov rcx,pthread_arg
call pthread_create wrt ..plt
mov rdi,[ThreadID] ; id to wait on
mov rsi,Join_Ret_Val ; return value
call pthread_join wrt ..plt
mov rax,[tcounter]
add rax,8
mov [tcounter],rax
mov rbx,[Number_Of_Cores]
cmp rax,rbx
jl label_0
; _____
jmp label_900 ; All threads return here, and exit
; ______________________________________
Test_fn:
; Get the core number
call sched_getcpu wrt ..plt
mov rbx,8 ; multiply by 8
mul rbx
push rax
pop rax
mov rbx,rax
push rax
Next_Stop: ; THIS IS WHERE EACH THREAD STOPS
mov rdi,extra_test_array
mov [rdi+rbx],rbx
jmp label_899 ; ******************
;__________
label_899:
pop rax
ret
; __________
label_900:
%include "/opt/P01_SH/_Include_Utilities/Sys_Close_Include.asm"
mov rdi,extra_test_array
mov rax,rdi
ret
;__________
;Free the memory
FreeMem_fn:
;The pointer is passed back in rcx (of course)
sub rsp,40
call free wrt ..plt
add rsp,40
ret
; __________
; Main Entry
Main_Entry_fn:
push rdi
push rbp
push rbx
push r15
xor r15,r15
push r14
xor r14,r14
push r13
xor r13,r13
push r12
xor r12,r12
push r11
xor r11,r11
push r10
xor r10,r10
push r9
xor r9,r9
push r8
xor r8,r8
movsd [XMM_Stack+0],xmm13
movsd [XMM_Stack+8],xmm12
movsd [XMM_Stack+16],xmm11
movsd [XMM_Stack+24],xmm15
movsd [XMM_Stack+32],xmm14
movsd [XMM_Stack+40],xmm10
mov [X_ptr],rdi
mov [data_master_ptr],rsi
; Now assign lengths
lea rdi,[data_master_ptr]
mov rbp,[rdi]
xor rcx,rcx
movsd xmm0,qword[rbp+rcx]
cvttsd2si rax,xmm0
mov [X_length],rax
add rcx,8
; __________
; Write variables to assigned registers
mov r15,0
lea rdi,[rel collect_ptr]
mov r14,qword[rdi]
mov r13,[collect_ctr]
mov r12,[collect_length]
lea rdi,[rel X_ptr]
mov r11,qword[rdi]
mov r10,[X_length]
; __________
call Init_Cores_fn
movsd xmm10,[XMM_Stack+0]
movsd xmm14,[XMM_Stack+8]
movsd xmm15,[XMM_Stack+16]
movsd xmm11,[XMM_Stack+24]
movsd xmm12,[XMM_Stack+32]
movsd xmm13,[XMM_Stack+40]
pop r8
pop r9
pop r10
pop r11
pop r12
pop r13
pop r14
pop r15
pop rbx
pop rbp
pop rdi
ret
;__________
NASM 代码很长,但重点是 label_0(创建线程的地方)和 Test_fn(新线程到达的第一个断点。
我非常感谢任何有关 gdb 调度程序锁定问题的意见。谢谢。
【问题讨论】:
标签: linux multithreading gdb