Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TSL instruction reference

Tags:

assembly

masm

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.

like image 818
RF27 Avatar asked Mar 15 '14 13:03

RF27


People also ask

What is TSL instruction in operating system?

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.

Is progress guaranteed in TSL?

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.

How does TSL achieve mutual exclusion?

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.

What kind of solution is test and set lock TSL provide?

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.


2 Answers

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.

like image 157
Jester Avatar answered Oct 06 '22 09:10

Jester


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;
}
like image 33
László Balogh Avatar answered Oct 06 '22 09:10

László Balogh