symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_pthread.h
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 
       
     2 /* Posix threads interface */
       
     3 
       
     4 #include <stdlib.h>
       
     5 #include <string.h>
       
     6 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
       
     7 #define destructor xxdestructor
       
     8 #endif
       
     9 #include <pthread.h>
       
    10 #if defined(__APPLE__) || defined(HAVE_PTHREAD_DESTRUCTOR)
       
    11 #undef destructor
       
    12 #endif
       
    13 #include <signal.h>
       
    14 
       
    15 /* The POSIX spec requires that use of pthread_attr_setstacksize
       
    16    be conditional on _POSIX_THREAD_ATTR_STACKSIZE being defined. */
       
    17 #ifdef _POSIX_THREAD_ATTR_STACKSIZE
       
    18 #ifndef THREAD_STACK_SIZE
       
    19 #define	THREAD_STACK_SIZE	0	/* use default stack size */
       
    20 #endif
       
    21 /* for safety, ensure a viable minimum stacksize */
       
    22 #define	THREAD_STACK_MIN	0x8000	/* 32kB */
       
    23 #else  /* !_POSIX_THREAD_ATTR_STACKSIZE */
       
    24 #ifdef THREAD_STACK_SIZE
       
    25 #error "THREAD_STACK_SIZE defined but _POSIX_THREAD_ATTR_STACKSIZE undefined"
       
    26 #endif
       
    27 #endif
       
    28 
       
    29 /* The POSIX spec says that implementations supporting the sem_*
       
    30    family of functions must indicate this by defining
       
    31    _POSIX_SEMAPHORES. */   
       
    32 #ifdef _POSIX_SEMAPHORES
       
    33 /* On FreeBSD 4.x, _POSIX_SEMAPHORES is defined empty, so 
       
    34    we need to add 0 to make it work there as well. */
       
    35 #if (_POSIX_SEMAPHORES+0) == -1
       
    36 #define HAVE_BROKEN_POSIX_SEMAPHORES
       
    37 #else
       
    38 #include <semaphore.h>
       
    39 #include <errno.h>
       
    40 #endif
       
    41 #endif
       
    42 
       
    43 /* Before FreeBSD 5.4, system scope threads was very limited resource
       
    44    in default setting.  So the process scope is preferred to get
       
    45    enough number of threads to work. */
       
    46 #ifdef __FreeBSD__
       
    47 #include <osreldate.h>
       
    48 #if __FreeBSD_version >= 500000 && __FreeBSD_version < 504101
       
    49 #undef PTHREAD_SYSTEM_SCHED_SUPPORTED
       
    50 #endif
       
    51 #endif
       
    52 
       
    53 #if !defined(pthread_attr_default)
       
    54 #  define pthread_attr_default ((pthread_attr_t *)NULL)
       
    55 #endif
       
    56 #if !defined(pthread_mutexattr_default)
       
    57 #  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
       
    58 #endif
       
    59 #if !defined(pthread_condattr_default)
       
    60 #  define pthread_condattr_default ((pthread_condattr_t *)NULL)
       
    61 #endif
       
    62 
       
    63 
       
    64 /* Whether or not to use semaphores directly rather than emulating them with
       
    65  * mutexes and condition variables:
       
    66  */
       
    67 #if defined(_POSIX_SEMAPHORES) && !defined(HAVE_BROKEN_POSIX_SEMAPHORES)
       
    68 #  define USE_SEMAPHORES
       
    69 #else
       
    70 #  undef USE_SEMAPHORES
       
    71 #endif
       
    72 
       
    73 
       
    74 /* On platforms that don't use standard POSIX threads pthread_sigmask()
       
    75  * isn't present.  DEC threads uses sigprocmask() instead as do most
       
    76  * other UNIX International compliant systems that don't have the full
       
    77  * pthread implementation.
       
    78  */
       
    79 #if defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
       
    80 #  define SET_THREAD_SIGMASK pthread_sigmask
       
    81 #else
       
    82 #  define SET_THREAD_SIGMASK sigprocmask
       
    83 #endif
       
    84 
       
    85 
       
    86 /* A pthread mutex isn't sufficient to model the Python lock type
       
    87  * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
       
    88  * following are undefined:
       
    89  *  -> a thread tries to lock a mutex it already has locked
       
    90  *  -> a thread tries to unlock a mutex locked by a different thread
       
    91  * pthread mutexes are designed for serializing threads over short pieces
       
    92  * of code anyway, so wouldn't be an appropriate implementation of
       
    93  * Python's locks regardless.
       
    94  *
       
    95  * The pthread_lock struct implements a Python lock as a "locked?" bit
       
    96  * and a <condition, mutex> pair.  In general, if the bit can be acquired
       
    97  * instantly, it is, else the pair is used to block the thread until the
       
    98  * bit is cleared.     9 May 1994 tim@ksr.com
       
    99  */
       
   100 
       
   101 typedef struct {
       
   102 	char             locked; /* 0=unlocked, 1=locked */
       
   103 	/* a <cond, mutex> pair to handle an acquire of a locked lock */
       
   104 	pthread_cond_t   lock_released;
       
   105 	pthread_mutex_t  mut;
       
   106 } pthread_lock;
       
   107 
       
   108 #define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
       
   109 
       
   110 /*
       
   111  * Initialization.
       
   112  */
       
   113 
       
   114 #ifdef _HAVE_BSDI
       
   115 static
       
   116 void _noop(void)
       
   117 {
       
   118 }
       
   119 
       
   120 static void
       
   121 PyThread__init_thread(void)
       
   122 {
       
   123 	/* DO AN INIT BY STARTING THE THREAD */
       
   124 	static int dummy = 0;
       
   125 	pthread_t thread1;
       
   126 	pthread_create(&thread1, NULL, (void *) _noop, &dummy);
       
   127 	pthread_join(thread1, NULL);
       
   128 }
       
   129 
       
   130 #else /* !_HAVE_BSDI */
       
   131 
       
   132 static void
       
   133 PyThread__init_thread(void)
       
   134 {
       
   135 #if defined(_AIX) && defined(__GNUC__)
       
   136 	pthread_init();
       
   137 #endif
       
   138 }
       
   139 
       
   140 #endif /* !_HAVE_BSDI */
       
   141 
       
   142 /*
       
   143  * Thread support.
       
   144  */
       
   145 
       
   146 
       
   147 long
       
   148 PyThread_start_new_thread(void (*func)(void *), void *arg)
       
   149 {
       
   150 	pthread_t th;
       
   151 	int status;
       
   152 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
       
   153 	pthread_attr_t attrs;
       
   154 #endif
       
   155 #if defined(THREAD_STACK_SIZE)
       
   156 	size_t	tss;
       
   157 #endif
       
   158 
       
   159 	dprintf(("PyThread_start_new_thread called\n"));
       
   160 	if (!initialized)
       
   161 		PyThread_init_thread();
       
   162 
       
   163 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
       
   164 	if (pthread_attr_init(&attrs) != 0)
       
   165 		return -1;
       
   166 #endif
       
   167 #if defined(THREAD_STACK_SIZE)
       
   168 	tss = (_pythread_stacksize != 0) ? _pythread_stacksize
       
   169 					 : THREAD_STACK_SIZE;
       
   170 	if (tss != 0) {
       
   171 		if (pthread_attr_setstacksize(&attrs, tss) != 0) {
       
   172 			pthread_attr_destroy(&attrs);
       
   173 			return -1;
       
   174 		}
       
   175 	}
       
   176 #endif
       
   177 #if defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
       
   178         pthread_attr_setscope(&attrs, PTHREAD_SCOPE_SYSTEM);
       
   179 #endif
       
   180 
       
   181 	status = pthread_create(&th, 
       
   182 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
       
   183 				 &attrs,
       
   184 #else
       
   185 				 (pthread_attr_t*)NULL,
       
   186 #endif
       
   187 				 (void* (*)(void *))func,
       
   188 				 (void *)arg
       
   189 				 );
       
   190 
       
   191 #if defined(THREAD_STACK_SIZE) || defined(PTHREAD_SYSTEM_SCHED_SUPPORTED)
       
   192 	pthread_attr_destroy(&attrs);
       
   193 #endif
       
   194 	if (status != 0)
       
   195             return -1;
       
   196 
       
   197         pthread_detach(th);
       
   198 
       
   199 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
       
   200 	return (long) th;
       
   201 #else
       
   202 	return (long) *(long *) &th;
       
   203 #endif
       
   204 }
       
   205 
       
   206 /* XXX This implementation is considered (to quote Tim Peters) "inherently
       
   207    hosed" because:
       
   208      - It does not guarantee the promise that a non-zero integer is returned.
       
   209      - The cast to long is inherently unsafe.
       
   210      - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
       
   211        latter return statement (for Alpha OSF/1) are any longer necessary.
       
   212 */
       
   213 long 
       
   214 PyThread_get_thread_ident(void)
       
   215 {
       
   216 	volatile pthread_t threadid;
       
   217 	if (!initialized)
       
   218 		PyThread_init_thread();
       
   219 	/* Jump through some hoops for Alpha OSF/1 */
       
   220 	threadid = pthread_self();
       
   221 #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
       
   222 	return (long) threadid;
       
   223 #else
       
   224 	return (long) *(long *) &threadid;
       
   225 #endif
       
   226 }
       
   227 
       
   228 static void 
       
   229 do_PyThread_exit_thread(int no_cleanup)
       
   230 {
       
   231 	dprintf(("PyThread_exit_thread called\n"));
       
   232 	if (!initialized) {
       
   233 		if (no_cleanup)
       
   234 			_exit(0);
       
   235 		else
       
   236 			exit(0);
       
   237 	}
       
   238 }
       
   239 
       
   240 void 
       
   241 PyThread_exit_thread(void)
       
   242 {
       
   243 	do_PyThread_exit_thread(0);
       
   244 }
       
   245 
       
   246 void 
       
   247 PyThread__exit_thread(void)
       
   248 {
       
   249 	do_PyThread_exit_thread(1);
       
   250 }
       
   251 
       
   252 #ifndef NO_EXIT_PROG
       
   253 static void 
       
   254 do_PyThread_exit_prog(int status, int no_cleanup)
       
   255 {
       
   256 	dprintf(("PyThread_exit_prog(%d) called\n", status));
       
   257 	if (!initialized)
       
   258 		if (no_cleanup)
       
   259 			_exit(status);
       
   260 		else
       
   261 			exit(status);
       
   262 }
       
   263 
       
   264 void 
       
   265 PyThread_exit_prog(int status)
       
   266 {
       
   267 	do_PyThread_exit_prog(status, 0);
       
   268 }
       
   269 
       
   270 void 
       
   271 PyThread__exit_prog(int status)
       
   272 {
       
   273 	do_PyThread_exit_prog(status, 1);
       
   274 }
       
   275 #endif /* NO_EXIT_PROG */
       
   276 
       
   277 #ifdef USE_SEMAPHORES
       
   278 
       
   279 /*
       
   280  * Lock support.
       
   281  */
       
   282 
       
   283 PyThread_type_lock 
       
   284 PyThread_allocate_lock(void)
       
   285 {
       
   286 	sem_t *lock;
       
   287 	int status, error = 0;
       
   288 
       
   289 	dprintf(("PyThread_allocate_lock called\n"));
       
   290 	if (!initialized)
       
   291 		PyThread_init_thread();
       
   292 
       
   293 	lock = (sem_t *)malloc(sizeof(sem_t));
       
   294 
       
   295 	if (lock) {
       
   296 		status = sem_init(lock,0,1);
       
   297 		CHECK_STATUS("sem_init");
       
   298 
       
   299 		if (error) {
       
   300 			free((void *)lock);
       
   301 			lock = NULL;
       
   302 		}
       
   303 	}
       
   304 
       
   305 	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
       
   306 	return (PyThread_type_lock)lock;
       
   307 }
       
   308 
       
   309 void 
       
   310 PyThread_free_lock(PyThread_type_lock lock)
       
   311 {
       
   312 	sem_t *thelock = (sem_t *)lock;
       
   313 	int status, error = 0;
       
   314 
       
   315 	dprintf(("PyThread_free_lock(%p) called\n", lock));
       
   316 
       
   317 	if (!thelock)
       
   318 		return;
       
   319 
       
   320 	status = sem_destroy(thelock);
       
   321 	CHECK_STATUS("sem_destroy");
       
   322 
       
   323 	free((void *)thelock);
       
   324 }
       
   325 
       
   326 /*
       
   327  * As of February 2002, Cygwin thread implementations mistakenly report error
       
   328  * codes in the return value of the sem_ calls (like the pthread_ functions).
       
   329  * Correct implementations return -1 and put the code in errno. This supports
       
   330  * either.
       
   331  */
       
   332 static int
       
   333 fix_status(int status)
       
   334 {
       
   335 	return (status == -1) ? errno : status;
       
   336 }
       
   337 
       
   338 int 
       
   339 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
       
   340 {
       
   341 	int success;
       
   342 	sem_t *thelock = (sem_t *)lock;
       
   343 	int status, error = 0;
       
   344 
       
   345 	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
       
   346 
       
   347 	do {
       
   348 		if (waitflag)
       
   349 			status = fix_status(sem_wait(thelock));
       
   350 		else
       
   351 			status = fix_status(sem_trywait(thelock));
       
   352 	} while (status == EINTR); /* Retry if interrupted by a signal */
       
   353 
       
   354 	if (waitflag) {
       
   355 		CHECK_STATUS("sem_wait");
       
   356 	} else if (status != EAGAIN) {
       
   357 		CHECK_STATUS("sem_trywait");
       
   358 	}
       
   359 	
       
   360 	success = (status == 0) ? 1 : 0;
       
   361 
       
   362 	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
       
   363 	return success;
       
   364 }
       
   365 
       
   366 void 
       
   367 PyThread_release_lock(PyThread_type_lock lock)
       
   368 {
       
   369 	sem_t *thelock = (sem_t *)lock;
       
   370 	int status, error = 0;
       
   371 
       
   372 	dprintf(("PyThread_release_lock(%p) called\n", lock));
       
   373 
       
   374 	status = sem_post(thelock);
       
   375 	CHECK_STATUS("sem_post");
       
   376 }
       
   377 
       
   378 #else /* USE_SEMAPHORES */
       
   379 
       
   380 /*
       
   381  * Lock support.
       
   382  */
       
   383 PyThread_type_lock 
       
   384 PyThread_allocate_lock(void)
       
   385 {
       
   386 	pthread_lock *lock;
       
   387 	int status, error = 0;
       
   388 
       
   389 	dprintf(("PyThread_allocate_lock called\n"));
       
   390 	if (!initialized)
       
   391 		PyThread_init_thread();
       
   392 
       
   393 	lock = (pthread_lock *) malloc(sizeof(pthread_lock));
       
   394 	if (lock) {
       
   395 		memset((void *)lock, '\0', sizeof(pthread_lock));
       
   396 		lock->locked = 0;
       
   397 
       
   398 		status = pthread_mutex_init(&lock->mut,
       
   399 					    pthread_mutexattr_default);
       
   400 		CHECK_STATUS("pthread_mutex_init");
       
   401 
       
   402 		status = pthread_cond_init(&lock->lock_released,
       
   403 					   pthread_condattr_default);
       
   404 		CHECK_STATUS("pthread_cond_init");
       
   405 
       
   406 		if (error) {
       
   407 			free((void *)lock);
       
   408 			lock = 0;
       
   409 		}
       
   410 	}
       
   411 
       
   412 	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
       
   413 	return (PyThread_type_lock) lock;
       
   414 }
       
   415 
       
   416 void 
       
   417 PyThread_free_lock(PyThread_type_lock lock)
       
   418 {
       
   419 	pthread_lock *thelock = (pthread_lock *)lock;
       
   420 	int status, error = 0;
       
   421 
       
   422 	dprintf(("PyThread_free_lock(%p) called\n", lock));
       
   423 
       
   424 	status = pthread_mutex_destroy( &thelock->mut );
       
   425 	CHECK_STATUS("pthread_mutex_destroy");
       
   426 
       
   427 	status = pthread_cond_destroy( &thelock->lock_released );
       
   428 	CHECK_STATUS("pthread_cond_destroy");
       
   429 
       
   430 	free((void *)thelock);
       
   431 }
       
   432 
       
   433 int 
       
   434 PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
       
   435 {
       
   436 	int success;
       
   437 	pthread_lock *thelock = (pthread_lock *)lock;
       
   438 	int status, error = 0;
       
   439 
       
   440 	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
       
   441 
       
   442 	status = pthread_mutex_lock( &thelock->mut );
       
   443 	CHECK_STATUS("pthread_mutex_lock[1]");
       
   444 	success = thelock->locked == 0;
       
   445 
       
   446 	if ( !success && waitflag ) {
       
   447 		/* continue trying until we get the lock */
       
   448 
       
   449 		/* mut must be locked by me -- part of the condition
       
   450 		 * protocol */
       
   451 		while ( thelock->locked ) {
       
   452 			status = pthread_cond_wait(&thelock->lock_released,
       
   453 						   &thelock->mut);
       
   454 			CHECK_STATUS("pthread_cond_wait");
       
   455 		}
       
   456 		success = 1;
       
   457 	}
       
   458 	if (success) thelock->locked = 1;
       
   459 	status = pthread_mutex_unlock( &thelock->mut );
       
   460 	CHECK_STATUS("pthread_mutex_unlock[1]");
       
   461 
       
   462 	if (error) success = 0;
       
   463 	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
       
   464 	return success;
       
   465 }
       
   466 
       
   467 void 
       
   468 PyThread_release_lock(PyThread_type_lock lock)
       
   469 {
       
   470 	pthread_lock *thelock = (pthread_lock *)lock;
       
   471 	int status, error = 0;
       
   472 
       
   473 	dprintf(("PyThread_release_lock(%p) called\n", lock));
       
   474 
       
   475 	status = pthread_mutex_lock( &thelock->mut );
       
   476 	CHECK_STATUS("pthread_mutex_lock[3]");
       
   477 
       
   478 	thelock->locked = 0;
       
   479 
       
   480 	status = pthread_mutex_unlock( &thelock->mut );
       
   481 	CHECK_STATUS("pthread_mutex_unlock[3]");
       
   482 
       
   483 	/* wake up someone (anyone, if any) waiting on the lock */
       
   484 	status = pthread_cond_signal( &thelock->lock_released );
       
   485 	CHECK_STATUS("pthread_cond_signal");
       
   486 }
       
   487 
       
   488 #endif /* USE_SEMAPHORES */
       
   489 
       
   490 /* set the thread stack size.
       
   491  * Return 0 if size is valid, -1 if size is invalid,
       
   492  * -2 if setting stack size is not supported.
       
   493  */
       
   494 static int
       
   495 _pythread_pthread_set_stacksize(size_t size)
       
   496 {
       
   497 #if defined(THREAD_STACK_SIZE)
       
   498 	pthread_attr_t attrs;
       
   499 	size_t tss_min;
       
   500 	int rc = 0;
       
   501 #endif
       
   502 
       
   503 	/* set to default */
       
   504 	if (size == 0) {
       
   505 		_pythread_stacksize = 0;
       
   506 		return 0;
       
   507 	}
       
   508 
       
   509 #if defined(THREAD_STACK_SIZE)
       
   510 #if defined(PTHREAD_STACK_MIN)
       
   511 	tss_min = PTHREAD_STACK_MIN > THREAD_STACK_MIN ? PTHREAD_STACK_MIN
       
   512 						       : THREAD_STACK_MIN;
       
   513 #else
       
   514 	tss_min = THREAD_STACK_MIN;
       
   515 #endif
       
   516 	if (size >= tss_min) {
       
   517 		/* validate stack size by setting thread attribute */
       
   518 		if (pthread_attr_init(&attrs) == 0) {
       
   519 			rc = pthread_attr_setstacksize(&attrs, size);
       
   520 			pthread_attr_destroy(&attrs);
       
   521 			if (rc == 0) {
       
   522 				_pythread_stacksize = size;
       
   523 				return 0;
       
   524 			}
       
   525 		}
       
   526 	}
       
   527 	return -1;
       
   528 #else
       
   529 	return -2;
       
   530 #endif
       
   531 }
       
   532 
       
   533 #define THREAD_SET_STACKSIZE(x)	_pythread_pthread_set_stacksize(x)