📄 linuxwrapper.c
字号:
#ifdef MODULE
#include <linux/kthread.h>
#include <linux/kernel.h>
#endif
#include "linuxwrapper.h"
/* ---------- Constants ----------------*/
/* #define MESSAGE_QUEUE_DEBUG */
/* #define MESSAGE_QUEUE_FULL_DEBUG */
/* #define SEMAPHORE_DEBUG */
#ifdef MODULE
#define PrintTrace(x) printk x
#else /* MODULE */
#define PrintTrace(x) printf x
#endif /* MODULE */
#define TIME_NOW_CONSTRAINTS_ON_SECONDS 86400 /* Restraints number of seconds to last day (86400s in 1 day) */
/* ---------- Types & Variables ----------------*/
/* Lockers */
#ifdef MODULE
#define LOCKER_INIT SPIN_LOCK_UNLOCKED
typedef spinlock_t locker_t;
#define locker_lock(x) spin_lock(&x)
#define locker_unlock(x) spin_unlock(&x)
#else
#define LOCKER_INIT PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t locker_t;
#define locker_lock(x) pthread_mutex_lock(&x)
#define locker_unlock(x) pthread_mutex_unlock(&x)
#endif
/* Semaphores */
typedef struct SemaphoreList_s
{
struct SemaphoreList_s * Next_p;
semaphore_t * Semaphore_p;
} SemaphoreList_t;
static SemaphoreList_t * SemaphoreList_p = NULL;
static locker_t semaphore_mutex = LOCKER_INIT;
/* Messages */
#define QUEUE_NB_MAX 20
typedef struct MessageSend_s
{
struct MessageSend_s * Next_p;
void * Message_p;
} MessageSend_t;
typedef struct
{
void * Memory_p;
BOOL * Used_p;
MessageSend_t * Pending_p;
size_t ElementSize;
unsigned int NoElements;
} MessageElem_t;
typedef struct MessageQueueList_s
{
struct MessageQueueList_s * Next_p;
message_queue_t * MessageQueue_p;
void * Memory_p;
} MessageQueueList_t;
#if defined(MESSAGE_QUEUE_DEBUG) || defined(MESSAGE_QUEUE_FULL_DEBUG)
#ifdef MODULE
#define PrintMessageQ_Debug(x) printk x
#else
#define PrintMessageQ_Debug(x) printf x
#endif
#ifdef MESSAGE_QUEUE_FULL_DEBUG
#ifdef MODULE
#define PrintMessageQ_FullDebug(x) printk x
#else
#define PrintMessageQ_FullDebug(x) printf x
#endif
#else
#define PrintMessageQ_FullDebug(x)
#endif
#else
#define PrintMessageQ_Debug(x)
#define PrintMessageQ_FullDebug(x)
#endif
static MessageElem_t MessageArray[QUEUE_NB_MAX];
static BOOL MessageInitDone = FALSE;
static MessageQueueList_t * MessageQueueList_p = NULL;
static locker_t message_mutex = LOCKER_INIT;
/* task_lock/task_unlock */
#if !defined(MODULE)
static pthread_mutex_t compat_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif /* !MODULE */
/* Clocks */
#if !defined(MODULE)
/* Stores ClockTicks per second to avoid reread it too many times */
static int ClkPerSec = 0; /* Clock ticks per seconds (typically 15625) */
#endif /* !MODULE */
/* Random number */
#ifdef MODULE
unsigned long x=0;
#endif
/* Interrupt locks like variables */
#ifdef MODULE
U32 SpinIntFlagsIndex =0 ;
unsigned long SpinIntFlagsTab[SPIN_LOCK_DEPTH_MAX];
spinlock_t SpinIntLock = SPIN_LOCK_UNLOCKED;
#endif
#ifdef DEBUG_LOCK
IntLockVar_t IntLockInVar[INT_LOCK_INDEX_MAX];
IntLockVar_t IntLockOutVar[INT_LOCK_INDEX_MAX];
U32 IntLockPrint = 0;
#if defined(MODULE)
U32 IntLockInIndex = 0;
U32 IntLockOutIndex = 0;
unsigned long SpinIntFlags;
pid_t SpinIntPid;
int IntLockI,IntLockJ;
int IntLockPrintSignal = 0;
#endif
#endif
/* ---------- Functions ----------------*/
/* ******************************************** */
/* Input functions */
/* In order to be coherent after each call */
/* the terminal will return into blocking echoed state */
/* ******************************************** */
#if !defined(MODULE)
/*
* STTBX_InputChar
*/
void STTBX_InputChar(char * result)
{
struct termio term;
/* unblocking the teminal */
ioctl(0,TCGETA,(void *)&term);
term.c_lflag &= ~ICANON;
term.c_lflag &= ~ECHO;
ioctl(0,TCSETAW,(void *)&term);
/* getting the char */
*result= (char) getchar();
/* blocking the teminal */
ioctl(0,TCGETA,(void *)&term);
term.c_lflag |= ICANON;
term.c_lflag |= ECHO;
ioctl(0,TCSETAW,(void *)&term);
return ;
}
/*
* STTBX_InputPollChar
*/
BOOL STTBX_InputPollChar(char* buffer)
{
int ret=FALSE, size;
struct pollfd p;
struct termio term, term_old;
p.fd = 0;
p.events = POLLIN;
ioctl(0,TCGETA,(void *)&term);
term_old = term;
term.c_lflag &= ~ICANON;
term.c_lflag &= ~ECHO;
ioctl(0,TCSETAW,(void *)&term);
ret = poll(&p, 1, 0);
if (ret > 0) {
if (p.revents == POLLIN) {
size = read(0, buffer, 1);
ret=TRUE;
}
}
tcflush( 0, TCIOFLUSH);
ioctl(0,TCSETAW,(void *)&term_old);
return (ret);
}
/*
* STTBX_InputStr
*/
int STTBX_InputStr( char* answer, int size )
{
int result = 0;
while (!result) /* NS# needed to mimic OS21 behaviour (null string not expected) */
{
if (fgets( answer, size, stdin)) /* NS# use fgets instead of sscanf -- more secure */
{
char *p = strstr( answer, "\n");
if (p)
*p = 0; /* NS# suppress first CRLF to mimic OS21 behaviour */
result = strlen( answer); /* NS# return strlen to conform to STTBX_InputStr API */
}
}
return result;
}
#endif
/*
* STTBX_Report_arg
*/
void STTBX_Report_arg( const STTBX_ReportLevel_t ReportLevel, const char *const Format_p, ...)
{
va_list argument;
char line[256];
switch (ReportLevel)
{
case STTBX_REPORT_LEVEL_FATAL:
snprintf( line, sizeof( line), " Fatal> ");
break;
case STTBX_REPORT_LEVEL_ERROR:
snprintf( line, sizeof( line), " Error> ");
break;
case STTBX_REPORT_LEVEL_WARNING:
snprintf( line, sizeof( line), " Warning> ");
break;
case STTBX_REPORT_LEVEL_ENTER_LEAVE_FN:
snprintf( line, sizeof( line), "InOut Fn> ");
break;
case STTBX_REPORT_LEVEL_INFO:
snprintf( line, sizeof( line), " Info> ");
break;
case STTBX_REPORT_LEVEL_USER1:
snprintf( line, sizeof( line), " User1> ");
break;
case STTBX_REPORT_LEVEL_USER2:
snprintf( line, sizeof( line), " User2> ");
break;
default:
snprintf( line, sizeof( line), " ????? > ");
break;
}
PrintTrace(( "%s", line));
va_start( argument, Format_p);
vsnprintf( line, sizeof( line), Format_p, argument);
va_end( argument);
PrintTrace(( "%s", line));
PrintTrace(( "\n"));
}
/****************************************************/
/* SEMAPHORES */
/****************************************************/
/* ************************************************** */
/*
* semaphore_init_fifo
*/
/* ************************************************** */
int semaphore_init_fifo(semaphore_t *sem, int count)
{
#ifdef MODULE
init_waitqueue_head(&(sem->wait_queue));
atomic_set(&sem->Count, (1-count));
return 0;
#else
pthread_mutexattr_t MutAttr;
int ret;
#ifdef SEMAPHORE_DEBUG
PrintTrace(("sem_if:%x\n",(unsigned long) sem));
#endif
pthread_mutexattr_init(&MutAttr);
/* This is a WA to get much better response time (19000 us vs 90 us) */
/* Should be : ret = pthread_mutexattr_settype(&MutAttr, PTHREAD_MUTEX_ADAPTIVE_NP);*/
ret = pthread_mutexattr_settype(&MutAttr, PTHREAD_MUTEX_TIMED_NP);
if (ret == 0)
{
ret = pthread_mutex_init(sem, &MutAttr);
}
if (ret == 0)
{
if (count == 0)
{
pthread_mutex_lock(sem);
}
else
{
if (count <= 1)
{
pthread_mutex_unlock(sem);
sched_yield();
}
else
{
ret = 0xFF;
}
}
}
pthread_mutexattr_destroy(&MutAttr);
if (ret != 0)
{
PrintTrace(("semaphore_init_fifo creation problem 0x%x (%d)!!!!!\n\n", (U32)sem, ret));
}
return (ret == 0 ? 0 : -1);
#endif
}
/* ************************************************** */
/*
* semaphore_init_fifo_timeout
*/
/* ************************************************** */
int semaphore_init_fifo_timeout(semaphore_t *sem, int count)
{
#ifdef MODULE
init_waitqueue_head(&(sem->wait_queue));
atomic_set(&sem->Count, (1-count));
return 0;
#else
pthread_mutexattr_t MutAttr;
int ret;
#ifdef SEMAPHORE_DEBUG
PrintTrace(("sem_ift:%x\n",(unsigned long) sem));
#endif
pthread_mutexattr_init(&MutAttr);
ret = pthread_mutexattr_settype(&MutAttr, PTHREAD_MUTEX_TIMED_NP);
if (ret == 0)
{
ret = pthread_mutex_init(sem, &MutAttr);
}
if (ret == 0)
{
if (count == 0)
{
pthread_mutex_lock(sem);
}
else
{
if (count <= 1)
{
pthread_mutex_unlock(sem);
sched_yield();
}
else
{
ret = 0xFF;
}
}
}
pthread_mutexattr_destroy(&MutAttr);
if (ret != 0)
{
PrintTrace(("semaphore_init_fifo_timeout creation problem 0x%x (%d)!!!!!\n\n", (U32) sem, ret));
}
return (ret == 0 ? 0 : -1);
#endif /* MODULE */
}
/* ************************************************** */
/*
* semaphore_init_priority
*
* The next function should ensure that sem_wait will place the thread at top priority
* but is not the case in Linux. Putting it in kernel with waiting task ???
*/
/* ************************************************** */
int semaphore_init_priority(semaphore_t *sem, int count)
{
/* Not managed yet, emulate it !!! */
return (semaphore_init_fifo(sem, count) == 0 ? 0 : -1);
}
/* ************************************************** */
/*
* semaphore_create_fifo
*/
/* ************************************************** */
semaphore_t * semaphore_create_fifo(int count)
{
return( semaphore_create_fifo_timeout(count) );
}
/* ************************************************** */
/*
* semaphore_create_fifo_timeout
*/
/* ************************************************** */
semaphore_t * semaphore_create_fifo_timeout(int count)
{
SemaphoreList_t * Current_p;
SemaphoreList_t * New_p;
semaphore_t * sem_p = NULL;
if ((New_p = memory_allocate(NULL, sizeof(SemaphoreList_t))) != NULL)
{
if ((New_p->Semaphore_p = memory_allocate(NULL, sizeof(semaphore_t))) == NULL)
{
/* Memory allocation pb, deallocate list element */
memory_deallocate(NULL, New_p);
New_p = NULL;
}
}
if (New_p != NULL)
{
/* At this stage, we know that all allocations have been correctly done */
if (semaphore_init_fifo_timeout(New_p->Semaphore_p, count) == 0)
{
New_p->Next_p = NULL;
locker_lock(semaphore_mutex);
Current_p = SemaphoreList_p;
if (Current_p != NULL)
{
while (Current_p->Next_p != NULL)
Current_p = Current_p->Next_p;
Current_p->Next_p = New_p;
}
else
{
SemaphoreList_p = New_p;
}
locker_unlock(semaphore_mutex);
sem_p = New_p->Semaphore_p;
}
else
{
memory_deallocate(NULL, New_p->Semaphore_p);
memory_deallocate(NULL, New_p);
PrintTrace(("COMPAT: semaphore_create_fifo, semaphore init problem !!!\n"));
}
}
else
{
PrintTrace(("COMPAT: semaphore_create_fifo, no memory !!!\n"));
}
#ifdef SEMAPHORE_DEBUG
PrintTrace(("sem_cfto:%x\n",(unsigned long) sem_p));
#endif
/* NULL if Semaphore Creation Problem, sem pointer otherwise */
return(sem_p);
}
/* ************************************************** */
/*
* semaphore_create_priority
*
* The next function should ensure that sem_wait will place the thread at top priority
* but is not the case in Linux. Putting it in kernel with waiting task ???
*/
/* ************************************************** */
semaphore_t * semaphore_create_priority(int count)
{
/* Not managed yet, emulate it !!! */
return ( semaphore_create_fifo_timeout(count) );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -