我使用 ARMv8 64 位的程序集为共享内存上下文实现了 LIFO。
LIFO 在开头插入一个节点,每个节点结构的第一个属性必须是下一个指针。
这是为 LIFO 实现原子插入和删除的正确程序集吗?
它使用LL/SC在 LDXR 和 STXR 之间进行额外的加载或存储来读取 head->next 或将指针存储到新节点中。
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"
);
}
我对 ARM 组装真的很陌生,所以非常感谢任何帮助。