Python/thread.c patch for POSIX pthreads

Tim Peters (tim@ksr.com)
Sat, 07 May 94 17:46:05 -0400

The attached is crap, but works well enough so as not to be obviously
broken <ahem>. Warnings:

+ Unless you're running on a KSR machine, you'll want to find some way to
#define _POSIX_THREADS other than keying off #ifdef __ksr__.

+ If you are running on a KSR machine, the python link needs also to
specify "-para", after -lpthreads.

+ "configure" has to be fiddled to test for libpthreads, when
--with-thread is specified.

+ Due to misguided paternalism, POSIX doesn't want a thread to do
pthread_mutex_lock on a mutex that the thread already has locked. But
Guido doesn't write any code that _doesn't_ do that <wink>, so
pthread_mutex_lock can't be used directly in the waitflag==1 case of
acquire_lock. The attached uses a busy loop on pthread_mutex_trylock
instead, which sucks. Python's lock semantics should probably be
implemented as a combination of a POSIX condition variable and a POSIX
mutex; but I don't have the condition variable docs at hand, and don't
personally care how wasteful the busy loop is anyway.

+ The semaphore routines were fiddled just enough so that the compilation
doesn't blow up; they're 100% non-functional. But it doesn't appear
that anyone calls these routines, and there's no Python interface to
them in any case ...

what-the-world's-been-waiting-for-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp

*** thread.c Wed May 4 05:36:33 1994
--- ../../Python/thread.c Sat May 7 16:43:53 1994
***************
*** 30,35 ****
--- 30,39 ----
#define USE_DL
#endif

+ #ifdef __ksr__
+ #define _POSIX_THREADS
+ #endif
+
#ifdef HAVE_THREAD_H
#define SOLARIS
#endif
***************
*** 301,307 ****
#endif /* __sgi and USE_DL */
#ifdef _POSIX_THREADS
pthread_t th;
! #endif
int success = 0; /* init not needed when SOLARIS and */
/* C_THREADS implemented properly */

--- 305,311 ----
#endif /* __sgi and USE_DL */
#ifdef _POSIX_THREADS
pthread_t th;
! #endif /* _POSIX_THREADS */
int success = 0; /* init not needed when SOLARIS and */
/* C_THREADS implemented properly */

***************
*** 365,372 ****
(void) cthread_fork(func, arg);
#endif /* C_THREADS */
#ifdef _POSIX_THREADS
! pthread_create(&th, NULL, func, arg);
! #endif
return success < 0 ? 0 : 1;
}

--- 369,376 ----
(void) cthread_fork(func, arg);
#endif /* C_THREADS */
#ifdef _POSIX_THREADS
! success = pthread_create(&th, pthread_attr_default, func, arg);
! #endif /* _POSIX_THREADS */
return success < 0 ? 0 : 1;
}

***************
*** 507,512 ****
--- 511,520 ----
struct lock *lock;
extern char *malloc();
#endif
+ #ifdef _POSIX_THREADS
+ pthread_mutex_t *lock;
+ extern void *malloc();
+ #endif /* _POSIX_THREADS */

dprintf(("allocate_lock called\n"));
if (!initialized)
***************
*** 531,536 ****
--- 539,552 ----
(void) mon_create(&lock->lock_monitor);
(void) cv_create(&lock->lock_condvar, lock->lock_monitor);
#endif /* sun */
+ #ifdef _POSIX_THREADS
+ lock = (pthread_mutex_t *) malloc(sizeof(*lock));
+ if(pthread_mutex_init(lock, pthread_mutexattr_default)) {
+ perror("pthread_mutex_init");
+ free((void *) lock);
+ lock = 0;
+ }
+ #endif /* _POSIX_THREADS */
dprintf(("allocate_lock() -> %lx\n", (long)lock));
return (type_lock) lock;
}
***************
*** 549,554 ****
--- 565,576 ----
mon_destroy(((struct lock *) lock)->lock_monitor);
free((char *) lock);
#endif /* sun */
+ #ifdef _POSIX_THREADS
+ if (pthread_mutex_destroy((pthread_mutex_t *)lock)) {
+ perror("pthread_mutex_destroy");
+ }
+ free((void *)lock);
+ #endif /* _POSIX_THREADS */
}

int acquire_lock _P2(lock, type_lock lock, waitflag, int waitflag)
***************
*** 589,594 ****
--- 611,626 ----
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
#endif /* sun */
+ #ifdef _POSIX_THREADS
+ if (waitflag) {
+ do {
+ success = pthread_mutex_trylock((pthread_mutex_t *)lock);
+ } while (success == 0);
+ } else {
+ success = pthread_mutex_trylock((pthread_mutex_t *)lock);
+ }
+ if (success < 0) perror("pthread_mutex_trylock");
+ #endif /* _POSIX_THREADS */
dprintf(("acquire_lock(%lx, %d) -> %d\n", (long)lock, waitflag, success));
return success;
}
***************
*** 610,615 ****
--- 642,651 ----
cv_broadcast(((struct lock *) lock)->lock_condvar);
mon_exit(((struct lock *) lock)->lock_monitor);
#endif /* sun */
+ #ifdef _POSIX_THREADS
+ if (pthread_mutex_unlock((pthread_mutex_t *) lock))
+ perror("pthread_mutex_unlock");
+ #endif /* _POSIX_THREADS */
}

/*
***************
*** 626,632 ****
#ifdef sun
type_sema sema = 0;
#endif
!
dprintf(("allocate_sema called\n"));
if (!initialized)
init_thread();
--- 662,670 ----
#ifdef sun
type_sema sema = 0;
#endif
! #ifdef _POSIX_THREADS
! char *sema = 0;
! #endif
dprintf(("allocate_sema called\n"));
if (!initialized)
init_thread();

>>> END OF PATCH