/*
 *  thread_linux.c
 *
 *  Copyright 2013-2021 Michael Zillgith
 *
 *  This file is part of Platform Abstraction Layer (libpal)
 *  for libiec61850, libmms, and lib60870.
 */

#include "hal_thread.h"
#include "lib_memory.h"

#include "FreeRTOS.h"
#include "main.h"
#include "semphr.h"
#include "platform_thread.h"
#include "platform_memory.h"


struct sThread {
    ThreadExecutionFunction function;
    void* parameter;
    platform_thread_t * pthread;
    int state;
    bool autodestroy;
};

SemaphoreHandle_t
Semaphore_create(void)
{
    return xSemaphoreCreateMutex();;
}

/* Wait until semaphore value is more than zero. Then decrease the semaphore value. */
void
Semaphore_wait(Semaphore queueMutex)
{
    xSemaphoreTake(queueMutex, 1000);
}

void
Semaphore_post(Semaphore queueMutex)
{
    xSemaphoreGive(queueMutex);
}

void
Semaphore_destroy(SemaphoreHandle_t logMutex)
{
    vSemaphoreDelete(logMutex)
}

Thread
Thread_create(ThreadExecutionFunction function, void* parameter, bool autodestroy)
{
    Thread thread = (Thread) GLOBAL_MALLOC(sizeof(struct sThread));

    if (thread != NULL) {
        thread->parameter = parameter;
        thread->function = function;
        thread->state = 0;
        thread->autodestroy = autodestroy;
    }

    return thread;
}

static void*
destroyAutomaticThread(void* parameter)
{
    Thread thread = (Thread) parameter;

    thread->function(thread->parameter);

    GLOBAL_FREEMEM(thread);

    pthread_exit(NULL);
}

void
Thread_start(Thread thread)
{
    if (thread->autodestroy == true) {
        pthread_create(&thread->pthread, NULL, destroyAutomaticThread, thread);
        pthread_detach(thread->pthread);
    }
    else
        pthread_create(&thread->pthread, NULL, thread->function, thread->parameter);

    thread->state = 1;
}

void
Thread_destroy(Thread thread)
{
    if (thread->state == 1) {
        pthread_join(thread->pthread, NULL);
    }

    GLOBAL_FREEMEM(thread);
}

void
Thread_sleep(int millies)
{
    usleep(millies * 1000);
}

