still problems with semaphore code and smp
Posted: Sat Mar 17, 2007 12:44 pm
I still have the problem that my semaphore code doesn´t work on smp machines (I tested it on qemu and bochs, because at the moment I can´t test it on a real smp machine).
The problem seems to be that 2 threads execute the code which should be saved by the semaphore.
I will give you all the code you need to have a look at, but I think brendan is the only one who will understand my assembly "slang"
semaphore code:
The problem seems to be that 2 threads execute the code which should be saved by the semaphore.
I will give you all the code you need to have a look at, but I think brendan is the only one who will understand my assembly "slang"
semaphore code:
Code: Select all
;----------------------------
PROC semaphore_acquire_smp, sem
;----------------------------
BEGIN
;----------------------------
; make sure we are the only one to work on the semaphore
cli
CALL spinlock_acquire, dword[sem]
lock sub dword[esi+semaphore_t.count],1
jz .end
;----------------------------
; look if we have to wait or if we can go right away
cmp dword[esi+semaphore_t.count],0
jg .end
;----------------------------
; we have to wait
; APIC_GET_ID eax
; mov edx,[CPU_PTR+4*eax]
mov ebx,[fs:thread_t.tid]
mov edi,[esi+semaphore_t.threads] ;edi= firstThread
; mov eax,[edx+cpu_t.schdl_act_thread]
mov eax,[THREAD_TABLE+4*ebx] ;eax= actThread
test eax,eax
jnz .temp
int 0
;----------------------------
; look if we are the first thread that need to wait
align 4
.temp:
test edi,edi
jz .first
mov ebx,[edi+thread_t.prev] ;ebx= firstThread.prev= lastThread
xor ecx,ecx
mov [eax+thread_t.prev],ebx ;actThread.prev= lastThread
mov [eax+thread_t.next],ecx ;actThread.next= NULL
mov [edi+thread_t.prev],eax ;firstThread.prev= actThread
mov [ebx+thread_t.next],eax ;lastThread.next= actThread
jmp .scheduler
;----------------------------
; we are the first thread
align 4
.first:
mov [esi+semaphore_t.threads],eax
mov [eax+thread_t.prev],eax ;actThread.prev= firstThread.prev= actThread
mov [eax+thread_t.next],edi ;actThread.next= firstThread.next= NULL
;----------------------------
; scheduler have to know that this thread wants to wait
align 4
.scheduler:
or dword[eax+thread_t.flags],THREAD_WAIT or THREAD_RESCHEDULE
CALL spinlock_release, esi
CALLINT scheduler_reschedule_smp
sti
RETURN
;----------------------------
align 4
.end:
CALL spinlock_release, esi
sti
RETURN
ENDP
;----------------------------
;----------------------------
PROC semaphore_release, sem
;----------------------------
BEGIN
;----------------------------
; make sure we are the only one to work on the semaphore
cli
CALL spinlock_acquire, dword[sem]
lock add dword[esi+semaphore_t.count],1
;----------------------------
; look if we need to awake a thread
cmp dword[esi+semaphore_t.count],0
jg .end
;----------------------------
; we have to awake the thread on the top of the queue
mov eax,[esi+semaphore_t.threads] ;eax= firstThread
mov ebx,[eax+thread_t.next] ;ebx= firstThread.next= secondThread
mov ecx,[eax+thread_t.prev] ;ecx= firstThread.prev= lastThread
test ebx,ebx
jz .last
;----------------------------
; put the 2nd thread onto the top of the queue and put the last thread onto the 2nd threads prev ptr
mov [ebx+thread_t.prev],ecx ;secondThread.prev= lastThread
mov [esi+semaphore_t.threads],ebx ;firstThread= secondThread
jmp .scheduler
;----------------------------
; there is no more thread on the queue
align 4
.last:
mov [esi+semaphore_t.threads],ebx
;----------------------------
; scheduler needs to awaken the thread in eax
align 4
.scheduler:
CALL spinlock_release, esi
sti
CALL scheduler_add_scheduler, eax
RETURN
;----------------------------
align 4
.end:
CALL spinlock_release, esi
sti
RETURN
ENDP
;----------------------------