Consider the following piece of code.
#include <stdio.h>
void f(int *x, int *y)
{
(*x)++;
(*y)++;
}
int main()
{
int x=5, y=5;
f(&x, &y);
return 0;
}
I know that the function f is not reentrant. One of the stupid things I am thinking is to do (*x)++ + (*y)++ in one line and discard the sum. I wonder that multiple assembly instructions will be generated for evaluation of this expression. Will the interrupt be served in between evaluation of expression?
You won't get anything atomic with that...
c.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 89 7d f8 mov %rdi,-0x8(%rbp)
8: 48 89 75 f0 mov %rsi,-0x10(%rbp)
c: 48 8b 45 f8 mov -0x8(%rbp),%rax
10: 8b 00 mov (%rax),%eax
12: 8d 50 01 lea 0x1(%rax),%edx
15: 48 8b 45 f8 mov -0x8(%rbp),%rax
19: 89 10 mov %edx,(%rax)
1b: 48 8b 45 f0 mov -0x10(%rbp),%rax
1f: 8b 00 mov (%rax),%eax
21: 8d 50 01 lea 0x1(%rax),%edx
24: 48 8b 45 f0 mov -0x10(%rbp),%rax
28: 89 10 mov %edx,(%rax)
2a: 5d pop %rbp
2b: c3 retq
And it gets a lot better with -O2
, but still it's not atomic.
c.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <f>:
0: 83 07 01 addl $0x1,(%rdi)
3: 83 06 01 addl $0x1,(%rsi)
6: c3 retq
And, at least for GCC, the exact same code is generated for (*x)++ + (*y++)
. Anyway, may you elaborate a little bit on your question? You're being too broad and this code is reentrant as long as x
and y
are not the same on different entries. Otherwise, you should give us more details about you're intending.
Edit: It's (apparently, unless there's some hidden black magic...) impossible to do such a thing atomically on a x86(-64) architecture. Anyway, it's non-portable to consider an operation "atomic" if it is done in a single instruction. That's specific to x86(-64) CPUs.