I am new to the low level stuff so I am completely oblivious of what kind of problems you might face down there and I am not even sure if I understand the term "atomic" right. Right now I am trying to make simple atomic locks around memory manipulation via extended assembly. Why? For sake of curiosity. I know I am reinventing the wheel here and possibly oversimplifying the whole process.
The question?Does the code I present here achive the goal of making memory manipulation both threadsafe and reentrant?
- If it works, why?
- If it doesn't work, why?
- Not good enough? Should I for example make use of the register keyword in C?
What I simply want to do...
- Before memory manipulation, lock.
- After memory manipulation, unlock.
The code:
volatile int atomic_gate_memory = 0;static inline void atomic_open(volatile int *gate){ asm volatile ("wait:\n""cmp %[lock], %[gate]\n""je wait\n""mov %[lock], %[gate]\n" : [gate] "=m" (*gate) : [lock] "r" (1) );}static inline void atomic_close(volatile int *gate){ asm volatile ("mov %[lock], %[gate]\n" : [gate] "=m" (*gate) : [lock] "r" (0) );}
Then something like:
void *_malloc(size_t size){ atomic_open(&atomic_gate_memory); void *mem = malloc(size); atomic_close(&atomic_gate_memory); return mem;}#define malloc(size) _malloc(size)
.. same for calloc, realloc, free and fork(for linux).
#ifdef _UNISTD_Hint _fork(){ pid_t pid; atomic_open(&atomic_gate_memory); pid = fork(); atomic_close(&atomic_gate_memory); return pid;}#define fork() _fork()#endif
After loading the stackframe for atomic_open, objdump generates:
00000000004009a7 <wait>:4009a7: 39 10 cmp %edx,(%rax)4009a9: 74 fc je 4009a7 <wait>4009ab: 89 10 mov %edx,(%rax)
Also, given the disassembly above; can I assume I am making an atomic operation because it is only one instruction?