(*
 * @brief Тип для функции-обработчика треда  
 * typedef void ( *hsal_thread_worker)(void* );
 *)

@EXTERNAL FUNCTION typedef_hsal_thread_worker : VOID
VAR_INPUT 
	args: REF_TO VOID; 
END_VAR
END_FUNCTION

(*
type enum {
    HSAL_SCHED_OTHER = 0,
    HSAL_SCHED_FIFO,
    HSAL_SCHED_RR,
    // по необходимости добавятся новые пункты
} sch_policy;*)


TYPE sch_policy :
(
	HSAL_SCHED_OTHER:=0,
	HSAL_SCHED_FIFO:=1,
	HSAL_SCHED_RR:=2
);
END_TYPE



(**
 * @brief Обобщенный тип для хранения дескрипторов тредов в разных системам. 
 * Есть системы, где он представлен в целочисленном виде (id, для POSIX-совместимых),
 * а есть те, где он представлен указателем на структуру описателя треда (desc, для RTOS) 
 *)
 (*
typedef union {
    unsigned long id;
    uintptr_t desc;
} hsal_thread_desc;
*)




TYPE hsal_thread_desc :
STRUCT
	id: REF_TO DWORD;
	//descdesc: REF_TO VOID;
END_STRUCT
END_TYPE
(*
typedef struct {
    void *stack_addr;           // Указатель на буфер, выделенный под стек (в линуксе имеет значение по умолчанию, в RTOS устанавливается принудительно)
    size_t stack_size;          // Размер стека под тред (аналогично адресу)
    sch_policy sched_policy;    // Политика планировщика (только Linux)
    int priority;               // Приоритет треда (Linux (1-99) для sched_policy = SCHED_FIFO и SCHED_RR, RTOS 0-INT_MAX)
    char *name;                 // Имя задачи (Linux в целях отладки, RTOS - боевое)
} hsal_thread_attrs;
*)

TYPE hsal_thread_attrs :
STRUCT
	stack_addr: REF_TO VOID;
	stack_size: LWORD;
	sched_policy:sch_policy; 
	priority: DINT;
	name: REF_TO CHAR;
END_STRUCT
END_TYPE




TYPE HSAL_RETURN_VALUES:
(

	EPERM		 :=1,              /* Operation not permitted */
    ENOENT		 :=2,              /* No such file or directory */
    ESRCH		 :=3,              /* No such process */
    EINTR		 :=4,              /* Interrupted system call */
    EIO		 	 :=5,              /* I/O error */
    ENXIO		 :=6,              /* No such device or address */
    E2BIG		 :=7,              /* Argument list too long */
    ENOEXEC		 :=8,              /* Exec format error */
    EBADF		 :=9,              /* Bad file number */
    ECHILD		:=10,              /* No child processes */
    EAGAIN		:=11,              /* Try again #define	EWOULDBLOCK	EAGAIN	 Operation would block */
    ENOMEM		:=12,              /* Out of memory */
    EACCES		:=13,              /* Permission denied */
    EFAULT		:=14,              /* Bad address */
    ENOTBLK		:=15,              /* Block device required */
    EBUSY		:=16,              /* Device or resource busy */
    EEXIST		:=17,              /* File exists */
    EXDEV		:=18,              /* Cross-device link */
    ENODEV		:=19,              /* No such device */
    ENOTDIR		:=20,              /* Not a directory */
    EISDIR		:=21,              /* Is a directory */
    EINVAL		:=22,              /* Invalid argument */
    ENFILE		:=23,              /* File table overflow */
    EMFILE		:=24,              /* Too many open files */
    ENOTTY		:=25,              /* Not a typewriter */
    ETXTBSY		:=26,              /* Text file busy */
    EFBIG		:=27,              /* File too large */
    ENOSPC		:=28,              /* No space left on device */
    ESPIPE		:=29,              /* Illegal seek */
    EROFS		:=30,              /* Read-only file system */
    EMLINK		:=31,              /* Too many links */
    EPIPE		:=32,              /* Broken pipe */
    EDOM		:=33,              /* Math argument out of domain of func */
    ERANGE		:=34,              /* Math result not representable */
    ENOSYS      :=38,              /* Not implemented */
	ENOTSUP		:=95
);
END_TYPE

