Search code examples
cinterruptreentrancy

Is it possible to interrupt evaluation of an expression


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?


Solution

  • 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.