307 lines · 5.6 KB · C
RawDownload
/* This code implemented by cvale@netcom.com */ #define INCL_DOSPROCESS#define INCL_DOSSEMAPHORES#include "os2.h"#include "limits.h" #include "process.h" #if defined(PYCC_GCC)#include <sys/builtin.h>#include <sys/fmutex.h>#elselong PyThread_get_thread_ident(void);#endif /* default thread stack size of 64kB */#if !defined(THREAD_STACK_SIZE)#define	THREAD_STACK_SIZE	0x10000#endif #define OS2_STACKSIZE(x)	(x ? x : THREAD_STACK_SIZE) /* * Initialization of the C package, should not be needed. */static voidPyThread__init_thread(void){} /* * Thread support. */longPyThread_start_new_thread(void (*func)(void *), void *arg){	int thread_id; 	thread_id = _beginthread(func,				NULL,				OS2_STACKSIZE(_pythread_stacksize),				arg); 	if (thread_id == -1) {		dprintf(("_beginthread failed. return %ld\n", errno));	} 	return thread_id;} longPyThread_get_thread_ident(void){#if !defined(PYCC_GCC)	PPIB pib;	PTIB tib;#endif 	if (!initialized)		PyThread_init_thread(); #if defined(PYCC_GCC)	return _gettid();#else	DosGetInfoBlocks(&tib, &pib);	return tib->tib_ptib2->tib2_ultid;#endif} static voiddo_PyThread_exit_thread(int no_cleanup){	dprintf(("%ld: PyThread_exit_thread called\n",		 PyThread_get_thread_ident()));	if (!initialized)		if (no_cleanup)			_exit(0);		else			exit(0);	_endthread();} void PyThread_exit_thread(void){	do_PyThread_exit_thread(0);} void PyThread__exit_thread(void){	do_PyThread_exit_thread(1);} #ifndef NO_EXIT_PROGstatic void do_PyThread_exit_prog(int status, int no_cleanup){	dprintf(("PyThread_exit_prog(%d) called\n", status));	if (!initialized)		if (no_cleanup)			_exit(status);		else			exit(status);} void PyThread_exit_prog(int status){	do_PyThread_exit_prog(status, 0);} void PyThread__exit_prog(int status){	do_PyThread_exit_prog(status, 1);}#endif /* NO_EXIT_PROG */ /* * Lock support.  This is implemented with an event semaphore and critical * sections to make it behave more like a posix mutex than its OS/2  * counterparts. */ typedef struct os2_lock_t {	int is_set;	HEV changed;} *type_os2_lock; PyThread_type_lock PyThread_allocate_lock(void){#if defined(PYCC_GCC)	_fmutex *sem = malloc(sizeof(_fmutex));	if (!initialized)		PyThread_init_thread();	dprintf(("%ld: PyThread_allocate_lock() -> %lx\n",		 PyThread_get_thread_ident(),		 (long)sem));	if (_fmutex_create(sem, 0)) {		free(sem);		sem = NULL;	}	return (PyThread_type_lock)sem;#else	APIRET rc;	type_os2_lock lock = (type_os2_lock)malloc(sizeof(struct os2_lock_t)); 	dprintf(("PyThread_allocate_lock called\n"));	if (!initialized)		PyThread_init_thread(); 	lock->is_set = 0; 	DosCreateEventSem(NULL, &lock->changed, 0, 0); 	dprintf(("%ld: PyThread_allocate_lock() -> %p\n", 		 PyThread_get_thread_ident(),         	 lock->changed)); 	return (PyThread_type_lock)lock;#endif} void PyThread_free_lock(PyThread_type_lock aLock){#if !defined(PYCC_GCC)	type_os2_lock lock = (type_os2_lock)aLock;#endif 	dprintf(("%ld: PyThread_free_lock(%p) called\n",		 PyThread_get_thread_ident(),aLock)); #if defined(PYCC_GCC)	if (aLock) {		_fmutex_close((_fmutex *)aLock);		free((_fmutex *)aLock);	}#else	DosCloseEventSem(lock->changed);	free(aLock);#endif} /* * Return 1 on success if the lock was acquired * * and 0 if the lock was not acquired. */int PyThread_acquire_lock(PyThread_type_lock aLock, int waitflag){#if !defined(PYCC_GCC)	int   done = 0;	ULONG count;	PID   pid = 0;	TID   tid = 0;	type_os2_lock lock = (type_os2_lock)aLock;#endif 	dprintf(("%ld: PyThread_acquire_lock(%p, %d) called\n",		 PyThread_get_thread_ident(),		 aLock,		 waitflag)); #if defined(PYCC_GCC)	/* always successful if the lock doesn't exist */	if (aLock &&	    _fmutex_request((_fmutex *)aLock, waitflag ? 0 : _FMR_NOWAIT))		return 0;#else	while (!done) {		/* if the lock is currently set, we have to wait for		 * the state to change		 */		if (lock->is_set) {			if (!waitflag)				return 0;			DosWaitEventSem(lock->changed, SEM_INDEFINITE_WAIT);		} 		/* enter a critical section and try to get the semaphore.  If		 * it is still locked, we will try again.		 */		if (DosEnterCritSec())			return 0; 		if (!lock->is_set) {			lock->is_set = 1;			DosResetEventSem(lock->changed, &count);			done = 1;		} 		DosExitCritSec();	}#endif 	return 1;} voidPyThread_release_lock(PyThread_type_lock aLock){#if !defined(PYCC_GCC)	type_os2_lock lock = (type_os2_lock)aLock;#endif 	dprintf(("%ld: PyThread_release_lock(%p) called\n",		 PyThread_get_thread_ident(),		 aLock)); #if defined(PYCC_GCC)	if (aLock)		_fmutex_release((_fmutex *)aLock);#else	if (!lock->is_set) {		dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",			 PyThread_get_thread_ident(),			 aLock,			 GetLastError()));		return;	} 	if (DosEnterCritSec()) {		dprintf(("%ld: Could not PyThread_release_lock(%p) error: %l\n",			 PyThread_get_thread_ident(),			 aLock,			 GetLastError()));		return;	} 	lock->is_set = 0;	DosPostEventSem(lock->changed); 	DosExitCritSec();#endif} /* minimum/maximum thread stack sizes supported */#define THREAD_MIN_STACKSIZE	0x8000		/* 32kB */#define THREAD_MAX_STACKSIZE	0x2000000	/* 32MB */ /* set the thread stack size. * Return 0 if size is valid, -1 otherwise. */static int_pythread_os2_set_stacksize(size_t size){	/* set to default */	if (size == 0) {		_pythread_stacksize = 0;		return 0;	} 	/* valid range? */	if (size >= THREAD_MIN_STACKSIZE && size < THREAD_MAX_STACKSIZE) {		_pythread_stacksize = size;		return 0;	} 	return -1;} #define THREAD_SET_STACKSIZE(x)	_pythread_os2_set_stacksize(x)