📄 thread.h
字号:
else \
{ \
krnlData->name##MutexInitialised = TRUE; \
status = CRYPT_OK; \
} \
}
#define MUTEX_DESTROY( name ) \
if( krnlData->name##MutexInitialised ) \
{ \
xSemaphoreTakeRecursive( krnlData->name##Mutex, \
MUTEX_WAIT_TIME ); \
xSemaphoreGiveRecursive( krnlData->name##Mutex ); \
krnlData->name##MutexInitialised = FALSE; \
}
#define MUTEX_LOCK( name ) \
xSemaphoreTakeRecursive( krnlData->name##Mutex, \
MUTEX_WAIT_TIME )
#define MUTEX_UNLOCK( name ) \
xSemaphoreGiveRecursive( krnlData->name##Mutex )
/* Thread management functions. FreeRTOS threads are generally sensible and
don't require user management of stack space as with many other
minimalist embedded OSes, although they do have the peculiarity that the
stack size is given as a "depth" rather than an actual stack size, where
the total size is defined by "depth" x "width" (= machine word size) */
#define STACK_DEPTH 8192
#define THREADFUNC_DEFINE( name, arg ) void name( void *arg )
#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \
{ \
portBASE_TYPE result; \
\
syncHandle = xSemaphoreCreateMutex(); \
xSemaphoreTake( syncHandle, MUTEX_WAIT_TIME ); \
result = xTaskCreate( function, "clibTask", STACK_DEPTH, \
arg, tskIDLE_PRIORITY, &threadHandle ); \
if( result != pdPASS ) \
status = CRYPT_ERROR; \
else \
status = CRYPT_OK; \
}
#define THREAD_EXIT( sync ) xSemaphoreGive( &sync )
#define THREAD_INITIALISER 0
#define THREAD_SAME( thread1, thread2 ) ( ( thread1 ) == ( thread2 ) )
#define THREAD_SELF() xTaskGetCurrentTaskHandle()
#define THREAD_SLEEP( ms ) vTaskDelay( ( ms ) / portTICK_RATE_MS )
#define THREAD_YIELD() taskYIELD()
#define THREAD_WAIT( sync, status ) \
if( xSemaphoreTake( sync, MUTEX_WAIT_TIME ) != pdTRUE ) \
status = CRYPT_ERROR
#define THREAD_CLOSE( sync ) vTaskDelete( &sync )
/****************************************************************************
* *
* uC/OS-II *
* *
****************************************************************************/
#elif defined( __UCOS__ )
/* uC/OS-II has a pure priority-based scheduler (no round-robin scheduling)
and makes a task's priority do double duty as the task ID, which means
that it's unlikely it'll ever get round-robin scheduling without a
major overhaul of the API. Because of this, a background task started
inside cryptlib for initialisation or keygen will either never run or
always run depending on the priority it's started with, thus making it
equivalent to performing the operation synchronously. This means that
there's no point in using cryptlib-internal tasks, so they're disabled
unless the following is commented out. Note that cryptlib is still
thread-(task)-safe, it just won't use internal tasks for asynchronous
ops, because uC/OS-II's scheduling will make the synchronous */
/* #define UCOS_USE_TASKS */
/* Most systems handle priority-inversion-avoidance automatically, however
for some reason in uC/OS-II this has to be managed manually by the user.
This is done by specifying the priority-inherit priority level that a
low-priority task is raised to when a high-priority task attempts to
acquire a mutex that the low-priority task is currently holding. This
has to be higher than the priority of any of the tasks that will try
to acquire the mutex, as well as being different from the task ID/
priority of any task (another problem caused by the task ID == priority
issue). The following is a sample value that'll need to be adjusted
based on usage by the calling application */
#define UCOS_PIP 10
/* Because of the strict priority scheduling, we have to specify the task
priority (which then also becomes the task ID) when we create the task.
The following is a sample task ID, which must be less than UCOS_PIP */
#define UCOS_TASKID 20
#include <includes.h>
/* Object handles */
#define THREAD_HANDLE INT8U
#define MUTEX_HANDLE OS_EVENT *
/* Mutex management functions. uC/OS-II mutexes aren't re-entrant (although
this is never mentioned explicitly in any documentation the description
of how mutexes work in App.Note 1002 makes it clear that they're not), we
use the standard trylock()-style mechanism to work around this */
#define MUTEX_DECLARE_STORAGE( name ) \
OS_EVENT *name##Mutex; \
BOOLEAN name##MutexInitialised; \
INT8U name##MutexOwner; \
int name##MutexLockcount
#define MUTEX_CREATE( name, status ) \
status = CRYPT_OK; \
if( !krnlData->name##MutexInitialised ) \
{ \
INT8U err; \
\
krnlData->name##Mutex = OSMutexCreate( UCOS_PIP, &err ); \
if( err == OS_NO_ERR ) \
krnlData->name##MutexInitialised = TRUE; \
else \
status = CRYPT_ERROR; \
}
#define MUTEX_DESTROY( name ) \
if( krnlData->name##MutexInitialised ) \
{ \
INT8U err; \
\
OSMutexPend( krnlData->name##Mutex, 0, &err ); \
OSMutexPost( krnlData->name##Mutex ); \
OSMutexDel( krnlData->name##Mutex, OS_DEL_ALWAYS, &err ); \
krnlData->name##MutexInitialised = FALSE; \
}
#define MUTEX_LOCK( name ) \
{ \
INT8U err; \
\
if( OSMutexAcept( krnlData->name##Mutex, &err ) == 0 ) \
{ \
if( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \
OSMutexPend( krnlData->name##Mutex, 0, &err ); \
else \
krnlData->name##MutexLockcount++; \
} \
krnlData->name##MutexOwner = THREAD_SELF();
#define MUTEX_UNLOCK( name ) \
if( krnlData->name##MutexLockcount > 0 ) \
krnlData->name##MutexLockcount--; \
else \
{ \
krnlData->name##MutexOwner = THREAD_INITIALISER; \
OSMutexPost( krnlData->name##Mutex ); \
}
/* Thread management functions. Because of the strict priority-based
scheduling there's no way to perform a yield, the best that we can do
is sleep for 1ms, which is better than performing a busy wait.
Thread sleep times are measured in implementation-specific ticks rather
than ms, so we have to scale the time based on the OS_TICKS_PER_SEC
value */
#define THREADFUNC_DEFINE( name, arg ) void name( void *arg )
#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \
{ \
OS_STK *threadData = malloc( 4096 ); \
\
syncHandle = OSSemCreate( 0 ); \
if( OSTaskCreate( function, arg, ( BYTE * ) threadData + 4095, \
UCOS_TASKID ) != OS_NO_ERR ) \
{ \
free( threadData ); \
status = CRYPT_ERROR; \
} \
else \
status = CRYPT_OK; \
}
#define THREAD_EXIT( sync ) OSSemPost( sync ); \
OSTaskDel( OS_PRIO_SELF )
#define THREAD_INITIALISER 0
#define THREAD_SAME( thread1, thread2 ) ( ( thread1 ) == ( thread2 ) )
#define THREAD_SELF() threadSelf()
#if OS_TICKS_PER_SEC >= 1000
#define THREAD_SLEEP( ms ) OSTimeDelay( ( OS_TICKS_PER_SEC / 1000 ) * ms )
#else
#define THREAD_SLEEP( ms ) OSTimeDelay( max( ( ms * OS_TICKS_PER_SEC ) / 1000, 1 ) )
#endif /* OS_TICKS_PER_SEC time scaling */
#define THREAD_YIELD() THREAD_SLEEP( 1 )
#define THREAD_WAIT( sync, status ) \
{ \
INT8U err; \
\
OSSemPend( sync, 0, &err ); \
if( err != OS_NO_ERR ) \
status = CRYPT_ERROR; \
OSSemDel( sync ); \
}
#define THREAD_CLOSE( sync )
/* uC/OS-II doesn't have a thread-self function, but allows general task
info to be queried. Because of this we provide a wrapper that returns
the task ID as its return value */
INT8U threadSelf( void );
/* Because of the inability to do round-robin scheduling, we no-op out the
use of internal threads/tasks. Note that cryptlib itself is still thread-
safe, it just can't do its init or keygen in an internal background
thread */
#ifndef UCOS_USE_TASKS
#undef THREAD_CREATE
#undef THREAD_EXIT
#undef THREAD_CLOSE
#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \
status = CRYPT_ERROR
#define THREAD_EXIT( sync )
#define THREAD_CLOSE( sync )
#endif /* !UCOS_USE_TASKS */
/****************************************************************************
* *
* IBM 4758 *
* *
****************************************************************************/
#elif defined( __IBM4758__ )
#include <cpqlib.h>
/* Object handles */
#define THREAD_HANDLE long
#define MUTEX_HANDLE long
/* Mutex management functions */
#define MUTEX_DECLARE_STORAGE( name ) \
long name##Semaphore; \
BOOLEAN name##SemaphoreInitialised
#define MUTEX_CREATE( name, status ) \
status = CRYPT_OK; \
if( !krnlData->name##SemaphoreInitialised ) \
{ \
if( CPCreateSerSem( NULL, 0, 0, \
&krnlData->name##Semaphore ) == 0 ) \
krnlData->name##SemaphoreInitialised = TRUE; \
else \
status = CRYPT_ERROR; \
}
#define MUTEX_DESTROY( name ) \
if( krnlData->name##SemaphoreInitialised ) \
{ \
CPSemClaim( krnlData->name##Semaphore, SVCWAITFOREVER ); \
CPSemRelease( krnlData->name##Semaphore ); \
CPDelete( krnlData->name##Semaphore, 0 ); \
krnlData->name##SemaphoreInitialised = FALSE; \
}
#define MUTEX_LOCK( name ) \
CPSemClaim( krnlData->name##Semaphore, SVCWAITFOREVER )
#define MUTEX_UNLOCK( name ) \
CPSemRelease( krnlData->name##Semaphore )
/* Thread management functions. CP/Q doesn't use threads but only supports
CP/Q tasks. These function in a somewhat peculiar manner, so this
facility isn't currently used */
/****************************************************************************
* *
* uITRON *
* *
****************************************************************************/
#elif defined( __ITRON__ )
/* In the following includes, kernel.h is the uITRON kernel.h, not the
cryptlib one */
#include <itron.h>
#include <kernel.h>
/* Object handles */
#define THREAD_HANDLE ID
#define MUTEX_HANDLE ID
/* Mutex management functions. We could use either semaphores or mutexes
for this, semaphores are supported under uITRON 3.0 but since we're
using automatic assignment of handles (which requires uITRON 4.0) we may
as well use mutexes */
#define MUTEX_DECLARE_STORAGE( name ) \
ID name##Mutex; \
BOOLEAN name##MutexInitialised; \
ID name##MutexOwner; \
int name##MutexLockcount
#define MUTEX_CREATE( name, status ) \
status = CRYPT_OK; \
if( !krnlData->name##MutexInitialised ) \
{ \
static const T_CMTX pk_cmtx = { 0, 0 }; \
\
if( ( krnlData->name##Mutex = \
acre_mtx( ( T_CMTX * ) &pk_cmtx ) ) < E_OK ) \
status = CRYPT_ERROR; \
else \
krnlData->name##MutexInitialised = TRUE; \
}
#define MUTEX_DESTROY( name ) \
if( krnlData->name##MutexInitialised ) \
{ \
loc_mtx( krnlData->name##Mutex ); \
unl_mtx( krnlData->name##Mutex ); \
del_mtx( krnlData->name##Mutex ); \
krnlData->name##MutexInitialised = FALSE; \
}
#define MUTEX_LOCK( name ) \
if( ploc_mtx( krnlData->name##Mutex ) == E_ILUSE ) \
{ \
if( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \
loc_mtx( krnlData->name##Mutex ); \
else \
krnlData->name##MutexLockcount++; \
} \
krnlData->name##MutexOwner = threadSelf();
#define MUTEX_UNLOCK( name ) \
if( krnlData->name##MutexLockcount > 0 ) \
krnlData->name##MutexLockcount--; \
else \
{ \
krnlData->name##MutexOwner = THREAD_INITIALISER; \
unl_mtx( krnlData->name##Mutex ); \
}
/* Thread management functions. The attributes for task creation are:
TA_HLNG | TA_ACT -- C interface, create task in the active rather
than suspended state (otherwise we'd have to use
act_tsk() to activate it a la BeOS).
arg -- Task extended info.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -