/ / Spin Lock използвайки xchg - c, x86, заключване

Spin Lock използвайки xchg - c, x86, заключване

Опитвам се да внедря най-простият шпиц(използвайки TAS) в C, използвайки inline монтаж с командата xchg. Тъй като съобщенията ми за грешки в компилатора стават все по-екзотични и започвам да растем сиви коси, реших да попитам тук. Също така съжалявам, ако този въпрос вече беше отговорен, тъй като не съм намерил нищо.

Какво може да се каже за моето програмиранеопит по тази тема. Аз съм доста добър с C (по мое мнение, като се има предвид стандартните проблеми). Също така вярвам, че знам основите за x86, но аз съм напълно изгубен, когато става въпрос за ограничения в inline асемблер. Това, което разбрах, че правя някакво разправяне, ми е още по-объркващо, тъй като много източници казват много различни неща.

Моят код досега:

int acquire_lock(int* lock){
int val = 1;
int lock_cont;
while((lock_cont = *lock) != 0){
__asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));
}
return 0;
}

Това не работи по причини, които вероятно саочевидно, но ме карат да се справям. Също така опитах някои други варианти, но никой от тях дори не е съставил. Вероятно вече може да кажете, че не знам какво правя, затова ще бъда повече от щастлив за всякакъв вид съвети.

Тук моите компилатор съобщения в случай, че това помага:

my_lock.c:17:11: error: unexpected token in argument list
__asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));
^
<inline asm>:1:12: note: instantiated into assembly here
xchg %eax -16(%rbp)
^
1 error generated.

Благодаря предварително

Отчаян ученик

РЕДАКТИРАНЕ:

Имам ключалката да работи. докато вървим, а запетая направихме трика. Сега имам нов проблем, че прилагането ми заключване все още не изглежда да гарантира изключителен достъп .. Ще публикува целия код и ще бъде щастлив за всички предложения / критици.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

//shared variable
int x;

//new lock instance that"s consistent over function calls
int* new_lock(){
int* ptr = (int*)(malloc(sizeof(int)));
*ptr = 0;
return ptr;
}

//set content of lock atomically to 1
int acquire_lock(int* lock){
int val = 1;
do{
__asm__("xchg %0, %1" : "+q" (val), "+m" (*lock));
}while(val - (*lock) == 0);
return 0;
}

//release the lock
int release_lock(int* lock){
*lock = 0;
return 0;
}

//free lock
int delete_lock(int* ptr){
free(ptr);
return 0;
}

//thread counts to 10^6
void* thread_do(void* arg){
int* lock = (int*) arg;
for(int i = 0; i < 100000; i++){
acquire_lock(lock);
x++;
release_lock(lock);
}
return NULL;
}

int main(int argc, char** argv){
pthread_t thread0, thread1;
int* lock = new_lock();
pthread_create(&thread0, NULL, thread_do, lock);
pthread_create(&thread1, NULL, thread_do, lock);
pthread_join(thread0, NULL);
pthread_join(thread1, NULL);
printf("%dn",x);
return 0;
}

EDIT2:

Заключването ми действително работи, както може да се види когазаключване на цялата линия в рамките на функцията thread_do. Не съвсем доволен от този резултат, тъй като това заключва х за доста дълго време, но предполагам, че аз ще трябва да живея с това .. Предполагам, че проблемът е, че между моята ас инструкция и сравнението от време на време не мога да гарантирам атомност когато заключването и отключването е толкова бърз поток от инструкции (за цикъл в thread_do), тъй като не виждам решение в C (предложенията са добре дошли), ще се придържам към тези реализации, тъй като общата идея изглежда е правилна.

Отговори:

2 за отговор № 1

Ако се опитвате да направите въртележка, вероятно ще искате да използвате силна атомна смяна.

Ето едно просто приложение от вас acquire_lock използвайки GCC вграден:

int acquire_lock(int* lock)
{
while (__sync_val_compare_and_swap (lock, 0, 1) != 0)
{
// Do something while waiting for the lock ?
}
return 0;
}

Вградените компилатори имат предимството да бъдат по-четливи и малко по-преносими от вградените ASM.


/>

По отношение на грешката в кода ви липсва запетая между операндите. Този ред:

__asm__("xchg %0 %1" : "+q" (val), "+m" (lock_cont));

Би трябвало :

__asm__("xchg %0, %1" : "+q" (val), "+m" (lock_cont));