view Python/thread_pthread.h @ 40643:47f9efdc0855

Merged revisions 53304-53433,53435-53450 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r53304 | vinay.sajip | 2007-01-09 15:50:28 +0100 (Tue, 09 Jan 2007) | 1 line Bug #1627575: Added _open() method to FileHandler which can be used to reopen files. The FileHandler instance now saves the encoding (which can be None) in an attribute called "encoding". ........ r53305 | vinay.sajip | 2007-01-09 15:51:36 +0100 (Tue, 09 Jan 2007) | 1 line Added entry about addition of _open() method to logging.FileHandler. ........ r53306 | vinay.sajip | 2007-01-09 15:54:56 +0100 (Tue, 09 Jan 2007) | 1 line Added a docstring ........ r53316 | thomas.heller | 2007-01-09 20:19:33 +0100 (Tue, 09 Jan 2007) | 4 lines Verify the sizes of the basic ctypes data types against the struct module. Will backport to release25-maint. ........ r53340 | gustavo.niemeyer | 2007-01-10 17:13:40 +0100 (Wed, 10 Jan 2007) | 3 lines Mention in the int() docstring that a base zero has meaning, as stated in http://docs.python.org/lib/built-in-funcs.html as well. ........ r53341 | gustavo.niemeyer | 2007-01-10 17:15:48 +0100 (Wed, 10 Jan 2007) | 2 lines Minor change in int() docstring for proper spacing. ........ r53358 | thomas.heller | 2007-01-10 21:12:13 +0100 (Wed, 10 Jan 2007) | 1 line Change the ctypes version number to "1.1.0". ........ r53361 | thomas.heller | 2007-01-10 21:51:19 +0100 (Wed, 10 Jan 2007) | 1 line Must change the version number in the _ctypes extension as well. ........ r53362 | guido.van.rossum | 2007-01-11 00:12:56 +0100 (Thu, 11 Jan 2007) | 3 lines Fix the signature of log_error(). (A subclass that did the right thing was getting complaints from pychecker.) ........ r53370 | matthias.klose | 2007-01-11 11:26:31 +0100 (Thu, 11 Jan 2007) | 2 lines - Make the documentation match the code and the docstring ........ r53375 | matthias.klose | 2007-01-11 12:44:04 +0100 (Thu, 11 Jan 2007) | 2 lines - idle: Honor the "Cancel" action in the save dialog (Debian bug #299092). ........ r53381 | raymond.hettinger | 2007-01-11 19:22:55 +0100 (Thu, 11 Jan 2007) | 1 line SF #1486663 -- Allow keyword args in subclasses of set() and frozenset(). ........ r53388 | thomas.heller | 2007-01-11 22:18:56 +0100 (Thu, 11 Jan 2007) | 4 lines Fixes for 64-bit Windows: In ctypes.wintypes, correct the definitions of HANDLE, WPARAM, LPARAM data types. Make parameterless foreign function calls work. ........ r53390 | thomas.heller | 2007-01-11 22:23:12 +0100 (Thu, 11 Jan 2007) | 2 lines Correct the comments: the code is right. ........ r53393 | brett.cannon | 2007-01-12 08:27:52 +0100 (Fri, 12 Jan 2007) | 3 lines Fix error where the end of a funcdesc environment was accidentally moved too far down. ........ r53397 | anthony.baxter | 2007-01-12 10:35:56 +0100 (Fri, 12 Jan 2007) | 3 lines add parsetok.h as a dependency - previously, changing this file doesn't cause the right files to be rebuilt. ........ r53401 | thomas.heller | 2007-01-12 21:08:19 +0100 (Fri, 12 Jan 2007) | 3 lines Avoid warnings in the test suite because ctypes.wintypes cannot be imported on non-windows systems. ........ r53402 | thomas.heller | 2007-01-12 21:17:34 +0100 (Fri, 12 Jan 2007) | 6 lines patch #1610795: BSD version of ctypes.util.find_library, by Martin Kammerhofer. release25-maint backport candidate, but the release manager has to decide. ........ r53403 | thomas.heller | 2007-01-12 21:21:53 +0100 (Fri, 12 Jan 2007) | 3 lines patch #1610795: BSD version of ctypes.util.find_library, by Martin Kammerhofer. ........ r53406 | brett.cannon | 2007-01-13 01:29:49 +0100 (Sat, 13 Jan 2007) | 2 lines Deprecate the sets module. ........ r53407 | georg.brandl | 2007-01-13 13:31:51 +0100 (Sat, 13 Jan 2007) | 3 lines Fix typo. ........ r53409 | marc-andre.lemburg | 2007-01-13 22:00:08 +0100 (Sat, 13 Jan 2007) | 16 lines Bump version number and change copyright year. Add new API linux_distribution() which supports reading the full distribution name and also knows how to parse LSB-style release files. Redirect the old dist() API to the new API (using the short distribution name taken from the release file filename). Add branch and revision to _sys_version(). Add work-around for Cygwin to libc_ver(). Add support for IronPython (thanks for Anthony Baxter) and make Jython support more robust. ........ r53410 | neal.norwitz | 2007-01-13 22:22:37 +0100 (Sat, 13 Jan 2007) | 1 line Fix grammar in docstrings ........ r53411 | marc-andre.lemburg | 2007-01-13 23:32:21 +0100 (Sat, 13 Jan 2007) | 9 lines Add parameter sys_version to _sys_version(). Change the cache for _sys_version() to take the parameter into account. Add support for parsing the IronPython 1.0.1 sys.version value - even though it still returns '1.0.0'; the version string no longer includes the patch level. ........ r53412 | peter.astrand | 2007-01-13 23:35:35 +0100 (Sat, 13 Jan 2007) | 1 line Fix for bug #1634343: allow specifying empty arguments on Windows ........ r53414 | marc-andre.lemburg | 2007-01-13 23:59:36 +0100 (Sat, 13 Jan 2007) | 14 lines Add Python implementation to the machine details. Pretty-print the Python version used for running PyBench. Let the user know when calibration has finished. [ 1563844 ] pybench support for IronPython: Simplify Unicode version detection. Make garbage collection and check interval settings optional if the Python implementation doesn't support thess (e.g. IronPython). ........ r53415 | marc-andre.lemburg | 2007-01-14 00:13:54 +0100 (Sun, 14 Jan 2007) | 5 lines Use defaults if sys.executable isn't set (e.g. on Jython). This change allows running PyBench under Jython. ........ r53416 | marc-andre.lemburg | 2007-01-14 00:15:33 +0100 (Sun, 14 Jan 2007) | 3 lines Jython doesn't have sys.setcheckinterval() - ignore it in that case. ........ r53420 | gerhard.haering | 2007-01-14 02:43:50 +0100 (Sun, 14 Jan 2007) | 29 lines Merged changes from standalone version 2.3.3. This should probably all be merged into the 2.5 maintenance branch: - self->statement was not checked while fetching data, which could lead to crashes if you used the pysqlite API in unusual ways. Closing the cursor and continuing to fetch data was enough. - Converters are stored in a converters dictionary. The converter name is uppercased first. The old upper-casing algorithm was wrong and was replaced by a simple call to the Python string's upper() method instead. -Applied patch by Glyph Lefkowitz that fixes the problem with subsequent SQLITE_SCHEMA errors. - Improvement to the row type: rows can now be iterated over and have a keys() method. This improves compatibility with both tuple and dict a lot. - A bugfix for the subsecond resolution in timestamps. - Corrected the way the flags PARSE_DECLTYPES and PARSE_COLNAMES are checked for. Now they work as documented. - gcc on Linux sucks. It exports all symbols by default in shared libraries, so if symbols are not unique it can lead to problems with symbol lookup. pysqlite used to crash under Apache when mod_cache was enabled because both modules had the symbol cache_init. I fixed this by applying the prefix pysqlite_ almost everywhere. Sigh. ........ r53423 | guido.van.rossum | 2007-01-14 04:46:33 +0100 (Sun, 14 Jan 2007) | 2 lines Remove a dependency of this test on $COLUMNS. ........ r53425 | ka-ping.yee | 2007-01-14 05:25:15 +0100 (Sun, 14 Jan 2007) | 3 lines Handle old-style instances more gracefully (display documentation on the relevant class instead of documentation on <type 'instance'>). ........ r53440 | vinay.sajip | 2007-01-14 22:49:59 +0100 (Sun, 14 Jan 2007) | 1 line Added WatchedFileHandler (based on SF patch #1598415) ........ r53441 | vinay.sajip | 2007-01-14 22:50:50 +0100 (Sun, 14 Jan 2007) | 1 line Added documentation for WatchedFileHandler (based on SF patch #1598415) ........ r53442 | guido.van.rossum | 2007-01-15 01:02:35 +0100 (Mon, 15 Jan 2007) | 2 lines Doc patch matching r53434 (htonl etc. now always take/return positive ints). ........
author Thomas Wouters <thomas@python.org>
date Mon, 15 Jan 2007 15:49:28 +0000
parents 654c380cf8b9
children f197407bdba2 798e0d0c7246
line wrap: on
line source


/* Posix threads interface */

#include <stdlib.h>
#include <string.h>
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
#define destructor xxdestructor
#endif
#include <pthread.h>
#if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
#undef destructor
#endif
#include <signal.h>

/* The POSIX spec requires that use of pthread_attr_setstacksize
   be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
#ifndef THREAD_STACK_SIZE
#define	THREAD_STACK_SIZE	0	/* use default stack size */
#endif
/* for safety, ensure a viable minimum stacksize */
#define	THREAD_STACK_MIN	0x8000	/* 32kB */
#else  /* !_POSIX_THREAD_ATTR_STACKSIZE */
#ifdef THREAD_STACK_SIZE
#error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
#endif
#endif

/* The POSIX spec says that implementations supporting the sem_*
   family of functions must indicate this by defining
   _POSIX_SEMAPHORES. */   
#ifdef _POSIX_SEMAPHORES
/* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so 
   we need to add 0 to make it work there as well. */
#if (_POSIX_SEMAPHORES+0) == -1
#define HAVE_BROKEN_POSIX_SEMAPHORES
#else
#include <semaphore.h>
#include <errno.h>
#endif
#endif

/* Before FreeBSD 5.4, system scope threads was very limited resource
   in default setting.  So the process scope is preferred to get
   enough number of threads to work. */
#ifdef __FreeBSD__
#include <osreldate.h>
#if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101
#undef PTHREAD_SYSTEM_SCHED_SUPPORTED
#endif
#endif

#if !defined(pthread_attr_default)
#  define pthread_attr_default ((pthread_attr_t *)NULL)
#endif
#if !defined(pthread_mutexattr_default)
#  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
#endif
#if !defined(pthread_condattr_default)
#  define pthread_condattr_default ((pthread_condattr_t *)NULL)
#endif


/* Whether or not to use semaphores directly rather than emulating them with
 * mutexes and condition variables:
 */
#if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES)
#  define USE_SEMAPHORES
#else
#  undef USE_SEMAPHORES
#endif


/* On platforms that don't use standard POSIX threads pthread_sigmask()
 * isn't present.  DEC threads uses sigprocmask() instead as do most
 * other UNIX International compliant systems that don't have the full
 * pthread implementation.
 */
#if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
#  define SET_THREAD_SIGMASK pthread_sigmask
#else
#  define SET_THREAD_SIGMASK sigprocmask
#endif


/* A pthread mutex isn't sufficient to model the Python lock type
 * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
 * following are undefined:
 *  -> a thread tries to lock a mutex it already has locked
 *  -> a thread tries to unlock a mutex locked by a different thread
 * pthread mutexes are designed for serializing threads over short pieces
 * of code anyway, so wouldn't be an appropriate implementation of
 * Python's locks regardless.
 *
 * The pthread_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.     9 May 1994 tim@ksr.com
 */

typedef struct {
	char             locked; /* 0=unlocked, 1=locked */
	/* a <cond, mutex> pair to handle an acquire of a locked lock */
	pthread_cond_t   lock_released;
	pthread_mutex_t  mut;
} pthread_lock;

#define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }

/*
 * Initialization.
 */

#ifdef _HAVE_BSDI
static
void _noop(void)
{
}

static void
PyThread__init_thread(void)
{
	/* DO AN INIT BY STARTING THE THREAD */
	static int dummy = 0;
	pthread_t thread1;
	pthread_create(&thread1, NULL, (void *) _noop, &dummy);
	pthread_join(thread1, NULL);
}

#else /* !_HAVE_BSDI */

static void
PyThread__init_thread(void)
{
#if defined(_AIX) && defined(__GNUC__)
	pthread_init();
#endif
}

#endif /* !_HAVE_BSDI */

/*
 * Thread support.
 */


