Mutex

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Whatever5k

Mutex

Post by Whatever5k »

I'm wondering how to implement a Mutex. I've got OS Design and Implementation by A. Tanenbaum and he discusses this topic, too. But there's only a solution, if only *two* processes want to access a variable. There is also the tsr instruction, but I do not know, if every CPU supports it. And message handling is too compilicated.
So, what do you think - how should I solve this?
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Mutex

Post by Pype.Clicker »

Code: Select all

mutex_lock:
       cli
; assume [edx] is the place where the mutex is
; a non-zero value in the mutex means its locked.
       mov al, 1
.loop:
       xchg [edx],al
       cmp al,1
       je .loop
       ret

mutex_unlock:
       mov byte [edx],0
       sti
       ret
now, this is a "spinlock" mutex, so you should use it only when you know the access to the component will be locked only for a very short time. You'll also notice i locked interrupts while waiting so that we're sure there won't be a preemptive task switch while the mutex is held.

This code will also work fine with multi-CPU systems as XCHG is an atomic operation on the bus (lock xchg if not sure ;). And because you only put short operations and have busy waiting, it won't hang other CPUs for too long :)

Basic idea is to use this to control access to structures more complex like semaphores, message queues, etc.
Whatever5k

Re:Mutex

Post by Whatever5k »

Ok, but how do I transfer my mutex variable to edx?
Is this here possible?

Code: Select all

[BITS 32]

lock_mutex:
  cli;
  push eax;
  push edx;
  mov al,1
  mov edx,[ss:esp+2]   ; is this here possible?
.loop:
  ...
  ...
Is it possible? If not, how can I fix it?
I do the [ss:esp+2] because I call lock_mutex in C like this:
lock_mutex(&semaphore);
So semaphore is put on the stack.
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:Mutex

Post by Pype.Clicker »

Whatever5k wrote: Ok, but how do I transfer my mutex variable to edx?
Is this here possible?

Code: Select all

[BITS 32]

lock_mutex:
  cli;
  push eax;
  push edx;
  mov al,1
  mov edx,[ss:esp+2]   ; is this here possible?
.loop:
  ...
  ...
Is it possible? If not, how can I fix it?
I do the [ss:esp+2] because I call lock_mutex in C like this:
lock_mutex(&semaphore);
So semaphore is put on the stack.
just keep in mind that dx is not the mutex, but just a pointer to it ... So yes, you can give the address of semaphore on the stack and get it with [ss:esp+4] (remember we're in BITS32, so eip needs 4 bytes), or for more cleaner (backtrace-friendly) code,

Code: Select all

push ebp
mov ebp, esp
mov edx,[ebp+8]
...

pop ebp
ret
Whatever5k

Re:Mutex

Post by Whatever5k »

Thanks...here is the full code:

Code: Select all

[BITS 32]

[global _lock_mutex]
_lock_mutex:
        cli     ; disable interrupts
        push eax;       ; save
        push edx;       ; registers
        push ebp;
        mov ebp,esp
        mov edx,[ss:ebp+8]      ; MOV the parameter of the function to edx
        mov al,1
.loop:
        xchg [edx],al
        cmp al,1
        je .loop
        pop ebp;
        pop edx;
        pop eax;
        ret

[global _unlock_mutex]
_unlock_mutex:
        push eax;
        push edx;
        push ebp;
        mov ebp,esp
        mov edx,[ss:ebp+8]
        mov byte [edx],0
        pop ebp;
        pop edx;
        pop eax;
        sti     ; enable interrupts
        ret
Post Reply