⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.h

📁 cryptlib安全工具包
💻 H
📖 第 1 页 / 共 5 页
字号:
									status = CRYPT_ERROR; \
								else \
									rtems_semaphore_release( sync ); \
								rtems_semaphore_delete( sync )
#define THREAD_CLOSE( sync )

/* The RTEMS thread-self function returns the task ID via a reference
   parameter, because of this we have to provide a wrapper that returns it
   as a return value */

rtems_id threadSelf( void );

/****************************************************************************
*																			*
*									ThreadX									*
*																			*
****************************************************************************/

#elif defined( __ThreadX__ )

/* To use resource-management wrappers for the ThreadX thread functions,
   undefine the following */

/* #define THREADX_THREAD_WRAPPERS */

#include <tx_api.h>

/* Object handles */

#define THREAD_HANDLE			TX_THREAD
#define MUTEX_HANDLE			TX_MUTEX

/* Mutex management functions.  ThreadX mutexes are reentrant so we don't 
   have to hand-assemble reentrant mutexes as for many other OSes.  All 
   ThreadX objects have names (presumably for debugging) but what the 
   requirements for these are aren't documented so we just use a dummy name 
   for everything.  Since we don't care whether the threads waiting on the 
   mutex get woken up in priority order, we use TX_NO_INHERIT to ignore 
   priority inheritance */

#define MUTEX_DECLARE_STORAGE( name ) \
		TX_MUTEX name##Mutex; \
		BOOLEAN name##MutexInitialised
#define MUTEX_CREATE( name, status ) \
		status = CRYPT_OK; \
		if( !krnlData->name##MutexInitialised ) \
			{ \
			if( tx_mutex_create( &krnlData->name##Mutex, "name", \
								 TX_NO_INHERIT ) == TX_SUCCESS ) \
				krnlData->name##MutexInitialised = TRUE; \
			else \
				status = CRYPT_ERROR; \
			}
#define MUTEX_DESTROY( name ) \
		if( krnlData->name##MutexInitialised ) \
			{ \
			tx_mutex_get( &krnlData->name##Mutex, TX_WAIT_FOREVER ); \
			tx_mutex_put( &krnlData->name##Mutex ); \
			tx_mutex_delete( &krnlData->name##Mutex ); \
			krnlData->name##MutexInitialised = FALSE; \
			}
#define MUTEX_LOCK( name ) \
		tx_mutex_get( &krnlData->name##Mutex, TX_WAIT_FOREVER )
#define MUTEX_UNLOCK( name ) \
		tx_mutex_put( &krnlData->name##Mutex )

/* Thread management functions.  ThreadX threads require that the user 
   allocate the stack space for them, unlike virtually every other embedded 
   OS, which make this at most a rarely-used option.  To handle this, we use 
   our own wrappers.

   We give the thread a mid-range priority value and preemption threshold of
   15 (from a range of 0 = highest ... 31 = lowest) and a 50-tick timeslice.
   The timeslice value is HAL-dependent so it's not really possible to tell 
   how much runtime this will actually give the thread, anyone using cryptlib
   with ThreadX will need to set an appropriate value for their HAL.  The
   same goes for the sleep time, the code assumes that 1 tick = 10ms so we
   divide by 10 to convert ms to ticks */

#define THREADFUNC_DEFINE( name, arg )	VOID name( ULONG arg )
#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \
			{ \
			BYTE *threadData = malloc( 16384 ); \
			\
			tx_semaphore_create( &syncHandle, "name", 1 ); \
			if( tx_thread_create( &threadHandle, "name", function, \
								  ( ULONG ) arg, threadData, 16384, \
								  15, 50, 15, TX_AUTO_START ) != TX_SUCCESS ) \
				{ \
				free( threadData ); \
				status = CRYPT_ERROR; \
				} \
			else \
				status = CRYPT_OK; \
			}
#define THREAD_EXIT( sync )		tx_semaphore_put( &sync ); \
								tx_thread_terminate( tx_thread_identify() )
#define THREAD_INITIALISER		0
#define THREAD_SAME( thread1, thread2 )	( ( thread1 ) == ( thread2 ) )
#define THREAD_SELF()			tx_thread_identify()
#define THREAD_SLEEP( ms )		tx_thread_sleep( ( ms ) / 10 )
#define THREAD_YIELD()			tx_thread_relinquish()
#define THREAD_WAIT( sync, status ) \
								if( !tx_semaphore_get( &sync, TX_WAIT_FOREVER ) ) \
									status = CRYPT_ERROR; \
								tx_semaphore_delete( &sync )
#define THREAD_CLOSE( sync )	tx_thread_delete( &sync )

/* Because of the problems with resource management of ThreadX threads and
   related metadata we no-op them out unless we're using wrappers by 
   ensuring that any attempt to spawn a thread inside cryptlib fails,
   falling back to the non-threaded alternative.  Note that cryptlib itself
   is still thread-safe, it just can't do its init or keygen in an internal
   background thread */

#ifndef THREADX_THREAD_WRAPPERS
  #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 /* !THREADX_THREAD_WRAPPERS */

/****************************************************************************
*																			*
*								Unix/MVS/XMK								*
*																			*
****************************************************************************/

#elif ( defined( __UNIX__ ) || defined( __XMK__ ) ) && defined( USE_THREADS )

/* Under OSF/1 pthread.h includes c_asm.h which contains a declaration

	long asm( const char *,...);

   that conflicts with the gcc asm keyword.  This asm stuff is only used
   when inline asm alternatives to the Posix threading functions are enabled,
   which isn't done by default so in theory we could also fix this by
   defining asm to something else before including pthread.h, but it's safer
   to just disable inclusion of c_asm.h by pre-defining the guard define.
   This will result in a more useful warning if for some reason inline
   threading functions with asm are enabled */

#if defined( __osf__ ) || defined( __alpha__ )
  #define __C_ASM_H
#endif /* Alpha */

/* Linux threads are a particularly peculiar implementation, being based on
   the Linux clone() system call, which clones an entire process and uses
   a special "manager thread" to provide the appearance of a multithreaded
   application.  This threads == processes model produces very strange
   effects such as the appearance of a mass of (pseudo-)processes, each with
   their own PID, that appear to consume more memory than is physically
   present.  Another problem was that signals, which are done on a per-PID
   basis and should have been consistent across all threads in the process,
   were instead only delivered to one thread/pseudo-process and never got
   any further.  The clone()-based hack results in non-conformance with the
   pthreads spec as well as significant scalability and performance issues.

   The problem was finally (mostly) fixed with Ingo Molnar's native Posix
   thread library (NPTL) patches to the 2.5 development) kernel, which
   still retains the strange clone()-based threading mechanism but provides
   enough kludges to other parts of the kernel that it's not longer so
   obvious.  For example the clone() call has been optimised to make it
   more lightweight, Molnar's O(1) scheduler reduces the overhead of the
   process-per-thread mechanism, fast userspace mutexes eliminate the need
   for interthread signalling to implement locking, and most importantly the
   kernel identification of all threads has been collapsed to a single PID,
   eliminating the confusion caused by the cloned pseudo-processes */

#include <pthread.h>
#include <sys/time.h>
#ifdef __XMK__
  #include <sys/process.h>
  #include <sys/timer.h>
#endif /* Xilinx XMK */

/* Object handles */

#define THREAD_HANDLE			pthread_t
#define MUTEX_HANDLE			pthread_t

/* Mutex management functions.  Most Unix mutex implementations are non-
   re-entrant, which means that re-locking a mutex leads to deadlock
   (charming).  Some implementations can fix this by setting a mutex
   attribute to ensure that it doesn't deadlock using:

	pthread_mutexattr_settype( attr, PTHREAD_MUTEX_RECURSIVE );

   or:

	pthread_mutex_setrecursive();

   but this isn't universal.  To fix the problem, we implement our own
   re-entrant mutexes on top of the Posix ones.

   Due to the complexity of the locking process using pthreads' (usually)
   non-reentrant mutexes, we don't try and lock+unlock the mutex before we
   destroy it.  This isn't a major issue since it's just a safety precaution,
   the kernel should have forced any remaining threads to exit by the time
   the shutdown occurs anyway */

#define MUTEX_DECLARE_STORAGE( name ) \
		pthread_mutex_t name##Mutex; \
		BOOLEAN name##MutexInitialised; \
		pthread_t name##MutexOwner; \
		int name##MutexLockcount
#define MUTEX_CREATE( name, status ) \
		status = CRYPT_OK; \
		if( !krnlData->name##MutexInitialised ) \
			{ \
			if( pthread_mutex_init( &krnlData->name##Mutex, \
									NULL ) == 0 ) \
				krnlData->name##MutexInitialised = TRUE; \
			else \
				status = CRYPT_ERROR; \
			}
#define MUTEX_DESTROY( name ) \
		if( krnlData->name##MutexInitialised ) \
			{ \
			pthread_mutex_destroy( &krnlData->name##Mutex ); \
			krnlData->name##MutexInitialised = FALSE; \
			}
#define MUTEX_LOCK( name ) \
		if( pthread_mutex_trylock( &krnlData->name##Mutex ) ) \
			{ \
			if( !THREAD_SAME( krnlData->name##MutexOwner, THREAD_SELF() ) ) \
				pthread_mutex_lock( &krnlData->name##Mutex ); \
			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; \
			pthread_mutex_unlock( &krnlData->name##Mutex ); \
			}

/* Instead of the DIY recursive mutexes above it's also possible to use OS
   recursive mutexes if they're available.  Unfortunately there's no easy
   way to reliably test for these (they're often provided as _NP variants,
   or require obscure preprocessor trickery to enable them), and even if
   they're present they may not be supported (pthread_mutexattr_settype()
   returns an error), or the implementation may be flaky (some Linux 
   threading implementations).  Because of this the following use of 
   recursive mutexes needs to be manually enabled.  Note that on most 
   systems that use gcc it's necessary to define either _XOPEN_SOURCE=500 or 
   _GNU_SOURCE to get PTHREAD_MUTEX_RECURSIVE, otherwise only 
   PTHREAD_MUTEX_RECURSIVE_NP is defined, i.e. the standard behaviour of gcc 
   is to be nonstandard */

#if 0

#undef MUTEX_CREATE
#undef MUTEX_LOCK
#undef MUTEX_UNLOCK
#define MUTEX_CREATE( name, status ) \
		if( !krnlData->name##MutexInitialised ) \
			{ \
			pthread_mutexattr_t mutexAttr;\
			\
			pthread_mutexattr_init( &mutexAttr );\
			pthread_mutexattr_settype( &mutexAttr, \
									   PTHREAD_MUTEX_RECURSIVE ); \
			if( pthread_mutex_init( &krnlData->name##Mutex, \
									&mutexAttr ) == 0 ) \
				{ \
				krnlData->name##MutexInitialised = TRUE; \
				status = CRYPT_OK; \
				} \
			else \
				status = CRYPT_ERROR; \
			pthread_mutexattr_destroy ( &mutexAttr );\
			}
#define MUTEX_LOCK( name )		pthread_mutex_lock( &krnlData->name##Mutex )
#define MUTEX_UNLOCK( name )	pthread_mutex_unlock( &krnlData->name##Mutex )

#endif /* 0 */

/* Putting a thread to sleep for a number of milliseconds can be done with
   select() because it should be a thread-safe one in the presence of
   pthreads.  In addition there are some system-specific quirks, these are
   handled by re-defining the macros below in a system-specific manner
   further on.

   Yielding a thread's timeslice gets rather complex due to a confusion of
   non-portable "portable" Posix functions.  Initially there was
   pthread_yield() from draft 4 of the Posix thread standard in 1990,
   popularised in the DCE threading code and picked up by a number of other
   implementations.  At about that time the realtime (1003.1b) and thread
   (1003.1c) standardisation was proceeding independently, with neither side
   knowing which one would make it to standards status first.  As it turned
   out this was 1003.1b with sched_yield().  When the 1003.1c folks were
   looking for every place where the text said "process" but should say
   "thread" once 1003.1c was in effect, they noticed that sched_yield() and
   pthread_yield() were now identical.  Since sched_yield() was already in
   the standard, there was no need for pthread_yield() so it was removed.
   However, some older implementations still do pthread_yield() and some
   (also older) implementations use sched_yield() to yield the processes'
   timeslice rather than the thread's timeslice, further complicated by the
   fact that some implementations like PHUX 10.x/11.x have buggy manpages
   that claim sched_yield() is per-process when in fact it's per-thread
   (PHUX 10.x still had pthread_yield() while 11.x only has sched_yield()).
   The whole is further confused by the fact that in some implementations,
   threads are processes (sort of, e.g. Linux's clone()'d threads and Sun
   LWPs).  In addition Sun have their own thr_yield which is part of their
   UI threads interface and that you have to fall back to occasionally.

   Because of this mess, we try for pthread_yield() if possible (since that
   definitely yields the thread's timeslice), fall back to sched_yield() if
   necessary, and add a special workaround for Sun systems.

   "Posix is portable in the sense that you can use a forklift to move the
    printed volumes around" */

#define THREADFUNC_DEFINE( name, arg )	void *name( void *arg )
#define THREAD_CREATE( function, arg, threadHandle, syncHandle, status ) \
			{ \
			status = pthread_create( &threadHandle, NULL, function, arg ) ? \
					 CRYPT_ERROR : CRYPT_OK; \
			syncHandle = threadHandle; \
			}
#define THREAD_EXIT( sync )		pthread_exit( ( void * ) 0 )
#define THREAD_INITIALISER		0
#define THREAD_SELF()			pthread_self()
#define THREAD_SAME( thread1, thread2 )	pthread_equal( ( thread1 ), ( thread2 ) )
#if defined( __osf__ ) || defined( __alpha__ ) || defined( __APPLE__ )
  #define THREAD_YIELD()		pthread_yield_np()
#elif defined( __MVS__ )
  #define THREAD_YIELD()		pthread_yield( NULL )
#elif defined( sun )
  #if OSVERSION <= 6
	/* Older Slowaris gets a bit complex, SunOS 4.x always

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -