mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Andy Dustman: add GNU pth user-space thread support.
This commit is contained in:
		
							parent
							
								
									8b41d5363a
								
							
						
					
					
						commit
						07bd90e92d
					
				
					 7 changed files with 594 additions and 198 deletions
				
			
		|  | @ -128,4 +128,8 @@ PERFORMANCE OF THIS SOFTWARE. | ||||||
| #define Py_file_input 257 | #define Py_file_input 257 | ||||||
| #define Py_eval_input 258 | #define Py_eval_input 258 | ||||||
| 
 | 
 | ||||||
|  | #ifdef _GNU_PTH | ||||||
|  | /* GNU pth user-space thread support */ | ||||||
|  | #include <pth.h> | ||||||
|  | #endif | ||||||
| #endif /* !Py_PYTHON_H */ | #endif /* !Py_PYTHON_H */ | ||||||
|  |  | ||||||
|  | @ -150,9 +150,13 @@ void PyThread_init_thread _P0() | ||||||
| #include "thread_lwp.h" | #include "thread_lwp.h" | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef _GNU_PTH | ||||||
|  | #include "thread_pth.h" | ||||||
|  | #else | ||||||
| #ifdef _POSIX_THREADS | #ifdef _POSIX_THREADS | ||||||
| #include "thread_pthread.h" | #include "thread_pthread.h" | ||||||
| #endif | #endif | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef C_THREADS | #ifdef C_THREADS | ||||||
| #include "thread_cthread.h" | #include "thread_cthread.h" | ||||||
|  |  | ||||||
							
								
								
									
										328
									
								
								Python/thread_pth.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								Python/thread_pth.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,328 @@ | ||||||
|  | /***********************************************************
 | ||||||
|  | Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam, | ||||||
|  | The Netherlands. | ||||||
|  | 
 | ||||||
|  |                         All Rights Reserved | ||||||
|  | 
 | ||||||
|  | Permission to use, copy, modify, and distribute this software and its | ||||||
|  | documentation for any purpose and without fee is hereby granted, | ||||||
|  | provided that the above copyright notice appear in all copies and that | ||||||
|  | both that copyright notice and this permission notice appear in | ||||||
|  | supporting documentation, and that the names of Stichting Mathematisch | ||||||
|  | Centrum or CWI or Corporation for National Research Initiatives or | ||||||
|  | CNRI not be used in advertising or publicity pertaining to | ||||||
|  | distribution of the software without specific, written prior | ||||||
|  | permission. | ||||||
|  | 
 | ||||||
|  | While CWI is the initial source for this software, a modified version | ||||||
|  | is made available by the Corporation for National Research Initiatives | ||||||
|  | (CNRI) at the Internet address ftp://ftp.python.org.
 | ||||||
|  | 
 | ||||||
|  | STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH | ||||||
|  | REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF | ||||||
|  | MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH | ||||||
|  | CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL | ||||||
|  | DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR | ||||||
|  | PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||||||
|  | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||||||
|  | PERFORMANCE OF THIS SOFTWARE. | ||||||
|  | 
 | ||||||
|  | ******************************************************************/ | ||||||
|  | 
 | ||||||
|  | /* GNU pth threads interface
 | ||||||
|  |    http://www.gnu.org/software/pth
 | ||||||
|  |    2000-05-03 Andy Dustman <andy@dustman.net> | ||||||
|  | 
 | ||||||
|  |    Adapted from Posix threads interface  | ||||||
|  |    12 May 1997 -- david arnold <davida@pobox.com> | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <pth.h> | ||||||
|  | 
 | ||||||
|  | /* A pth mutex isn't sufficient to model the Python lock type
 | ||||||
|  |  * because pth mutexes can be acquired multiple times by the | ||||||
|  |  * same thread. | ||||||
|  |  * | ||||||
|  |  * The pth_lock struct implements a Python lock as a "locked?" bit | ||||||
|  |  * and a <condition, mutex> pair.  In general, if the bit can be acquired | ||||||
|  |  * instantly, it is, else the pair is used to block the thread until the | ||||||
|  |  * bit is cleared. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  | 	char             locked; /* 0=unlocked, 1=locked */ | ||||||
|  | 	/* a <cond, mutex> pair to handle an acquire of a locked lock */ | ||||||
|  | 	pth_cond_t   lock_released; | ||||||
|  | 	pth_mutex_t  mut; | ||||||
|  | } pth_lock; | ||||||
|  | 
 | ||||||
