__sys_time_slice = 10 ;[ms]


if used TimerCreate

uglobal
  __InternalTimerID dd ?
endg

initialize InitLinuxTimers
  .action lnx_sigaction
  .timer lnx_sigevent
  .time  lnx_itimerspec
begin
; set the signal handler.
        mov     eax, sys_sigaction
        mov     ebx, SIGALRM

        lea     ecx, [.action]
        mov     [ecx+lnx_sigaction.sa_handler], __TimerProc
        mov     [ecx+lnx_sigaction.sa_mask], 0
        mov     [ecx+lnx_sigaction.sa_flags], 0
        xor     edx, edx

        int $80
        stdcall     OutputRegister, regEAX, 16

; create the interval timer
        mov     eax, sys_timer_create
        mov     ebx, CLOCK_REALTIME

        lea     ecx, [.timer]
        mov     [ecx+lnx_sigevent.notify], SIGEV_SIGNAL
        mov     [ecx+lnx_sigevent.signo], SIGALRM
        mov     [ecx+lnx_sigevent.value], 0             ; not used but must be set - the function fails without it...
        mov     edx, __InternalTimerID

        int $80
        stdcall     OutputRegister, regEAX, 16

; start the timer
        mov     ebx, eax
        mov     eax, sys_timer_settime
        lea     edx, [.time]
        mov     [edx+lnx_itimerspec.it_interval.tv_sec], 0
        mov     [edx+lnx_itimerspec.it_interval.tv_nsec], __sys_time_slice*1000000
        mov     [edx+lnx_itimerspec.it_value.tv_sec], 0
        mov     [edx+lnx_itimerspec.it_value.tv_nsec], __sys_time_slice*1000000
        xor     esi, esi

        int $80
        stdcall     OutputRegister, regEAX, 16

    DebugMsg 'Interval timer set.'

        return
endp



finalize FreeLinuxTimers
begin

        mov     eax, sys_timer_delete
        mov     ebx, [__InternalTimerID]
        int $80

        return
endp

end if


; This procedure is called by the system on every time quant.
;

proc __TimerProc, .signal
begin
        push    ebx esi edi

        lea     eax, [__ptrFirstTimer]

.loop:
        mov     eax, [eax+TTimer.next]
        test    eax, eax
        jz      .end_timers

        test    [eax+TTimer.flags], tmfRunning
        jz      .loop

        mov     ecx, [eax+TTimer.value]
        add     ecx, __sys_time_slice
        mov     [eax+TTimer.value], ecx
        cmp     ecx, [eax+TTimer.interval]
        jl     .loop

; call event handler
        cmp     [eax+TTimer.callback], 0
        je      .handlerok

        push    eax

        mov     ecx, [eax+TTimer.flags]
        and     ecx, $0f
        cmp     eax, tmfDoNothing
        je      .end_event

; run the timer event in separate thread:
        stdcall ThreadCreate, [eax+TTimer.callback], eax

.end_event:
        pop     eax
        test    [eax+TTimer.flags], tmfSyncDestroy
        jz      .handlerok

        stdcall TimerDestroy, eax

.handlerok:
; jump to loop
        mov     ecx, [eax+TTimer.interval]
        sub     [eax+TTimer.value], ecx
        jmp     .loop

.end_timers:
        pop     edi esi ebx
        xor     eax, eax
        cret
endp