Any Semaphore Implementation information pls?
Any Semaphore Implementation information pls?
Any Semaphore Implementation information pls?
Or any lock mechanism?
Or any lock mechanism?
- einsteinjunior
- Member
- Posts: 90
- Joined: Tue Sep 11, 2007 6:42 am
Re: Any Semaphore Implementation information pls?
What type of semaphore do you want to implement?Signal/Wait ?
Re: Any Semaphore Implementation information pls?
Write one, genius.oohayulin wrote:Any Semaphore Implementation information pls?
Or any lock mechanism?
Re: Any Semaphore Implementation information pls?
Hi,
This code is *bad* - it repeatedly locks the bus, so when there's several CPUs spinning any remaining CPUs have to struggle to get any bus bandwidth (which slows them down and means it takes longer for who-ever has the lock to release the lock). Here's some much better spinlock code:
This is much better, but it's still not good enough because it doesn't provide any help for debugging complex/messy problems (like deadlocks). Here's some even better spinlock code:
This is a good start, as it'll find most common mistakes people make with spinlocks. There are other problems that could be checked for (e.g. trying to do a task switch before releasing locks), and some of the tests might annoy you in strange situations (e.g. when a thread is meant to release a lock that was acquired by a different thread), but it should give you a good idea of what things could be detected.
However, this still isn't that good - the call/ret overhead is silly considering that the routines are so short (especially when you're not debugging). Here's one way to avoid that:
Note: None of the code above has been tested in any way...
Spinlocks are relatively simple. Decent quality semaphore code is left as an exercise for the reader.
Cheers,
Brendan
I'm a little bored, so here's some simple unoptimized spinlock code:oohayulin wrote:Or any lock mechanism?
Code: Select all
;Acquire the lock
;
;Input
; esi address of the lock
acquireSpinlock:
.tryLock:
lock bts [esi],0
jc .tryLock
ret
;Release the lock
;
;Input
; esi address of the lock
releaseLock:
mov dword [esi],0
ret
Code: Select all
;Acquire the lock
;
;Input
; esi address of the lock
acquireSpinlock:
.testLock1:
bt [esi],0
jnc .tryLock
.testLock2:
pause
bt [esi],0
jc .testLock2
.tryLock:
lock bts [esi],0
jc .tryLock
ret
;Release the lock
;
;Input
; esi address of the lock
releaseSpinlock:
mov dword [esi],0
ret
Code: Select all
;Initialize the lock
;
;Input
; esi address of the lock
initSpinlock:
%ifdef DEBUGGING
cmp dword [esi+4],0xFEEDFACE
je CRITICAL_ERROR_attempt_to_initialize_lock_that_was_already_initialized
mov dword [esi+4],0xFEEDFACE
%endif
mov dword [esi],0
ret
;Acquire the lock
;
;Input
; esi address of the lock
acquireSpinlock:
%ifdef DEBUGGING
push ebx
push eax
mov ebx,[current_thread_ID]
xor eax,eax
or ebx,0x80000000
cmp dword [esi+4],0xFEEDFACE
je CRITICAL_ERROR_attempt_to_acquire_something_that_isn't_a_valid_lock
.testLock1:
cmp [esi],eax
je .tryLock
.testLock2:
pause
cmp [esi],eax
jne .testLock2
.tryLock:
lock cmpxchg [esi],ebx
je .gotLock
cmp eax,ebx
jne CRITICAL_ERROR_attempt_to_acquire_lock_that_thread_already_has
xor eax,eax
jmp .testLock2
.gotLock:
pop eax
pop ebx
%else
.testLock1:
bt [esi],0
jnc .tryLock
.testLock2:
pause
bt [esi],0
jc .testLock2
.tryLock:
lock bts [esi],0
jc .tryLock
%endif
ret
;Release the lock
;
;Input
; esi address of the lock
releaseSpinlock:
%ifdef DEBUGGING
cmp dword [esi+4],0xFEEDFACE
jne CRITICAL_ERROR_attempt_to_release_something_that_isn't_a_valid_lock
cmp dword [esi],0
jne CRITICAL_ERROR_tried_to_free_lock_when_lock_not_acquired
push ebx
mov ebx,[current_thread_ID]
or ebx,0x80000000
cmp [esi],ebx
pop ebx
jne CRITICAL_ERROR_wrong_task_tried_to_free_lock
%endif
mov dword [esi],0
ret
However, this still isn't that good - the call/ret overhead is silly considering that the routines are so short (especially when you're not debugging). Here's one way to avoid that:
Code: Select all
;Macro to create a pre-initialized spinlock (e.g. in the ".data" section)
%macro SPINLOCK 1
%if ($ & 0x7F) <> 0
%warning Lock not aligned on a 128-byte boundary
%endif
dd 0
dd 0xFEEDFACE
%endmacro
;Macro to initialize a lock (e.g. for dynamically allocated locks)
%macro INIT_SPINLOCK 1
%ifdef DEBUGGING
cmp dword [%1+4],0xFEEDFACE
je CRITICAL_ERROR_attempt_to_initialize_lock_that_was_already_initialized
mov dword [%1+4],0xFEEDFACE
%endif
mov dword [%1],0
%endmacro
;Macro to acquire a lock
%macro ACQUIRE_SPINLOCK 1
%ifdef DEBUGGING
push ebx
push eax
mov ebx,[current_thread_ID]
xor eax,eax
or ebx,0x80000000
cmp dword [%1+4],0xFEEDFACE
je CRITICAL_ERROR_attempt_to_acquire_something_that_isn't_a_valid_lock
%%testLock1:
cmp [%1],eax
je %%tryLock
%%testLock2:
pause
cmp [%1],eax
jne %%testLock2
%%tryLock:
lock cmpxchg [%1],ebx
je %%gotLock
cmp eax,ebx
jne CRITICAL_ERROR_attempt_to_acquire_lock_that_thread_has_already_acquired
xor eax,eax
jmp %%testLock2
%%gotLock:
pop eax
pop ebx
%else
%%testLock1:
bt [%1],0
jnc %%tryLock
%%testLock2:
pause
bt [%1],0
jc %%testLock2
%%tryLock:
lock bts [%1],0
jc %%tryLock
%endif
%endmacro
;Macro to release a lock
%macro RELEASE_SPINLOCK 1
%ifdef DEBUGGING
cmp dword [%1+4],0xFEEDFACE
jne CRITICAL_ERROR_attempt_to_release_something_that_isn't_a_valid_lock
cmp dword [%1],0
jne CRITICAL_ERROR_tried_to_free_lock_when_lock_not_acquired
push ebx
mov ebx,[current_thread_ID]
or ebx,0x80000000
cmp [%1],ebx
pop ebx
jne CRITICAL_ERROR_wrong_task_tried_to_free_lock
%endif
mov dword [%1],0
%endmacro
Spinlocks are relatively simple. Decent quality semaphore code is left as an exercise for the reader.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re: Any Semaphore Implementation information pls?
Brendan, you provide is what I want.
Thank you all guys.
I am not genius. haha.
But no hero, be hero.
Thank you all guys.
I am not genius. haha.
But no hero, be hero.
- salil_bhagurkar
- Member
- Posts: 261
- Joined: Mon Feb 19, 2007 10:40 am
- Location: India
Re: Any Semaphore Implementation information pls?
Can anybody tell me about a practical implementation of semaphores where there could be more than one users (the value is initialized to -2 giving 2 users and sleeping any more users than 2)... Till now i have only seen sems with initialized value -1 meaning single user...
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Any Semaphore Implementation information pls?
on a 486:
Go figure how it works
Code: Select all
sem_down:
mov eax, 1
lock xadd [semaphore], eax ; magix happens here
.wait:
mov edx, [semaphore+4]
add edx, user_count
cmp eax, edx
jns .wait
ret
sem_up:
lock inc [semaphore+4]
ret
semaphore: dd 0, 0
- salil_bhagurkar
- Member
- Posts: 261
- Joined: Mon Feb 19, 2007 10:40 am
- Location: India
Re: Any Semaphore Implementation information pls?
Okay sorry for my wrong terminology.. By practical implementation, i meant practical application in operating systems.. For example in linux... Some usual application where it is used... Not the code for it...
- Combuster
- Member
- Posts: 9301
- Joined: Wed Oct 18, 2006 3:45 am
- Libera.chat IRC: [com]buster
- Location: On the balcony, where I can actually keep 1½m distance
- Contact:
Re: Any Semaphore Implementation information pls?
a practical application: reader-writer configurations
You have a shared buffer, application A writes to it, Application B reads from it. when A has done writing a block to the buffer, it increases the semaphore. Application B will try to decrease the semaphore. When it can, A must have completed writing a block to the buffer so that B can read it. When it can't decrease it, it will wait for the semaphore (and by that, wait for the next block of data)
Textbook example, I might add.
You have a shared buffer, application A writes to it, Application B reads from it. when A has done writing a block to the buffer, it increases the semaphore. Application B will try to decrease the semaphore. When it can, A must have completed writing a block to the buffer so that B can read it. When it can't decrease it, it will wait for the semaphore (and by that, wait for the next block of data)
Textbook example, I might add.
- kataklinger
- Member
- Posts: 381
- Joined: Fri Nov 04, 2005 12:00 am
- Location: Serbia
Re: Any Semaphore Implementation information pls?
For instance you can have buffer of X work items and best performance are gained if you let only Y threads to execute work in the buffer concurrently. Now you can use semaphore to signal only Y worker threads that are waiting by setting semaphore count to Y when the buffer is full (assuming that the threads know how to split work i.e. they can use their IDs to calculate indices of the items in the buffer...)