long
PyThread_start_new_thread(void (*func)(void *), void *arg)
{
	pthread_t th;
	int status;
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
	pthread_attr_t attrs;
#endif
#if defined(THREAD_STACK_SIZE)
	size_t	tss;
#endif

	dprintf(("PyThread_start_new_thread called\n"));
	if (!initialized)
		PyThread_init_thread();

#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
	if (pthread_attr_init(&attrs) != 0)
		return -1;
#endif
#if defined(THREAD_STACK_SIZE)
	tss = (_pythread_stacksize != 0) ? _pythread_stacksize
					 : THREAD_STACK_SIZE;
	if (tss != 0) {
		if (pthread_attr_setstacksize(&attrs, tss) != 0) {
			pthread_attr_destroy(&attrs);
			return -1;
		}
	}
#endif
#if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
        pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
#endif

	status = pthread_create(&th, 
#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
				 &attrs,
#else
				 (pthread_attr_t*)NULL,
#endif
				 (void* (*)(void *))func,
				 (void *)arg
				 );

#if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
	pthread_attr_destroy(&attrs);
#endif
	if (status != 0)
            return -1;

        pthread_detach(th);

#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
	return (long) th;
#else
	return (long) *(long *) &th;
#endif
}

/* XXX This implementation is considered (to quote Tim Peters) "inherently
   hosed" because:
     - It does not guarantee the promise that a non-zero integer is returned.
     - The cast to long is inherently unsafe.
     - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
       latter return statement (for Alpha OSF/1) are any longer necessary.
*/
long 
PyThread_get_thread_ident(void)
{
	volatile pthread_t threadid;
	if (!initialized)
		PyThread_init_thread();
	/* Jump through some hoops for Alpha OSF/1 */
	threadid = pthread_self();
#if SIZEOF_PTHREAD_T <= SIZEOF_LONG
	return (long) threadid;
#else
	return (long) *(long *) &threadid;
#endif
}

static void 
do_PyThread_exit_thread(int no_cleanup)
{
	dprintf(("PyThread_exit_thread called\n"));
	if (!initialized) {
		if (no_cleanup)
			_exit(0);
		else
			exit(0);
	}
}

void 
PyThread_exit_thread(void)
{
	do_PyThread_exit_thread(0);
}

void 
PyThread__exit_thread(void)
{
	do_PyThread_exit_thread(1);
}

#ifndef NO_EXIT_PROG
static 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 */

#ifdef USE_SEMAPHORES

/*
 * Lock support.
 */

PyThread_type_lock 
PyThread_allocate_lock(void)
{
	sem_t *lock;
	int status, error = 0;

	dprintf(("PyThread_allocate_lock called\n"));
	if (!initialized)
		PyThread_init_thread();

	lock = (sem_t *)malloc(sizeof(sem_t));

	if (lock) {
		status = sem_init(lock,0,1);
		CHECK_STATUS("sem_init");

		if (error) {
			free((void *)lock);
			lock = NULL;
		}
	}

	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
	return (PyThread_type_lock)lock;
}

void 
PyThread_free_lock(PyThread_type_lock lock)
{
	sem_t *thelock = (sem_t *)lock;
	int status, error = 0;

	dprintf(("PyThread_free_lock(%p) called\n", lock));

	if (!thelock)
		return;

	status = sem_destroy(thelock);
	CHECK_STATUS("sem_destroy");

	free((void *)thelock);
}

/*
 * As of February 2002, Cygwin thread implementations mistakenly report error
 * codes in the return value of the sem_ calls (like the pthread_ functions).
 * Correct implementations return -1 and put the code in errno. This supports
 * either.
 */
static int
fix_status(int status)
{
	return (status == -1) ? errno : status;
}

int 
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
	int success;
	sem_t *thelock = (sem_t *)lock;
	int status, error = 0;

	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));

	do {
		if (waitflag)
			status = fix_status(sem_wait(thelock));
		else
			status = fix_status(sem_trywait(thelock));
	} while (status == EINTR); /* Retry if interrupted by a signal */

	if (waitflag) {
		CHECK_STATUS("sem_wait");
	} else if (status != EAGAIN) {
		CHECK_STATUS("sem_trywait");
	}
	
	success = (status == 0) ? 1 : 0;

	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
	return success;
}

void 
PyThread_release_lock(PyThread_type_lock lock)
{
	sem_t *thelock = (sem_t *)lock;
	int status, error = 0;

	dprintf(("PyThread_release_lock(%p) called\n", lock));

	status = sem_post(thelock);
	CHECK_STATUS("sem_post");
}

#else /* USE_SEMAPHORES */

/*
 * Lock support.
 */
PyThread_type_lock 
PyThread_allocate_lock(void)
{
	pthread_lock *lock;
	int status, error = 0;

	dprintf(("PyThread_allocate_lock called\n"));
	if (!initialized)
		PyThread_init_thread();

	lock = (pthread_lock *) malloc(sizeof(pthread_lock));
	if (lock) {
		memset((void *)lock, '\0', sizeof(pthread_lock));
		lock->locked = 0;

		status = pthread_mutex_init(&lock->mut,
					    pthread_mutexattr_default);
		CHECK_STATUS("pthread_mutex_init");

		status = pthread_cond_init(&lock->lock_released,
					   pthread_condattr_default);
		CHECK_STATUS("pthread_cond_init");

		if (error) {
			free((void *)lock);
			lock = 0;
		}
	}

	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
	return (PyThread_type_lock) lock;
}

void 
PyThread_free_lock(PyThread_type_lock lock)
{
	pthread_lock *thelock = (pthread_lock *)lock;
	int status, error = 0;

	dprintf(("PyThread_free_lock(%p) called\n", lock));

	status = pthread_mutex_destroy( &thelock->mut );
	CHECK_STATUS("pthread_mutex_destroy");

	status = pthread_cond_destroy( &thelock->lock_released );
	CHECK_STATUS("pthread_cond_destroy");

	free((void *)thelock);
}

int 
PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
{
	int success;
	pthread_lock *thelock = (pthread_lock *)lock;
	int status, error = 0;

	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));

	status = pthread_mutex_lock( &thelock->mut );
	CHECK_STATUS("pthread_mutex_lock[1]");
	success = thelock->locked == 0;

	if ( !success && waitflag ) {
		/* continue trying until we get the lock */

		/* mut must be locked by me -- part of the condition
		 * protocol */
		while ( thelock->locked ) {
			status = pthread_cond_wait(&thelock->lock_released,
						   &thelock->mut);
			CHECK_STATUS("pthread_cond_wait");
		}
		success = 1;
	}
	if (success) thelock->locked = 1;
	status = pthread_mutex_unlock( &thelock->mut );
	CHECK_STATUS("pthread_mutex_unlock[1]");

	if (error) success = 0;
	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
	return success;
}

void 
PyThread_release_lock(PyThread_type_lock lock)
{
	pthread_lock *thelock = (pthread_lock *)lock;
	int status, error = 0;

	dprintf(("PyThread_release_lock(%p) called\n", lock));

	status = pthread_mutex_lock( &thelock->mut );
	CHECK_STATUS("pthread_mutex_lock[3]");

	thelock->locked = 0;

	status = pthread_mutex_unlock( &thelock->mut );
	CHECK_STATUS("pthread_mutex_unlock[3]");

	/* wake up someone (anyone, if any) waiting on the lock */
	status = pthread_cond_signal( &thelock->lock_released );
	CHECK_STATUS("pthread_cond_signal");
}

#endif /* USE_SEMAPHORES */

/* set the thread stack size.
 * Return 0 if size is valid, -1 if size is invalid,
 * -2 if setting stack size is not supported.
 */
static int
_pythread_pthread_set_stacksize(size_t size)
{
#if defined(THREAD_STACK_SIZE)
	pthread_attr_t attrs;
	size_t tss_min;
	int rc = 0;
#endif

	/* set to default */
	if (size == 0) {
		_pythread_stacksize = 0;
		return 0;
	}

#if defined(THREAD_STACK_SIZE)
#if defined(PTHREAD_STACK_MIN)
	tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
						       : THREAD_STACK_MIN;
#else
	tss_min = THREAD_STACK_MIN;
#endif
	if (size >= tss_min) {
		/* validate stack size by setting thread attribute */
		if (pthread_attr_init(&attrs) == 0) {
			rc = pthread_attr_setstacksize(&attrs, size);
			pthread_attr_destroy(&attrs);
			if (rc == 0) {
				_pythread_stacksize = size;
				return 0;
			}
		}
	}
	return -1;
#else
	return -2;
#endif
}

#define THREAD_SET_STACKSIZE(x)	_pythread_pthread_set_stacksize(x)