731 lines
24 KiB
C
731 lines
24 KiB
C
/*
|
||
*********************************************************************************************************
|
||
* uC/OS-III
|
||
* The Real-Time Kernel
|
||
*
|
||
* Copyright 2009-2020 Silicon Laboratories Inc. www.silabs.com
|
||
*
|
||
* SPDX-License-Identifier: APACHE-2.0
|
||
*
|
||
* This software is subject to an open source license and is distributed by
|
||
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
|
||
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
|
||
*
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* POSIX GNU Port
|
||
*
|
||
* File : os_cpu_c.c
|
||
* Version : V3.08.00
|
||
*********************************************************************************************************
|
||
* For : POSIX
|
||
* Toolchain : GNU
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
#define OS_CPU_GLOBALS
|
||
#define _GNU_SOURCE
|
||
|
||
#ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
|
||
const CPU_CHAR *os_cpu_c__c = "$Id: $";
|
||
#endif
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INCLUDE FILES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#include "../../Source/os.h"
|
||
#include <os_cfg_app.h>
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <pthread.h>
|
||
#include <stdint.h>
|
||
#include <signal.h>
|
||
#include <semaphore.h>
|
||
#include <time.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
#include <stdlib.h>
|
||
#include <sys/types.h>
|
||
#include <sys/syscall.h>
|
||
#include <sys/resource.h>
|
||
#include <errno.h>
|
||
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DEFINES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#define THREAD_CREATE_PRIO 50u /* Tasks underlying posix threads prio. */
|
||
|
||
/* Err handling convenience macro. */
|
||
#define ERR_CHK(func) do {int res = func; \
|
||
if (res != 0u) { \
|
||
printf("Error in call '%s' from %s(): %s\r\n", #func, __FUNCTION__, strerror(res)); \
|
||
perror(" \\->'errno' indicates (might not be relevant if function doesn't use 'errno')"); \
|
||
raise(SIGABRT); \
|
||
} \
|
||
} while(0)
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL DATA TYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
typedef struct os_tcb_ext_posix {
|
||
pthread_t Thread;
|
||
pid_t ProcessId;
|
||
sem_t InitSem;
|
||
sem_t Sem;
|
||
} OS_TCB_EXT_POSIX;
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL FUNCTION PROTOTYPES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void *OSTaskPosix (void *p_arg);
|
||
|
||
static void OSTaskTerminate (OS_TCB *p_tcb);
|
||
|
||
static void OSThreadCreate (pthread_t *p_thread,
|
||
void *p_task,
|
||
void *p_arg,
|
||
int prio);
|
||
|
||
static void OSTimeTickHandler (void);
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL VARIABLES
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
/* Tick timer cfg. */
|
||
static CPU_TMR_INTERRUPT OSTickTmrInterrupt = { .Interrupt.NamePtr = "Tick tmr interrupt",
|
||
.Interrupt.Prio = 10u,
|
||
.Interrupt.TraceEn = 0u,
|
||
.Interrupt.ISR_Fnct = OSTimeTickHandler,
|
||
.Interrupt.En = 1u,
|
||
.OneShot = 0u,
|
||
.PeriodSec = 0u,
|
||
.PeriodMuSec = (1000000u / OS_CFG_TICK_RATE_HZ)
|
||
};
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* LOCAL CONFIGURATION ERRORS
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
#if (OS_CFG_TICK_RATE_HZ > 100u)
|
||
#warning "Time accuracy cannot be maintained with OS_CFG_TICK_RATE_HZ > 100u.\n\n",
|
||
#endif
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* IDLE TASK HOOK
|
||
*
|
||
* Description: This function is called by the idle task. This hook has been added to allow you to do
|
||
* such things as STOP the CPU to conserve power.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : None.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSIdleTaskHook (void)
|
||
{
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||
(*OS_AppIdleTaskHookPtr)();
|
||
}
|
||
#endif
|
||
|
||
sleep(1u); /* Reduce CPU utilization. */
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* OS INITIALIZATION HOOK
|
||
*
|
||
* Description: This function is called by OSInit() at the beginning of OSInit().
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) Interrupts should be disabled during this call.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
|
||
void OSInitHook (void)
|
||
{
|
||
struct rlimit rtprio_limits;
|
||
|
||
|
||
ERR_CHK(getrlimit(RLIMIT_RTPRIO, &rtprio_limits));
|
||
if (rtprio_limits.rlim_cur != RLIM_INFINITY) {
|
||
printf("Error: RTPRIO limit is too low. Set to 'unlimited' via 'ulimit -r' or /etc/security/limits.conf\r\n");
|
||
exit(-1);
|
||
}
|
||
|
||
CPU_IntInit(); /* Initialize critical section objects. */
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* STATISTIC TASK HOOK
|
||
*
|
||
* Description: This function is called every second by uC/OS-III's statistics task. This allows your
|
||
* application to add functionality to the statistics task.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : None.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSStatTaskHook (void)
|
||
{
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppStatTaskHookPtr != (OS_APP_HOOK_VOID)0) {
|
||
(*OS_AppStatTaskHookPtr)();
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TASK CREATION HOOK
|
||
*
|
||
* Description: This function is called when a task is created.
|
||
*
|
||
* Arguments : p_tcb Pointer to the task control block of the task being created.
|
||
*
|
||
* Note(s) : 1) Interrupts are disabled during this call.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSTaskCreateHook (OS_TCB *p_tcb)
|
||
{
|
||
OS_TCB_EXT_POSIX *p_tcb_ext;
|
||
int ret;
|
||
|
||
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppTaskCreateHookPtr != (OS_APP_HOOK_TCB)0) {
|
||
(*OS_AppTaskCreateHookPtr)(p_tcb);
|
||
}
|
||
#endif
|
||
|
||
p_tcb_ext = malloc(sizeof(OS_TCB_EXT_POSIX));
|
||
p_tcb->ExtPtr = p_tcb_ext;
|
||
|
||
ERR_CHK(sem_init(&p_tcb_ext->InitSem, 0u, 0u));
|
||
ERR_CHK(sem_init(&p_tcb_ext->Sem, 0u, 0u));
|
||
|
||
OSThreadCreate(&p_tcb_ext->Thread, OSTaskPosix, p_tcb, THREAD_CREATE_PRIO);
|
||
|
||
do {
|
||
ret = sem_wait(&p_tcb_ext->InitSem); /* Wait for init. */
|
||
if (ret != 0 && errno != EINTR) {
|
||
raise(SIGABRT);
|
||
}
|
||
} while (ret != 0);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TASK DELETION HOOK
|
||
*
|
||
* Description: This function is called when a task is deleted.
|
||
*
|
||
* Arguments : p_tcb Pointer to the task control block of the task being deleted.
|
||
*
|
||
* Note(s) : 1) Interrupts are disabled during this call.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSTaskDelHook (OS_TCB *p_tcb)
|
||
{
|
||
OS_TCB_EXT_POSIX *p_tcb_ext = (OS_TCB_EXT_POSIX *)p_tcb->ExtPtr;
|
||
pthread_t self;
|
||
CPU_BOOLEAN same;
|
||
|
||
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppTaskDelHookPtr != (OS_APP_HOOK_TCB)0) {
|
||
(*OS_AppTaskDelHookPtr)(p_tcb);
|
||
}
|
||
#endif
|
||
|
||
self = pthread_self();
|
||
same = (pthread_equal(self, p_tcb_ext->Thread) != 0u);
|
||
if (same != 1u) {
|
||
ERR_CHK(pthread_cancel(p_tcb_ext->Thread));
|
||
}
|
||
|
||
OSTaskTerminate(p_tcb);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TASK RETURN HOOK
|
||
*
|
||
* Description: This function is called if a task accidentally returns. In other words, a task should
|
||
* either be an infinite loop or delete itself when done.
|
||
*
|
||
* Arguments : p_tcb Pointer to the task control block of the task that is returning.
|
||
*
|
||
* Note(s) : None.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSTaskReturnHook (OS_TCB *p_tcb)
|
||
{
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppTaskReturnHookPtr != (OS_APP_HOOK_TCB)0) {
|
||
(*OS_AppTaskReturnHookPtr)(p_tcb);
|
||
}
|
||
#else
|
||
(void)p_tcb; /* Prevent compiler warning */
|
||
#endif
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INITIALIZE A TASK'S STACK
|
||
*
|
||
* Description: This function is called by OS_Task_Create() or OSTaskCreateExt() to initialize the stack
|
||
* frame of the task being created. This function is highly processor specific.
|
||
*
|
||
* Arguments : p_task Pointer to the task entry point address.
|
||
*
|
||
* p_arg Pointer to a user supplied data area that will be passed to the task
|
||
* when the task first executes.
|
||
*
|
||
* p_stk_base Pointer to the base address of the stack.
|
||
*
|
||
* stk_size Size of the stack, in number of CPU_STK elements.
|
||
*
|
||
* opt Options used to alter the behavior of OS_Task_StkInit().
|
||
* (see OS.H for OS_TASK_OPT_xxx).
|
||
*
|
||
* Returns : Always returns the location of the new top-of-stack' once the processor registers have
|
||
* been placed on the stack in the proper order.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task,
|
||
void *p_arg,
|
||
CPU_STK *p_stk_base,
|
||
CPU_STK *p_stk_limit,
|
||
CPU_STK_SIZE stk_size,
|
||
OS_OPT opt)
|
||
{
|
||
return (p_stk_base);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TASK SWITCH HOOK
|
||
*
|
||
* Description: This function is called when a task switch is performed. This allows you to perform other
|
||
* operations during a context switch.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) Interrupts are disabled during this call.
|
||
* 2) It is assumed that the global pointer 'OSTCBHighRdyPtr' points to the TCB of the task
|
||
* that will be 'switched in' (i.e. the highest priority task) and, 'OSTCBCurPtr' points
|
||
* to the task being switched out (i.e. the preempted task).
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSTaskSwHook (void)
|
||
{
|
||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||
CPU_TS ts;
|
||
#endif
|
||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||
CPU_TS int_dis_time;
|
||
#endif
|
||
|
||
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppTaskSwHookPtr != (OS_APP_HOOK_VOID)0) {
|
||
(*OS_AppTaskSwHookPtr)();
|
||
}
|
||
#endif
|
||
|
||
#if OS_CFG_TASK_PROFILE_EN > 0u
|
||
ts = OS_TS_GET();
|
||
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
|
||
OSTCBCurPtr->CyclesDelta = ts - OSTCBCurPtr->CyclesStart;
|
||
OSTCBCurPtr->CyclesTotal += (OS_CYCLES)OSTCBCurPtr->CyclesDelta;
|
||
}
|
||
|
||
OSTCBHighRdyPtr->CyclesStart = ts;
|
||
#endif
|
||
|
||
#ifdef CPU_CFG_INT_DIS_MEAS_EN
|
||
int_dis_time = CPU_IntDisMeasMaxCurReset(); /* Keep track of per-task interrupt disable time */
|
||
if (OSTCBCurPtr->IntDisTimeMax < int_dis_time) {
|
||
OSTCBCurPtr->IntDisTimeMax = int_dis_time;
|
||
}
|
||
#endif
|
||
|
||
#if OS_CFG_SCHED_LOCK_TIME_MEAS_EN > 0u
|
||
/* Keep track of per-task scheduler lock time */
|
||
if (OSTCBCurPtr->SchedLockTimeMax < (CPU_TS)OSSchedLockTimeMaxCur) {
|
||
OSTCBCurPtr->SchedLockTimeMax = (CPU_TS)OSSchedLockTimeMaxCur;
|
||
}
|
||
OSSchedLockTimeMaxCur = (CPU_TS)0; /* Reset the per-task value */
|
||
#endif
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TICK HOOK
|
||
*
|
||
* Description: This function is called every tick.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) This function is assumed to be called from the Tick ISR.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSTimeTickHook (void)
|
||
{
|
||
#if OS_CFG_APP_HOOKS_EN > 0u
|
||
if (OS_AppTimeTickHookPtr != (OS_APP_HOOK_VOID)0) {
|
||
(*OS_AppTimeTickHookPtr)();
|
||
}
|
||
#endif
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* START HIGHEST PRIORITY TASK READY-TO-RUN
|
||
*
|
||
* Description: This function is called by OSStart() to start the highest priority task that was created
|
||
* by your application before calling OSStart().
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) OSStartHighRdy() MUST:
|
||
* a) Call OSTaskSwHook() then,
|
||
* b) Switch to the highest priority task.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSStartHighRdy (void)
|
||
{
|
||
OS_TCB_EXT_POSIX *p_tcb_ext;
|
||
sigset_t sig_set;
|
||
int signo;
|
||
|
||
|
||
OSTaskSwHook();
|
||
|
||
p_tcb_ext = (OS_TCB_EXT_POSIX *)OSTCBCurPtr->ExtPtr;
|
||
|
||
CPU_INT_DIS();
|
||
|
||
ERR_CHK(sem_post(&p_tcb_ext->Sem));
|
||
|
||
ERR_CHK(sigemptyset(&sig_set));
|
||
ERR_CHK(sigaddset(&sig_set, SIGTERM));
|
||
ERR_CHK(sigwait(&sig_set, &signo));
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* TASK LEVEL CONTEXT SWITCH
|
||
*
|
||
* Description: This function is called when a task makes a higher priority task ready-to-run.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) Upon entry,
|
||
* OSTCBCur points to the OS_TCB of the task to suspend
|
||
* OSTCBHighRdy points to the OS_TCB of the task to resume
|
||
*
|
||
* 2) OSCtxSw() MUST:
|
||
* a) Save processor registers then,
|
||
* b) Save current task's stack pointer into the current task's OS_TCB,
|
||
* c) Call OSTaskSwHook(),
|
||
* d) Set OSTCBCur = OSTCBHighRdy,
|
||
* e) Set OSPrioCur = OSPrioHighRdy,
|
||
* f) Switch to the highest priority task.
|
||
*
|
||
* pseudo-code:
|
||
* void OSCtxSw (void)
|
||
* {
|
||
* Save processor registers;
|
||
*
|
||
* OSTCBCur->OSTCBStkPtr = SP;
|
||
*
|
||
* OSTaskSwHook();
|
||
*
|
||
* OSTCBCur = OSTCBHighRdy;
|
||
* OSPrioCur = OSPrioHighRdy;
|
||
*
|
||
* Restore processor registers from (OSTCBHighRdy->OSTCBStkPtr);
|
||
* }
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSCtxSw (void)
|
||
{
|
||
OS_TCB_EXT_POSIX *p_tcb_ext_old;
|
||
OS_TCB_EXT_POSIX *p_tcb_ext_new;
|
||
int ret;
|
||
CPU_BOOLEAN detach = 0u;
|
||
|
||
|
||
OSTaskSwHook();
|
||
|
||
p_tcb_ext_new = (OS_TCB_EXT_POSIX *)OSTCBHighRdyPtr->ExtPtr;
|
||
p_tcb_ext_old = (OS_TCB_EXT_POSIX *)OSTCBCurPtr->ExtPtr;
|
||
|
||
if (OSTCBCurPtr->TaskState == OS_TASK_STATE_DEL) {
|
||
detach = 1u;
|
||
}
|
||
|
||
OSTCBCurPtr = OSTCBHighRdyPtr;
|
||
OSPrioCur = OSPrioHighRdy;
|
||
|
||
ERR_CHK(sem_post(&p_tcb_ext_new->Sem));
|
||
|
||
if (detach == 0u) {
|
||
do {
|
||
ret = sem_wait(&p_tcb_ext_old->Sem);
|
||
if (ret != 0 && errno != EINTR) {
|
||
raise(SIGABRT);
|
||
}
|
||
} while (ret != 0);
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INTERRUPT LEVEL CONTEXT SWITCH
|
||
*
|
||
* Description: This function is called by OSIntExit() to perform a context switch from an ISR.
|
||
*
|
||
* Arguments : None.
|
||
*
|
||
* Note(s) : 1) OSIntCtxSw() MUST:
|
||
* a) Call OSTaskSwHook() then,
|
||
* b) Set OSTCBCurPtr = OSTCBHighRdyPtr,
|
||
* c) Set OSPrioCur = OSPrioHighRdy,
|
||
* d) Switch to the highest priority task.
|
||
*
|
||
* 2) OSIntCurTaskSuspend() MUST be called prior to OSIntEnter().
|
||
*
|
||
* 3) OSIntCurTaskResume() MUST be called after OSIntExit() to switch to the highest
|
||
* priority task.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OSIntCtxSw (void)
|
||
{
|
||
if (OSTCBCurPtr != OSTCBHighRdyPtr) {
|
||
OSCtxSw();
|
||
}
|
||
}
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* INITIALIZE SYS TICK
|
||
*
|
||
* Description: Initialize the SysTick.
|
||
*
|
||
* Arguments : none.
|
||
*
|
||
* Note(s) : 1) This function MUST be called after OSStart() & after processor initialization.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
void OS_CPU_SysTickInit (void)
|
||
{
|
||
CPU_TmrInterruptCreate(&OSTickTmrInterrupt);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
*********************************************************************************************************
|
||
* LOCAL FUNCTIONS
|
||
*********************************************************************************************************
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void OSTimeTickHandler (void)
|
||
{
|
||
OSIntEnter();
|
||
OSTimeTick();
|
||
CPU_ISR_End();
|
||
OSIntExit();
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* OSTaskPosix()
|
||
*
|
||
* Description: This function is a generic POSIX task wrapper for uC/OS-III tasks.
|
||
*
|
||
* Arguments : p_arg Pointer to argument of the task's TCB.
|
||
*
|
||
* Note(s) : 1) Priorities of these tasks are very important.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void *OSTaskPosix (void *p_arg)
|
||
{
|
||
OS_TCB_EXT_POSIX *p_tcb_ext;
|
||
OS_TCB *p_tcb;
|
||
OS_ERR err;
|
||
|
||
|
||
p_tcb = (OS_TCB *)p_arg;
|
||
p_tcb_ext = (OS_TCB_EXT_POSIX *)p_tcb->ExtPtr;
|
||
|
||
p_tcb_ext->ProcessId = syscall(SYS_gettid);
|
||
ERR_CHK(sem_post(&p_tcb_ext->InitSem));
|
||
|
||
#ifdef OS_CFG_MSG_TRACE_EN
|
||
if (p_tcb->NamePtr != (CPU_CHAR *)0) {
|
||
printf("Task[%3.1d] '%-32s' running\n", p_tcb->Prio, p_tcb->NamePtr);
|
||
}
|
||
#endif
|
||
|
||
CPU_INT_DIS();
|
||
{
|
||
int ret = -1u;
|
||
while (ret != 0u) {
|
||
ret = sem_wait(&p_tcb_ext->Sem); /* Wait until first CTX SW. */
|
||
if ((ret != 0) && (ret != -EINTR)) {
|
||
ERR_CHK(ret);
|
||
}
|
||
}
|
||
}
|
||
CPU_INT_EN();
|
||
|
||
((void (*)(void *))p_tcb->TaskEntryAddr)(p_tcb->TaskEntryArg);
|
||
|
||
OSTaskDel(p_tcb, &err); /* Thread may exit at OSCtxSw(). */
|
||
|
||
return (0u);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* OSTaskTerminate()
|
||
*
|
||
* Description: This function handles task termination control signals.
|
||
*
|
||
* Arguments : p_task Pointer to the task information structure of the task to clear its control
|
||
* signals.
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void OSTaskTerminate (OS_TCB *p_tcb)
|
||
{
|
||
#ifdef OS_CFG_MSG_TRACE_EN
|
||
if (p_tcb->NamePtr != (CPU_CHAR *)0) {
|
||
printf("Task[%3.1d] '%-32s' deleted\n", p_tcb->Prio, p_tcb->NamePtr);
|
||
}
|
||
#endif
|
||
|
||
free(p_tcb->ExtPtr);
|
||
}
|
||
|
||
|
||
/*
|
||
*********************************************************************************************************
|
||
* OSThreadCreate()
|
||
*
|
||
* Description : Create new posix thread.
|
||
*
|
||
* Argument(s) : p_thread Pointer to preallocated thread variable.
|
||
*
|
||
* p_task Pointer to associated function.
|
||
*
|
||
* p_arg Pointer to associated function's argument.
|
||
*
|
||
* prio Thread priority.
|
||
*
|
||
* Return(s) : Thread's corresponding LWP pid.
|
||
*
|
||
* Note(s) : none.
|
||
*
|
||
*********************************************************************************************************
|
||
*/
|
||
|
||
static void OSThreadCreate (pthread_t *p_thread,
|
||
void *p_task,
|
||
void *p_arg,
|
||
int prio)
|
||
{
|
||
pthread_attr_t attr;
|
||
struct sched_param param;
|
||
|
||
|
||
if (prio < sched_get_priority_min(SCHED_RR) ||
|
||
prio > sched_get_priority_max(SCHED_RR)) {
|
||
#ifdef OS_CFG_MSG_TRACE_EN
|
||
printf("ThreadCreate(): Invalid prio arg.\n");
|
||
#endif
|
||
raise(SIGABRT);
|
||
}
|
||
|
||
ERR_CHK(pthread_attr_init(&attr));
|
||
ERR_CHK(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED));
|
||
param.__sched_priority = prio;
|
||
ERR_CHK(pthread_attr_setschedpolicy(&attr, SCHED_RR));
|
||
ERR_CHK(pthread_attr_setschedparam(&attr, ¶m));
|
||
ERR_CHK(pthread_create(p_thread, &attr, p_task, p_arg));
|
||
}
|
||
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|