2015-08-30 2 views
0

Considérons le code suivant.Est-il possible d'interrompre l'évaluation d'une expression?

#‎include‬ <stdio.h> 

void f(int *x, int *y) 
{ 
    (*x)++; 
    (*y)++; 
} 

int main() 
{ 
    int x=5, y=5; 

    f(&x, &y); 

return 0; 
} 

Je sais que la fonction f n'est pas réentrante. Une des choses stupides que je pense est de faire (* x) ++ + (* y) ++ dans une ligne et de jeter la somme. Je me demande si des instructions d'assemblage multiples seront générées pour l'évaluation de cette expression. L'interruption sera-t-elle servie entre l'évaluation de l'expression?

+2

Que voulez-vous dire par "interruption"? Pouvez-vous élaborer s'il vous plaît? Quel est le problème que vous essayez de résoudre? –

+0

Oui, c'est possible. Mais s'il vous plaît, pour l'amour de la programmation des Dieux, s'il vous plaît ne faites pas ce que vous avez suggéré. Il vaut mieux écrire du code clair que du code "intelligent". – kaylum

+0

Merci Alan Au. Je sais que c'est stupide à faire. Quel type d'opération est garanti d'être atomique en C? Je pense que c'est une question distincte mais toujours pour maintenir le contexte que je demande ici. – user902384

Répondre

1

Vous ne tirerez rien atomique avec ça ...

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 

Et il y a beaucoup mieux avec -O2, mais ce n'est pas atomique.

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 

Et, au moins pour GCC, la exacte même code est généré pour (*x)++ + (*y++). Quoi qu'il en soit, pourriez-vous élaborer un peu sur votre question? Vous êtes trop large et ce code est réentrant tant que x et y ne sont pas les mêmes sur différentes entrées. Sinon, vous devriez nous donner plus de détails sur vos intentions.

Édition: C'est (apparemment, à moins qu'il y ait de la magie noire cachée ...) impossible de faire une telle chose atomiquement sur une architecture x86 (-64). De toute façon, il est non-portable de considérer une opération "atomique" si elle est faite en une seule instruction. C'est spécifique aux processeurs x86 (-64).

+0

Non, la fonction f dans sa forme originale n'est pas réentrante. Si interruption est servi après l'incrément de x alors y ne sera pas augmenté. Un autre appel à f de principal est perturbé. – user902384

+0

@ user902384: Il * est * réentrant tant qu'il n'est pas appelé avec le (s) même (s) argument (s) par un autre thread. Et quel est le problème avec «y» ne pas être incrémenté immédiatement? Après que l'OS reprendra la tâche, ce sera; aucune "perturbation" ne se produit. – 3442

+0

@ user902384: p.d: Lisez [this] (https://en.wikipedia.org/wiki/Reentrancy_ (computing)), juste pour être sûr que nous avons la même définition de "reentrancy". – 3442