I had implemented a LIFO for shared memory context using assembly for ARMv8 64bit.
The LIFO inserts a node in beginning and each node structure's first attribute must be next pointer.
Is this correct assembly for implementing atomic insert and delete for the LIFO?
It uses LL/SC with an extra load or store between the LDXR and STXR to read the head->next or store a pointer into a new node.
typedef union {
void * head[1];
}lifo;
int atomic_lifo_init(lifo * h) {
if (h) {
h->head[0]=NULL;
}
}
inline void *
atomic_lifo_delete (lifo *h)
{
void *ret = NULL;
/*sa_ignore UNUSED_VAR*/
void * tmp = NULL;
asm volatile ("\n"
"2: ldxr %0,[%2] \n" //load the head from h, which points the 1st node of list to local ret pointer.
" cbz %0, 3f \n" //check if the lifo is empty.
" ldr %1,[%0] \n" //store in tmp the 2nd node by derefencing the ret (h->head points 1st node. value of each node is next node as 1st attribute of node structure is pointing next.)
" stxr %w1, %1,[%2] \n" //update h->head with tmp.
" cbnz %w1, 2b \n" //continue if failed
"3: \n"
: "=&r" (ret), "=&r" (tmp)
: "r" (h)
: "memory"
);
return(ret);
}
/*
* atomic_lifo_insert()
* Put an element on a list, protected against SMP
*/
void
atomic_lifo_insert (lifo *h, void *__new)
{
/*sa_ignore UNUSED_VAR*/
void * next = NULL;
void * flag = NULL;
asm volatile (" \n"
"1: ldxr %1,[%2] \n" //load head[0] from h,which points 1st node to local next pointer
" str %1,[%3] \n" //store the local next pointer to value of __new, as 1st attribute of the any node is next (convention used here). so __new's next is pointing current 1st node.
" stxr %w0, %3,[%2] \n" //update the h->head with
__next.
" cbnz %w0, 1b \n" //if stxr is failure try again.
: "=&r" (flag), "=&r" (next)
: "r" (h), "r" (__new)
: "memory"
);
}
I am really new to ARM assembly, so any help is really appreciated.