I want to use "TSL" instruction in assembly , but it has no reference for understand .in some articles this instruction is introduced for mutual exclusion problem but it has no reference or complete example to understand completely.
Test and Set Lock This instructions reads the contents of a memory location, stores it in a register and then stores a non-zero value at the address. This operation is guaranteed to be indivisible. That is, no other process can access that memory location until the TSL instruction has finished.
In TSL mechanism, a process will execute the TSL instruction only when it wants to get into the critical section. The value of the lock will always be 0 if no process doesn't want to enter into the critical section hence the progress is always guaranteed in TSL.
Perhaps the most obvious way of achieving mutual exclusion is to allow a process to disable interrupts before it enters its critical section and then enable interrupts after it leaves its critical section. By disabling interrupts the CPU will be unable to switch processes.
In Process Synchronization, Test and Set Lock (TSL) is a synchronization mechanism that uses a test-and-set instruction to provide the synchronization among the processes. It ensures mutual exclusion and freedom from deadlock.
TSL (Test and Set Lock) is an operation that frequently comes up when dealing with mutual exclusion problems in general, but that doesn't mean such an instruction actually exists on whatever architecture you are using; or, even if it does exist, that it's called TSL.
On x86, for example, you can use the XCHG
instruction to perform a TSL.
I think @Jester and @Seva Alekseyev have already done a great job answering this question but here is a simple implementation in C with inline Assembly by using pthreads on a x86 Ubuntu machine.
In the following example, there are two long-running threads. Both threads have a critical and a non-critical section, critical_region() and noncritical_region respectively. They both have to call enter_region() in order to get the lock. Once a thread gets the lock, it can start running its critical section. The other thread is blocked until the thread with the lock will call 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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With