|  | #define CHECK_STATUS(name)  if (status == -1) { printf("%d ", status); perror(name); error = 1; } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Initialization. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | static void PyThread__init_thread _P0() | ||||||
|  | { | ||||||
|  | 	pth_init(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Thread support. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int PyThread_start_new_thread _P2(func, void (*func) _P((void *)), arg, void *arg) | ||||||
|  | { | ||||||
|  | 	pth_t th; | ||||||
|  | 	int success; | ||||||
|  | 	dprintf(("PyThread_start_new_thread called\n")); | ||||||
|  | 	if (!initialized) | ||||||
|  | 		PyThread_init_thread(); | ||||||
|  | 
 | ||||||
|  | 	th = pth_spawn(PTH_ATTR_DEFAULT, | ||||||
|  | 				 (void* (*)_P((void *)))func, | ||||||
|  | 				 (void *)arg | ||||||
|  | 				 ); | ||||||
|  | 
 | ||||||
|  | 	return th == NULL ? 0 : 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | long PyThread_get_thread_ident _P0() | ||||||
|  | { | ||||||
|  | 	volatile pth_t threadid; | ||||||
|  | 	if (!initialized) | ||||||
|  | 		PyThread_init_thread(); | ||||||
|  | 	/* Jump through some hoops for Alpha OSF/1 */ | ||||||
|  | 	threadid = pth_self(); | ||||||
|  | 	return (long) *(long *) &threadid; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void do_PyThread_exit_thread _P1(no_cleanup, int no_cleanup) | ||||||
|  | { | ||||||
|  | 	dprintf(("PyThread_exit_thread called\n")); | ||||||
|  | 	if (!initialized) { | ||||||
|  | 		if (no_cleanup) | ||||||
|  | 			_exit(0); | ||||||
|  | 		else | ||||||
|  | 			exit(0); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread_exit_thread _P0() | ||||||
|  | { | ||||||
|  | 	do_PyThread_exit_thread(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread__exit_thread _P0() | ||||||
|  | { | ||||||
|  | 	do_PyThread_exit_thread(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #ifndef NO_EXIT_PROG | ||||||
|  | static void do_PyThread_exit_prog _P2(status, int status, no_cleanup, 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 _P1(status, int status) | ||||||
|  | { | ||||||
|  | 	do_PyThread_exit_prog(status, 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread__exit_prog _P1(status, int status) | ||||||
|  | { | ||||||
|  | 	do_PyThread_exit_prog(status, 1); | ||||||
|  | } | ||||||
|  | #endif /* NO_EXIT_PROG */ | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Lock support. | ||||||
|  |  */ | ||||||
|  | PyThread_type_lock PyThread_allocate_lock _P0() | ||||||
|  | { | ||||||
|  | 	pth_lock *lock; | ||||||
|  | 	int status, error = 0; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_allocate_lock called\n")); | ||||||
|  | 	if (!initialized) | ||||||
|  | 		PyThread_init_thread(); | ||||||
|  | 
 | ||||||
|  | 	lock = (pth_lock *) malloc(sizeof(pth_lock)); | ||||||
|  |         memset((void *)lock, '\0', sizeof(pth_lock)); | ||||||
|  | 	if (lock) { | ||||||
|  | 		lock->locked = 0; | ||||||
|  | 		status = pth_mutex_init(&lock->mut); | ||||||
|  | 		CHECK_STATUS("pth_mutex_init"); | ||||||
|  | 		status = pth_cond_init(&lock->lock_released); | ||||||
|  | 		CHECK_STATUS("pth_cond_init"); | ||||||
|  | 		if (error) { | ||||||
|  | 			free((void *)lock); | ||||||
|  | 			lock = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	dprintf(("PyThread_allocate_lock() -> %lx\n", (long)lock)); | ||||||
|  | 	return (PyThread_type_lock) lock; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread_free_lock _P1(lock, PyThread_type_lock lock) | ||||||
|  | { | ||||||
|  | 	pth_lock *thelock = (pth_lock *)lock; | ||||||
|  | 	int status, error = 0; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_free_lock(%lx) called\n", (long)lock)); | ||||||
|  | 
 | ||||||
|  | 	free((void *)thelock); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int PyThread_acquire_lock _P2(lock, PyThread_type_lock lock, waitflag, int waitflag) | ||||||
|  | { | ||||||
|  | 	int success; | ||||||
|  | 	pth_lock *thelock = (pth_lock *)lock; | ||||||
|  | 	int status, error = 0; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_acquire_lock(%lx, %d) called\n", (long)lock, waitflag)); | ||||||
|  | 
 | ||||||
|  | 	status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL); | ||||||
|  | 	CHECK_STATUS("pth_mutex_acquire[1]"); | ||||||
|  | 	success = thelock->locked == 0; | ||||||
|  |         if (success) thelock->locked = 1; | ||||||
|  |         status = pth_mutex_release( &thelock->mut ); | ||||||
|  |         CHECK_STATUS("pth_mutex_release[1]"); | ||||||
|  | 
 | ||||||
|  |         if ( !success && waitflag ) { | ||||||
|  |                 /* continue trying until we get the lock */ | ||||||
|  | 
 | ||||||
|  |                 /* mut must be locked by me -- part of the condition
 | ||||||
|  |                  * protocol */ | ||||||
|  |                 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL ); | ||||||
|  |                 CHECK_STATUS("pth_mutex_acquire[2]"); | ||||||
|  |                 while ( thelock->locked ) { | ||||||
|  |                         status = pth_cond_await(&thelock->lock_released, | ||||||
|  |                                                 &thelock->mut, NULL); | ||||||
|  |                         CHECK_STATUS("pth_cond_await"); | ||||||
|  |                 } | ||||||
|  |                 thelock->locked = 1; | ||||||
|  |                 status = pth_mutex_release( &thelock->mut ); | ||||||
|  |                 CHECK_STATUS("pth_mutex_release[2]"); | ||||||
|  |                 success = 1; | ||||||
|  |         } | ||||||
|  |         if (error) success = 0; | ||||||
|  |         dprintf(("PyThread_acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success)); | ||||||
|  | 	return success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread_release_lock _P1(lock, PyThread_type_lock lock) | ||||||
|  | { | ||||||
|  |         pth_lock *thelock = (pth_lock *)lock; | ||||||
|  |         int status, error = 0; | ||||||
|  | 
 | ||||||
|  |         dprintf(("PyThread_release_lock(%lx) called\n", (long)lock)); | ||||||
|  | 
 | ||||||
|  |         status = pth_mutex_acquire( &thelock->mut, 0, NULL ); | ||||||
|  |         CHECK_STATUS("pth_mutex_acquire[3]"); | ||||||
|  | 
 | ||||||
|  |         thelock->locked = 0; | ||||||
|  | 
 | ||||||
|  |         status = pth_mutex_release( &thelock->mut ); | ||||||
|  |         CHECK_STATUS("pth_mutex_release[3]"); | ||||||
|  | 
 | ||||||
|  |         /* wake up someone (anyone, if any) waiting on the lock */ | ||||||
|  |         status = pth_cond_notify( &thelock->lock_released, 0 ); | ||||||
|  |         CHECK_STATUS("pth_cond_notify"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Semaphore support. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | struct semaphore { | ||||||
|  | 	pth_mutex_t mutex; | ||||||
|  | 	pth_cond_t cond; | ||||||
|  | 	int value; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | PyThread_type_sema PyThread_allocate_sema _P1(value, int value) | ||||||
|  | { | ||||||
|  | 	struct semaphore *sema; | ||||||
|  | 	int status, error = 0; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_allocate_sema called\n")); | ||||||
|  | 	if (!initialized) | ||||||
|  | 		PyThread_init_thread(); | ||||||
|  | 
 | ||||||
|  | 	sema = (struct semaphore *) malloc(sizeof(struct semaphore)); | ||||||
|  | 	if (sema != NULL) { | ||||||
|  | 		sema->value = value; | ||||||
|  | 		status = pth_mutex_init(&sema->mutex); | ||||||
|  | 		CHECK_STATUS("pth_mutex_init"); | ||||||
|  | 		status = pth_cond_init(&sema->cond); | ||||||
|  | 		CHECK_STATUS("pth_mutex_init"); | ||||||
|  | 		if (error) { | ||||||
|  | 			free((void *) sema); | ||||||
|  | 			sema = NULL; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	dprintf(("PyThread_allocate_sema() -> %lx\n", (long) sema)); | ||||||
|  | 	return (PyThread_type_sema) sema; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread_free_sema _P1(sema, PyThread_type_sema sema) | ||||||
|  | { | ||||||
|  | 	int status, error = 0; | ||||||
|  | 	struct semaphore *thesema = (struct semaphore *) sema; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_free_sema(%lx) called\n", (long) sema)); | ||||||
|  | 	free((void *) thesema); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int PyThread_down_sema _P2(sema, PyThread_type_sema sema, waitflag, int waitflag) | ||||||
|  | { | ||||||
|  | 	int status, error = 0, success; | ||||||
|  | 	struct semaphore *thesema = (struct semaphore *) sema; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_down_sema(%lx, %d) called\n", (long) sema, waitflag)); | ||||||
|  | 	status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL); | ||||||
|  | 	CHECK_STATUS("pth_mutex_acquire"); | ||||||
|  | 	if (waitflag) { | ||||||
|  | 		while (!error && thesema->value <= 0) { | ||||||
|  | 			status = pth_cond_await(&thesema->cond, | ||||||
|  | 						&thesema->mutex, NULL); | ||||||
|  | 			CHECK_STATUS("pth_cond_await"); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if (error) | ||||||
|  | 		success = 0; | ||||||
|  | 	else if (thesema->value > 0) { | ||||||
|  | 		thesema->value--; | ||||||
|  | 		success = 1; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		success = 0; | ||||||
|  | 	status = pth_mutex_release(&thesema->mutex); | ||||||
|  | 	CHECK_STATUS("pth_mutex_release"); | ||||||
|  | 	dprintf(("PyThread_down_sema(%lx) return\n", (long) sema)); | ||||||
|  | 	return success; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PyThread_up_sema _P1(sema, PyThread_type_sema sema) | ||||||
|  | { | ||||||
|  | 	int status, error = 0; | ||||||
|  | 	struct semaphore *thesema = (struct semaphore *) sema; | ||||||
|  | 
 | ||||||
|  | 	dprintf(("PyThread_up_sema(%lx)\n", (long) sema)); | ||||||
|  | 	status = pth_mutex_acquire(&thesema->mutex, 0, NULL); | ||||||
|  | 	CHECK_STATUS("pth_mutex_acquire"); | ||||||
|  | 	thesema->value++; | ||||||
|  | 	status = pth_cond_notify(&thesema->cond, 1); | ||||||
|  | 	CHECK_STATUS("pth_cond_notify"); | ||||||
|  | 	status = pth_mutex_release(&thesema->mutex); | ||||||
|  | 	CHECK_STATUS("pth_mutex_release"); | ||||||
|  | } | ||||||
|  | @ -35,6 +35,9 @@ | ||||||
|    This is the case on Motorola V4 (R40V4.2) */ |    This is the case on Motorola V4 (R40V4.2) */ | ||||||
| #undef GETTIMEOFDAY_NO_TZ | #undef GETTIMEOFDAY_NO_TZ | ||||||
| 
 | 
 | ||||||
|  | /* Define if you have GNU PTH threads */ | ||||||
|  | #undef _GNU_PTH | ||||||
|  | 
 | ||||||
| /* Define this if your time.h defines altzone */ | /* Define this if your time.h defines altzone */ | ||||||
| #undef HAVE_ALTZONE | #undef HAVE_ALTZONE | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -103,6 +103,9 @@ | ||||||
|    This is the case on Motorola V4 (R40V4.2) */ |    This is the case on Motorola V4 (R40V4.2) */ | ||||||
| #undef GETTIMEOFDAY_NO_TZ | #undef GETTIMEOFDAY_NO_TZ | ||||||
| 
 | 
 | ||||||
|  | /* Define if you have GNU PTH threads */ | ||||||
|  | #undef _GNU_PTH | ||||||
|  | 
 | ||||||
| /* Define this if your time.h defines altzone */ | /* Define this if your time.h defines altzone */ | ||||||
| #undef HAVE_ALTZONE | #undef HAVE_ALTZONE | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -654,6 +654,10 @@ AC_DEFINE(_REENTRANT) | ||||||
| AC_CHECK_HEADER(mach/cthreads.h, [AC_DEFINE(WITH_THREAD) | AC_CHECK_HEADER(mach/cthreads.h, [AC_DEFINE(WITH_THREAD) | ||||||
| AC_DEFINE(C_THREADS) | AC_DEFINE(C_THREADS) | ||||||
| LIBOBJS="$LIBOBJS thread.o"],[ | LIBOBJS="$LIBOBJS thread.o"],[ | ||||||
|  | AC_CHECK_LIB(pth, pth_init, [AC_DEFINE(WITH_THREAD) | ||||||
|  | AC_DEFINE(_GNU_PTH) | ||||||
|  | LIBS="-lpth $LIBS" | ||||||
|  | LIBOBJS="$LIBOBJS thread.o"],[ | ||||||
| AC_CHECK_LIB(pthread, pthread_create, [AC_DEFINE(WITH_THREAD) | AC_CHECK_LIB(pthread, pthread_create, [AC_DEFINE(WITH_THREAD) | ||||||
| AC_DEFINE(_POSIX_THREADS) | AC_DEFINE(_POSIX_THREADS) | ||||||
| LIBS="-lpthread $LIBS" | LIBS="-lpthread $LIBS" | ||||||
|  | @ -680,7 +684,7 @@ AC_CHECK_LIB(cma, pthread_create, [AC_DEFINE(WITH_THREAD) | ||||||
| AC_DEFINE(_POSIX_THREADS) | AC_DEFINE(_POSIX_THREADS) | ||||||
| LIBS="$LIBS -lcma" | LIBS="$LIBS -lcma" | ||||||
| LIBOBJS="$LIBOBJS thread.o"]) | LIBOBJS="$LIBOBJS thread.o"]) | ||||||
| ])])])])])])]) | ])])])])])])])]) | ||||||
| 
 | 
 | ||||||
| AC_CHECK_LIB(mpc, usconfig, [AC_DEFINE(WITH_THREAD) | AC_CHECK_LIB(mpc, usconfig, [AC_DEFINE(WITH_THREAD) | ||||||
| LIBS="$LIBS -lmpc" | LIBS="$LIBS -lmpc" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum