Ok, this is my 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 ebx,[cpu_ptr+4*eax]
mov edi,[esi+semaphore_t.threads]
mov eax,[ebx+cpu_t.schdl_act_thread]
test edi,edi
jz .first
mov ebx,[edi+thread_t.prev]
xor ecx,ecx
mov [eax+thread_t.prev],ebx
mov [eax+thread_t.next],ecx
mov [edi+thread_t.prev],eax
mov [ebx+thread_t.next],eax
jmp .scheduler
;----------------------------
; we are the first thread
align 4
.first:
mov [esi+semaphore_t.threads],eax
mov [eax+thread_t.prev],eax
mov [eax+thread_t.next],edi
;----------------------------
; 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, dword[sem]
CALLINT scheduler_reschedule_smp
sti
.end_wait:
RETURN
;----------------------------
align 4
.end:
CALL spinlock_release, dword[sem]
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]
mov ebx,[eax+thread_t.next]
mov ecx,[eax+thread_t.prev]
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
mov [esi+semaphore_t.threads],ebx
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
.scheduler:
and dword[eax+thread_t.flags],not THREAD_WAIT
push eax
CALL spinlock_release, dword[sem]
sti
CALL scheduler_add_scheduler ;par is in pushed eax
;----------------------------
.end_awaken:
RETURN
;----------------------------
align 4
.end:
CALL spinlock_release, dword[sem]
sti
RETURN
ENDP
;----------------------------
This is the CALLINT macro:
Code: Select all
;----------------------------
macro CALLINT proc
{
pushfd
push cs
call proc
}
;----------------------------
I don?t know which piece of code could make this failure.