Initial commit
This commit is contained in:
264
ports/linux/gnu/src/tx_thread_schedule.c
Normal file
264
ports/linux/gnu/src/tx_thread_schedule.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
||||
/* */
|
||||
/* This software is licensed under the Microsoft Software License */
|
||||
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
||||
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
||||
/* and in the root directory of this software. */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
/** */
|
||||
/** ThreadX Component */
|
||||
/** */
|
||||
/** Thread */
|
||||
/** */
|
||||
/**************************************************************************/
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#define TX_SOURCE_CODE
|
||||
|
||||
|
||||
/* Include necessary system files. */
|
||||
|
||||
#include "tx_api.h"
|
||||
#include "tx_thread.h"
|
||||
#include "tx_timer.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern sem_t _tx_linux_timer_semaphore;
|
||||
extern sem_t _tx_linux_isr_semaphore;
|
||||
extern UINT _tx_linux_timer_waiting;
|
||||
extern pthread_t _tx_linux_timer_id;
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* FUNCTION RELEASE */
|
||||
/* */
|
||||
/* _tx_thread_schedule Linux/GNU */
|
||||
/* 6.0 */
|
||||
/* AUTHOR */
|
||||
/* */
|
||||
/* William E. Lamie, Microsoft Corporation */
|
||||
/* */
|
||||
/* DESCRIPTION */
|
||||
/* */
|
||||
/* This function waits for a thread control block pointer to appear in */
|
||||
/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */
|
||||
/* in the variable, the corresponding thread is resumed. */
|
||||
/* */
|
||||
/* INPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* OUTPUT */
|
||||
/* */
|
||||
/* None */
|
||||
/* */
|
||||
/* CALLS */
|
||||
/* */
|
||||
/* tx_linux_mutex_lock */
|
||||
/* tx_linux_mutex_unlock */
|
||||
/* _tx_linux_debug_entry_insert */
|
||||
/* _tx_linux_thread_resume */
|
||||
/* tx_linux_sem_post */
|
||||
/* sem_trywait */
|
||||
/* tx_linux_sem_wait */
|
||||
/* */
|
||||
/* CALLED BY */
|
||||
/* */
|
||||
/* _tx_initialize_kernel_enter ThreadX entry function */
|
||||
/* */
|
||||
/* RELEASE HISTORY */
|
||||
/* */
|
||||
/* DATE NAME DESCRIPTION */
|
||||
/* */
|
||||
/* 05-19-2020 William E. Lamie Initial Version 6.0 */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
VOID _tx_thread_schedule(VOID)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
/* Set timer. */
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 200000;
|
||||
|
||||
/* Loop forever. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Wait for a thread to execute and all ISRs to complete. */
|
||||
while(1)
|
||||
{
|
||||
|
||||
/* Lock Linux mutex. */
|
||||
tx_linux_mutex_lock(_tx_linux_mutex);
|
||||
|
||||
/* Determine if there is a thread ready to execute AND all ISRs
|
||||
are complete. */
|
||||
if ((_tx_thread_execute_ptr != TX_NULL) && (_tx_thread_system_state == 0))
|
||||
{
|
||||
|
||||
/* Get out of this loop and schedule the thread! */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Don't waste all the processor time here in the master thread... */
|
||||
#ifdef TX_LINUX_NO_IDLE_ENABLE
|
||||
while(!sem_trywait(&_tx_linux_timer_semaphore));
|
||||
tx_linux_sem_post(&_tx_linux_timer_semaphore);
|
||||
/*nanosleep(&ts, &ts);*/
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_nsec += 200000;
|
||||
if (ts.tv_nsec > 1000000000)
|
||||
{
|
||||
ts.tv_nsec -= 1000000000;
|
||||
ts.tv_sec++;
|
||||
}
|
||||
sem_timedwait(&_tx_linux_semaphore_no_idle, &ts);
|
||||
#else
|
||||
nanosleep(&ts, &ts);
|
||||
#endif /* TX_LINUX_NO_IDLE_ENABLE */
|
||||
}
|
||||
}
|
||||
|
||||
/* Yes! We have a thread to execute. Note that the critical section is already
|
||||
active from the scheduling loop above. */
|
||||
|
||||
/* Setup the current thread pointer. */
|
||||
_tx_thread_current_ptr = _tx_thread_execute_ptr;
|
||||
|
||||
/* Increment the run count for this thread. */
|
||||
_tx_thread_current_ptr -> tx_thread_run_count++;
|
||||
|
||||
/* Setup time-slice, if present. */
|
||||
_tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice;
|
||||
|
||||
/* Determine how the thread was suspended. */
|
||||
if (_tx_thread_current_ptr -> tx_thread_linux_suspension_type)
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-resume_thread", __FILE__, __LINE__);
|
||||
|
||||
/* Pseudo interrupt suspension. The thread is not waiting on
|
||||
its run semaphore. */
|
||||
_tx_linux_thread_resume(_tx_thread_current_ptr -> tx_thread_linux_thread_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-release_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Make sure semaphore is 0. */
|
||||
while(!sem_trywait(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore));
|
||||
|
||||
/* Let the thread run again by releasing its run semaphore. */
|
||||
tx_linux_sem_post(&_tx_thread_current_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
|
||||
/* Block timer ISR. */
|
||||
if(_tx_linux_timer_waiting)
|
||||
{
|
||||
|
||||
/* It is woken up by timer ISR. */
|
||||
/* Let ThreadX thread wake up first. */
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
|
||||
/* Wake up timer ISR. */
|
||||
tx_linux_sem_post_nolock(&_tx_linux_isr_semaphore);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/* It is woken up by TX_THREAD. */
|
||||
/* Suspend timer thread and let ThreadX thread wake up first. */
|
||||
_tx_linux_thread_suspend(_tx_linux_timer_id);
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
_tx_linux_thread_resume(_tx_linux_timer_id);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlock linux mutex. */
|
||||
tx_linux_mutex_unlock(_tx_linux_mutex);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-self_suspend_sem", __FILE__, __LINE__);
|
||||
|
||||
/* Now suspend the main thread so the application thread can run. */
|
||||
tx_linux_sem_wait(&_tx_linux_semaphore);
|
||||
|
||||
/* Debug entry. */
|
||||
_tx_linux_debug_entry_insert("SCHEDULE-wake_up", __FILE__, __LINE__);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void _tx_thread_delete_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
|
||||
{
|
||||
INT linux_status;
|
||||
sem_t *threadrunsemaphore;
|
||||
pthread_t thread_id;
|
||||
struct timespec ts;
|
||||
|
||||
thread_id = thread_ptr -> tx_thread_linux_thread_id;
|
||||
threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000000;
|
||||
TX_RESTORE
|
||||
do
|
||||
{
|
||||
linux_status = pthread_cancel(thread_id);
|
||||
if(linux_status != EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_tx_linux_thread_resume(thread_id);
|
||||
tx_linux_sem_post(threadrunsemaphore);
|
||||
nanosleep(&ts, &ts);
|
||||
} while (1);
|
||||
pthread_join(thread_id, NULL);
|
||||
sem_destroy(threadrunsemaphore);
|
||||
TX_DISABLE
|
||||
}
|
||||
|
||||
void _tx_thread_reset_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture)
|
||||
{
|
||||
INT linux_status;
|
||||
sem_t *threadrunsemaphore;
|
||||
pthread_t thread_id;
|
||||
struct timespec ts;
|
||||
|
||||
thread_id = thread_ptr -> tx_thread_linux_thread_id;
|
||||
threadrunsemaphore = &(thread_ptr -> tx_thread_linux_thread_run_semaphore);
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1000000;
|
||||
TX_RESTORE
|
||||
do
|
||||
{
|
||||
linux_status = pthread_cancel(thread_id);
|
||||
if(linux_status != EAGAIN)
|
||||
{
|
||||
break;
|
||||
}
|
||||
_tx_linux_thread_resume(thread_id);
|
||||
tx_linux_sem_post(threadrunsemaphore);
|
||||
nanosleep(&ts, &ts);
|
||||
} while (1);
|
||||
pthread_join(thread_id, NULL);
|
||||
sem_destroy(threadrunsemaphore);
|
||||
TX_DISABLE
|
||||
}
|
||||
Reference in New Issue
Block a user