I came across this stackoverflow question while researching this exact problem but apparently it has been deleted by the original author which is a shame. Other than that, I have been unlucky in finding any other resources.
I've been trying to use pthread_create
to test out race conditions with x86-64 using YASM 1.3 and GCC 11.1 on Linux 5.15 with the following code for several hours now:
racejoined.asm
%include "constants.asm"
%include "itosd_only.asm"
%include "printline_only.asm"
section .data
NTH equ 2 ; no. threads spawned
MAX equ 1000000000 ; sum loop required
ValBufSz equ 64
Val dq 0
X dq 1
Y dq 1
section .bss
ThrIds dq NTH
ValBuf db ValBufSz
section .text
extern pthread_create
extern pthread_join
global main
main:
push rbp
mov rbp, rsp
push r12
; spawn threads
mov r12, 0
main_spawn_thread_loop:
cmp r12, NTH
je main_spawn_thread_loop_end
; pthread_create(&ThrIds[r12], NULL, thread_func, NULL);
mov rcx, NULL
mov rdx, thread_func
mov rsi, NULL
lea rdi, QWORD [ThrIds+r12*8]
call pthread_create ; <-------------------------------- segfault here
; for part 1, we have to run threads in series
mov rsi, NULL
mov rdi, QWORD [ThrIds+r12*8]
call pthread_join
inc r12
jmp main_spawn_thread_loop
main_spawn_thread_loop_end:
; join threads
mov r12, 0
main_join_loop:
cmp r12, NTH
je main_join_loop_end
mov rsi, NULL
mov rdi, QWORD [ThrIds+r12*8]
call pthread_join
inc r12
jmp main_join_loop
main_join_loop_end:
; itos result and print it
mov cl, NULL
mov rdx, ValBufSz
mov rsi, ValBuf
mov rdi, Val
call itosd
mov rdi, ValBuf
call printline
; exit
mov rdi, EXIT_success
mov rax, SYS_exit
syscall
main_end:
pop r12
mov rsp, rbp
pop rbp
ret
thread_func:
push rbx
mov rax, MAX
mov rbx, NTH
cqo
div rbx
mov rcx, rax
thread_sum_loop:
mov rax, QWORD [Val]
cqo
div QWORD [X]
add rax, QWORD [Y]
mov QWORD [Val], rax
loop thread_sum_loop
thread_func_end:
pop rbx
ret
assembled and linked with script
./gld
#!/bin/sh
FILE=${1:?"Source file required: ./gdl FILE"}
ROOT=$(echo $FILE | sed 's/\.\w*$//g')
yasm -g dwarf2 -f elf64 -l "$ROOT.lst" -o "$ROOT.o" "$FILE"
gcc -g -no-pie -o "$ROOT" -pthread "$ROOT.o"
with ./racejoined
giving me a segfault with this backtrace:
gdb
(gdb) r
Starting program: /.../racejoined
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e3f1ca in __pthread_attr_copy () from /usr/lib/libc.so.6
(gdb) bt
#0 0x00007ffff7e3f1ca in __pthread_attr_copy ()
from /usr/lib/libc.so.6
#1 0x00007ffff7f9acf8 in pthread_getattr_default_np ()
from /usr/lib/libpthread.so.0
#2 0x00007ffff7f8f585 in pthread_create@@GLIBC_2.2.5 ()
from /usr/lib/libpthread.so.0
#3 0x0000000000401269 in main_spawn_thread_loop ()
at racejoined.asm:36
#4 0x0000000000401050 in pthread_join@plt ()
#5 0x0000000000000000 in ?? ()
(gdb)
I have an idea that it has to do with the pthread_attr_t
parameter, but almost every example I see on the internet with pthread_create
sets it to NULL
like I do there and it seems to work.
Also the backtrace is somewhat weird because I don't know why pthread_join
precedes the code in main
.
I would appreciate any advice on this, I've burned my eyes staring at my screen for a bit already. Thank you.