我想使用" TSL"汇编中的指令,但它没有参考理解。在一些文章中,该指令是针对互斥问题引入的,但它没有完全理解的参考或完整的例子。
答案 0 :(得分:7)
TSL(测试和设置锁定)是一般在处理互斥问题时经常出现的操作,但这并不意味着这样的指令实际上存在于任何架构中正在使用;或者,即使它确实存在,它也称为TSL。
例如,在x86上,您可以使用XCHG
指令执行TSL。
答案 1 :(得分:2)
XCNG不是有条件的,它只是用内存位置交换寄存器。你想要的是具有LOCK前缀的CMPXCHG。后者将使其在多核机器上成为原子。
此外,您可以使用LOCK XADD实现原子比较和设置,但这将需要一个循环。
答案 2 :(得分:1)
我认为@Jester和@Seva Alekseyev已经在回答这个问题方面做得很好但是这里是一个简单的C语言实现,通过在x86 Ubuntu机器上使用pthreads进行内联汇编。
在以下示例中,有两个长时间运行的线程。两个线程分别具有关键和非关键部分,critical_region()和noncritical_region。他们都必须调用 enter_region()才能获得锁定。一旦线程获得锁定,它就可以开始运行其关键部分。另一个线程被阻塞,直到带锁的线程将调用 leave_region()。
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
void enter_region() {
asm(
".data\n\t"
"lock:\n\t"
".byte 0\n\t"
".text\n\t"
"_enter_region:\n\t"
"movb $1, %al\n\t" /* move 1 to AL */
"xchgb (lock),%al\n\t"
"cmp $0, %al\n\t"
"jne _enter_region\n\t"
);
}
void leave_region() {
asm("movb $0, (lock)");
}
void critical_region() {
}
void noncritical_region() {
}
static void* f1(void* p) {
while(1) {
puts("wait for f2");
enter_region();
printf("f1 can start its critical section\n");
critical_region();
leave_region();
noncritical_region();
}
return NULL;
}
static void* f2(void* p) {
while(1) {
puts("wait for f1");
enter_region();
printf("f2 can start its critical section\n");
critical_region();
leave_region();
/* if you call sleep, you can see that the non-critical section of this thread won't
* block the other thread from running its critical section as many times as it wants
*/
// sleep(1);
noncritical_region();
}
return NULL;
}
int main() {
int rc;
pthread_t t1, t2;
rc = pthread_create(&t1, NULL, f1, NULL);
if(rc != 0) {
fprintf(stderr, "pthread f1 failed\n");
return EXIT_FAILURE;
}
rc = pthread_create(&t2, NULL, f2, NULL);
if(rc != 0) {
fprintf(stderr, "pthread f2 failed\n");
return EXIT_FAILURE;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
puts("All threads finished.");
return 0;
}