
uses pthreads, libc


body ThreadCreate
.threadid dd ?
begin
        push    ecx edx
        lea     eax, [.threadid]
        mov     [.threadid], 0
        cinvoke pthread_create, eax, NULL, [.ptrFunction], [.ptrArguments]
        test    eax, eax
        jnz     .error

        cinvoke pthread_detach, [.threadid]
        mov     eax, [.threadid]
        clc
        pop     edx ecx
        return

.error:
        stc
        pop     edx ecx
        return
endp


; Terminate current thread
; Returns: eax = 0
body Terminate
begin
        cinvoke pthread_exit, [.exit_code]
        return
endp




body FreeThreadID
begin
        return
endp



body Exec
begin
;sys_forkd
        return
endp



; MUTEX functions
;_________________________________________________________________________________________


;struct TMutex
;  .value     dd ?
;  .recursion dd ?
;  .kind      dd ?
;  .owner     dd ?
;  .event     dd ?
;ends

struct TMutex
  .array rb 48
ends


;TODO: This implementation ignores the .ptrName argument and this way creates only
;private proces mutexes.

body MutexCreate
.attr rb 256
begin
        pushad

        lea     esi, [.attr]
        cinvoke pthread_mutexattr_init, esi
        cinvoke pthread_mutexattr_settype, esi, PTHREAD_MUTEX_RECURSIVE

        cinvoke pthread_mutex_init, [.ptrMutex], esi
        cinvoke pthread_mutex_lock, [.ptrMutex]

        cinvoke pthread_mutexattr_destroy, esi

        popad
        return
endp




body WaitForMutex
.time lnx_timespec
begin
        pushad

        mov     eax, [.timeout]
        test    eax, eax
        js      .no_timeout

        mov     ecx, 1000
        cdq
        div     ecx
        imul    edx, 1000000

        lea     ecx, [.time]
        mov     [ecx+lnx_timespec.tv_sec], eax
        mov     [ecx+lnx_timespec.tv_nsec], edx

        cinvoke pthread_mutex_timedlock, [.ptrMutex], ecx
        test    eax, eax
        jnz     .error
        jmp     .finish

.no_timeout:
        cinvoke pthread_mutex_lock, [.ptrMutex]

.finish:
        clc
        popad
        return

.error:
        mov     [esp+4*regEAX], eax
        stc
        popad
        return
endp




body MutexRelease
begin
        pushf
        push    eax ecx edx
        cinvoke pthread_mutex_unlock, [.ptrMutex]
        pop     edx ecx eax
        popf
        return
endp



body MutexDestroy
begin
        push    eax ecx edx

        cinvoke pthread_mutex_destroy, [.ptrMutex]

        pop     edx ecx eax
        return
endp