@EXTERNAL FUNCTION typedef_create : HSAL_RETURN_VALUES
VAR_INPUT 
	thread: REF_TO HSAL_Thread;
	context: REF_TO VOID;
	worker: REF_TO typedef_hsal_thread_worker;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_restore_desc : HSAL_RETURN_VALUES
VAR_INPUT 
	thread:REF_TO HSAL_Thread;
END_VAR
END_FUNCTION


@EXTERNAL FUNCTION typedef_get_id : hsal_thread_desc
VAR_INPUT 
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_stop_cur : HSAL_RETURN_VALUES
VAR_INPUT 
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_stop_force : HSAL_RETURN_VALUES
VAR_INPUT 
	thread:REF_TO HSAL_Thread;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_suspend : HSAL_RETURN_VALUES
VAR_INPUT 
	thread:REF_TO HSAL_Thread;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_resume : HSAL_RETURN_VALUES
VAR_INPUT
	thread: REF_TO HSAL_Thread;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_runtime_set_prio_policy : HSAL_RETURN_VALUES
VAR_INPUT 
	thread: REF_TO HSAL_Thread;
	policy: DINT;
	priority: DINT;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_runtime_get_prio_policy : HSAL_RETURN_VALUES
VAR_INPUT 
	thread: REF_TO HSAL_Thread;
	policy: REF_TO DINT;
	priority: REF_TO DINT;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_wait_stopped : HSAL_RETURN_VALUES
VAR_INPUT 
	thread:REF_TO HSAL_Thread;
END_VAR
END_FUNCTION

@EXTERNAL FUNCTION typedef_runtime_set_name : HSAL_RETURN_VALUES
VAR_INPUT 
	thread:REF_TO  HSAL_Thread;
END_VAR
VAR_INPUT {ref}
	name: STRING;
END_VAR
END_FUNCTION



TYPE HSAL_Thread :
STRUCT
	id  :           intptr_t;         ///< ID треда    
    attrs:          hsal_thread_attrs;       ///< Аттрибуты треда 
	create:         REF_TO typedef_create;  //int ( *create)(struct HSAL_Thread *thread, void *context, hsal_thread_worker worker);

	restore_desc:   REF_TO typedef_restore_desc;				//int (*restore_desc)(struct HSAL_Thread *thread);

    get_id:         REF_TO typedef_get_id;						//hsal_thread_desc ( *get_id)(void);

    stop_cur:       REF_TO typedef_stop_cur;					//int ( *stop_cur)(void);

    stop_force:     REF_TO typedef_stop_force;				//int ( *stop_force)(struct HSAL_Thread *thread);
    
    suspend:        REF_TO typedef_suspend;					//int ( *suspend)(struct HSAL_Thread *thread);

    resume:         REF_TO typedef_resume;						//int ( *resume)(struct HSAL_Thread *thread);

    runtime_set_prio_policy:    REF_TO typedef_runtime_set_prio_policy; //int ( *runtime_set_prio_policy)(struct HSAL_Thread *thread, int policy, int priority);

    runtime_get_prio_policy:    REF_TO typedef_runtime_get_prio_policy;	//int ( *runtime_get_prio_policy)(struct HSAL_Thread *thread, int *policy, int *priority);

    wait_stopped:   REF_TO typedef_wait_stopped;			//int ( *wait_stopped)(struct HSAL_Thread *thread);

    runtime_set_name: REF_TO typedef_runtime_set_name;	//int ( *runtime_set_name)(struct HSAL_Thread *thread, const char *name);
END_STRUCT
END_TYPE


(**
 * @brief Функция инициализирует структуру треда настройками и правильной реализацией методов  
 * @param [in] thread Описатель треда
 * @return Код ошибки, или 0 в случае успеха
 *
 * int hsal_thread_constructor(HSAL_Thread *thread);
 *)
@EXTERNAL FUNCTION hsal_thread_constructor : HSAL_RETURN_VALUES
VAR_INPUT 
	thread: REF_TO HSAL_Thread;
END_VAR
END_FUNCTION


