2

Are there anything wrong with below inline assembly code? I encountered "Illegal instruction (core dumped)" when running the function spinlock_lock.

void spinlock_lock(struct spinlock * lock) {

    int a;
    __asm__ __volatile__("movl %0, %%eax;"
                         "test %%eax, %%eax;"
                         "jnz spinlock_lock;"
                         :"=r"(a)
                         :"r"(lock->cmos_lock)
                         :"eax");

    __asm__ __volatile__ ("lock; cmpxchg %%edx, %0\n"
                          :"=r"(a)
                          :"r"(lock->cmos_lock)
                          :"edx", "memory");
Jordan Richards
  • 532
  • 3
  • 18
dykw
  • 1,199
  • 3
  • 13
  • 17

1 Answers1

2

The problem is your branch; normally (x86) the called function will save the frame pointer on the stack before executing any other code.

Your jnz spinlock_lock branch will branch back to the entry point of the entire function and thus save the frame pointer again before getting back to your inline assembler. Save the frame pointer enough times, you'll run out of stack. Not to mention that if you leave your inline assembler by branching outside it, your registers may no longer contain what you think they do.

You should probably put a label inside your inline assembler and branch back to that instead.

Also, the instruction cmpxchg %edx, %0 can operate against a register, but cannot be combined with lock since you're using a register operand. To make lock cmpxchg work, you need to change the matching parameter constraint from r to m.

You may want to take a look here for a discussion of lock cmpxchg requiring a memory operand or here for an alternate gcc implementation of spinlock without the assembler.

Community
  • 1
  • 1
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • you are talking about his?__asm__ __volatile__("L: " "movl %0, %%eax;" "test %%eax, %%eax;" // "jnz spinlock_lock;" "jnz L;" ://"=r"(a) :"r"(lock->cmos_lock) :"eax"); – dykw Sep 17 '12 at 01:42
  • @dykw Yes, your jnz will branch back to the function entry point, you should keep the branching within your inline assembler code. – Joachim Isaksson Sep 17 '12 at 13:16
  • it doesn't work. I try to comment "__asm__ __volatile__ ("lock; cmpxchg %%edx, %0\n"". The illegal instruction disappear. Why? – dykw Sep 22 '12 at 21:51
  • @dykw Added some details on that to the answer. – Joachim Isaksson Sep 23 '12 at 06:18