home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 15 / AACD15.ISO / AACD / Programming / Python2 / Python20_source / Python / thread_pthread.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-25  |  10.6 KB  |  445 lines

  1.  
  2. /* Posix threads interface */
  3.  
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <pthread.h>
  7.  
  8.  
  9. /* try to determine what version of the Pthread Standard is installed.
  10.  * this is important, since all sorts of parameter types changed from
  11.  * draft to draft and there are several (incompatible) drafts in
  12.  * common use.  these macros are a start, at least. 
  13.  * 12 May 1997 -- david arnold <davida@pobox.com>
  14.  */
  15.  
  16. #if defined(__ultrix) && defined(__mips) && defined(_DECTHREADS_)
  17. /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
  18. #  define PY_PTHREAD_D4
  19.  
  20. #elif defined(__osf__) && defined (__alpha)
  21. /* _DECTHREADS_ is defined in cma.h which is included by pthread.h */
  22. #  if !defined(_PTHREAD_ENV_ALPHA) || defined(_PTHREAD_USE_D4) || defined(PTHREAD_USE_D4)
  23. #    define PY_PTHREAD_D4
  24. #  else
  25. #    define PY_PTHREAD_STD
  26. #  endif
  27.  
  28. #elif defined(_AIX)
  29. /* SCHED_BG_NP is defined if using AIX DCE pthreads
  30.  * but it is unsupported by AIX 4 pthreads. Default
  31.  * attributes for AIX 4 pthreads equal to NULL. For
  32.  * AIX DCE pthreads they should be left unchanged.
  33.  */
  34. #  if !defined(SCHED_BG_NP)
  35. #    define PY_PTHREAD_STD
  36. #  else
  37. #    define PY_PTHREAD_D7
  38. #  endif
  39.  
  40. #elif defined(__DGUX)
  41. #  define PY_PTHREAD_D6
  42.  
  43. #elif defined(__hpux) && defined(_DECTHREADS_)
  44. #  define PY_PTHREAD_D4
  45.  
  46. #else /* Default case */
  47. #  define PY_PTHREAD_STD
  48.  
  49. #endif
  50.  
  51.  
  52. /* set default attribute object for different versions */
  53.  
  54. #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D7)
  55. #  define pthread_attr_default pthread_attr_default
  56. #  define pthread_mutexattr_default pthread_mutexattr_default
  57. #  define pthread_condattr_default pthread_condattr_default
  58. #elif defined(PY_PTHREAD_STD) || defined(PY_PTHREAD_D6)
  59. #  define pthread_attr_default ((pthread_attr_t *)NULL)
  60. #  define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL)
  61. #  define pthread_condattr_default ((pthread_condattr_t *)NULL)
  62. #endif
  63.  
  64.  
  65. /* A pthread mutex isn't sufficient to model the Python lock type
  66.  * because, according to Draft 5 of the docs (P1003.4a/D5), both of the
  67.  * following are undefined:
  68.  *  -> a thread tries to lock a mutex it already has locked
  69.  *  -> a thread tries to unlock a mutex locked by a different thread
  70.  * pthread mutexes are designed for serializing threads over short pieces
  71.  * of code anyway, so wouldn't be an appropriate implementation of
  72.  * Python's locks regardless.
  73.  *
  74.  * The pthread_lock struct implements a Python lock as a "locked?" bit
  75.  * and a <condition, mutex> pair.  In general, if the bit can be acquired
  76.  * instantly, it is, else the pair is used to block the thread until the
  77.  * bit is cleared.     9 May 1994 tim@ksr.com
  78.  */
  79.  
  80. typedef struct {
  81.     char             locked; /* 0=unlocked, 1=locked */
  82.     /* a <cond, mutex> pair to handle an acquire of a locked lock */
  83.     pthread_cond_t   lock_released;
  84.     pthread_mutex_t  mut;
  85. } pthread_lock;
  86.  
  87. #define CHECK_STATUS(name)  if (status != 0) { perror(name); error = 1; }
  88.  
  89. /*
  90.  * Initialization.
  91.  */
  92.  
  93. #ifdef _HAVE_BSDI
  94. static
  95. void _noop(void)
  96. {
  97. }
  98.  
  99. static void
  100. PyThread__init_thread(void)
  101. {
  102.     /* DO AN INIT BY STARTING THE THREAD */
  103.     static int dummy = 0;
  104.     pthread_t thread1;
  105.     pthread_create(&thread1, NULL, (void *) _noop, &dummy);
  106.     pthread_join(thread1, NULL);
  107. }
  108.  
  109. #else /* !_HAVE_BSDI */
  110.  
  111. static void
  112. PyThread__init_thread(void)
  113. {
  114. #if defined(_AIX) && defined(__GNUC__)
  115.     pthread_init();
  116. #endif
  117. }
  118.  
  119. #endif /* !_HAVE_BSDI */
  120.  
  121. /*
  122.  * Thread support.
  123.  */
  124.  
  125.  
  126. int 
  127. PyThread_start_new_thread(void (*func)(void *), void *arg)
  128. {
  129.     pthread_t th;
  130.     int success;
  131.     dprintf(("PyThread_start_new_thread called\n"));
  132.     if (!initialized)
  133.         PyThread_init_thread();
  134.  
  135.     success = pthread_create(&th, 
  136. #if defined(PY_PTHREAD_D4)
  137.                  pthread_attr_default,
  138.                  (pthread_startroutine_t)func, 
  139.                  (pthread_addr_t)arg
  140. #elif defined(PY_PTHREAD_D6)
  141.                  pthread_attr_default,
  142.                  (void* (*)(void *))func,
  143.                  arg
  144. #elif defined(PY_PTHREAD_D7)
  145.                  pthread_attr_default,
  146.                  func,
  147.                  arg
  148. #elif defined(PY_PTHREAD_STD)
  149.                  (pthread_attr_t*)NULL,
  150.                  (void* (*)(void *))func,
  151.                  (void *)arg
  152. #endif
  153.                  );
  154.  
  155.     if (success == 0) {
  156. #if defined(PY_PTHREAD_D4) || defined(PY_PTHREAD_D6) || defined(PY_PTHREAD_D7)
  157.         pthread_detach(&th);
  158. #elif defined(PY_PTHREAD_STD)
  159.         pthread_detach(th);
  160. #endif
  161.     }
  162.     return success != 0 ? 0 : 1;
  163. }
  164.  
  165. /* XXX This implementation is considered (to quote Tim Peters) "inherently
  166.    hosed" because:
  167.      - It does not guanrantee the promise that a non-zero integer is returned.
  168.      - The cast to long is inherently unsafe.
  169.      - It is not clear that the 'volatile' (for AIX?) and ugly casting in the
  170.        latter return statement (for Alpha OSF/1) are any longer necessary.
  171. */
  172. long 
  173. PyThread_get_thread_ident(void)
  174. {
  175.     volatile pthread_t threadid;
  176.     if (!initialized)
  177.         PyThread_init_thread();
  178.     /* Jump through some hoops for Alpha OSF/1 */
  179.     threadid = pthread_self();
  180. #if SIZEOF_PTHREAD_T <= SIZEOF_LONG
  181.     return (long) threadid;
  182. #else
  183.     return (long) *(long *) &threadid;
  184. #endif
  185. }
  186.  
  187. static void 
  188. do_PyThread_exit_thread(int no_cleanup)
  189. {
  190.     dprintf(("PyThread_exit_thread called\n"));
  191.     if (!initialized) {
  192.         if (no_cleanup)
  193.             _exit(0);
  194.         else
  195.             exit(0);
  196.     }
  197. }
  198.  
  199. void 
  200. PyThread_exit_thread(void)
  201. {
  202.     do_PyThread_exit_thread(0);
  203. }
  204.  
  205. void 
  206. PyThread__exit_thread(void)
  207. {
  208.     do_PyThread_exit_thread(1);
  209. }
  210.  
  211. #ifndef NO_EXIT_PROG
  212. static void 
  213. do_PyThread_exit_prog(int status, int no_cleanup)
  214. {
  215.     dprintf(("PyThread_exit_prog(%d) called\n", status));
  216.     if (!initialized)
  217.         if (no_cleanup)
  218.             _exit(status);
  219.         else
  220.             exit(status);
  221. }
  222.  
  223. void 
  224. PyThread_exit_prog(int status)
  225. {
  226.     do_PyThread_exit_prog(status, 0);
  227. }
  228.  
  229. void 
  230. PyThread__exit_prog(int status)
  231. {
  232.     do_PyThread_exit_prog(status, 1);
  233. }
  234. #endif /* NO_EXIT_PROG */
  235.  
  236. /*
  237.  * Lock support.
  238.  */
  239. PyThread_type_lock 
  240. PyThread_allocate_lock(void)
  241. {
  242.     pthread_lock *lock;
  243.     int status, error = 0;
  244.  
  245.     dprintf(("PyThread_allocate_lock called\n"));
  246.     if (!initialized)
  247.         PyThread_init_thread();
  248.  
  249.     lock = (pthread_lock *) malloc(sizeof(pthread_lock));
  250.     memset((void *)lock, '\0', sizeof(pthread_lock));
  251.     if (lock) {
  252.         lock->locked = 0;
  253.  
  254.         status = pthread_mutex_init(&lock->mut,
  255.                         pthread_mutexattr_default);
  256.         CHECK_STATUS("pthread_mutex_init");
  257.  
  258.         status = pthread_cond_init(&lock->lock_released,
  259.                        pthread_condattr_default);
  260.         CHECK_STATUS("pthread_cond_init");
  261.  
  262.         if (error) {
  263.             free((void *)lock);
  264.             lock = 0;
  265.         }
  266.     }
  267.  
  268.     dprintf(("PyThread_allocate_lock() -> %p\n", lock));
  269.     return (PyThread_type_lock) lock;
  270. }
  271.  
  272. void 
  273. PyThread_free_lock(PyThread_type_lock lock)
  274. {
  275.     pthread_lock *thelock = (pthread_lock *)lock;
  276.     int status, error = 0;
  277.  
  278.     dprintf(("PyThread_free_lock(%p) called\n", lock));
  279.  
  280.     status = pthread_mutex_destroy( &thelock->mut );
  281.     CHECK_STATUS("pthread_mutex_destroy");
  282.  
  283.     status = pthread_cond_destroy( &thelock->lock_released );
  284.     CHECK_STATUS("pthread_cond_destroy");
  285.  
  286.     free((void *)thelock);
  287. }
  288.  
  289. int 
  290. PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
  291. {
  292.     int success;
  293.     pthread_lock *thelock = (pthread_lock *)lock;
  294.     int status, error = 0;
  295.  
  296.     dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
  297.  
  298.     status = pthread_mutex_lock( &thelock->mut );
  299.     CHECK_STATUS("pthread_mutex_lock[1]");
  300.     success = thelock->locked == 0;
  301.     if (success) thelock->locked = 1;
  302.     status = pthread_mutex_unlock( &thelock->mut );
  303.     CHECK_STATUS("pthread_mutex_unlock[1]");
  304.  
  305.     if ( !success && waitflag ) {
  306.         /* continue trying until we get the lock */
  307.  
  308.         /* mut must be locked by me -- part of the condition
  309.          * protocol */
  310.         status = pthread_mutex_lock( &thelock->mut );
  311.         CHECK_STATUS("pthread_mutex_lock[2]");
  312.         while ( thelock->locked ) {
  313.             status = pthread_cond_wait(&thelock->lock_released,
  314.                            &thelock->mut);
  315.             CHECK_STATUS("pthread_cond_wait");
  316.         }
  317.         thelock->locked = 1;
  318.         status = pthread_mutex_unlock( &thelock->mut );
  319.         CHECK_STATUS("pthread_mutex_unlock[2]");
  320.         success = 1;
  321.     }
  322.     if (error) success = 0;
  323.     dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
  324.     return success;
  325. }
  326.  
  327. void 
  328. PyThread_release_lock(PyThread_type_lock lock)
  329. {
  330.     pthread_lock *thelock = (pthread_lock *)lock;
  331.     int status, error = 0;
  332.  
  333.     dprintf(("PyThread_release_lock(%p) called\n", lock));
  334.  
  335.     status = pthread_mutex_lock( &thelock->mut );
  336.     CHECK_STATUS("pthread_mutex_lock[3]");
  337.  
  338.     thelock->locked = 0;
  339.  
  340.     status = pthread_mutex_unlock( &thelock->mut );
  341.     CHECK_STATUS("pthread_mutex_unlock[3]");
  342.  
  343.     /* wake up someone (anyone, if any) waiting on the lock */
  344.     status = pthread_cond_signal( &thelock->lock_released );
  345.     CHECK_STATUS("pthread_cond_signal");
  346. }
  347.  
  348. /*
  349.  * Semaphore support.
  350.  */
  351.  
  352. struct semaphore {
  353.     pthread_mutex_t mutex;
  354.     pthread_cond_t cond;
  355.     int value;
  356. };
  357.  
  358. PyThread_type_sema 
  359. PyThread_allocate_sema(int value)
  360. {
  361.     struct semaphore *sema;
  362.     int status, error = 0;
  363.  
  364.     dprintf(("PyThread_allocate_sema called\n"));
  365.     if (!initialized)
  366.         PyThread_init_thread();
  367.  
  368.     sema = (struct semaphore *) malloc(sizeof(struct semaphore));
  369.     if (sema != NULL) {
  370.         sema->value = value;
  371.         status = pthread_mutex_init(&sema->mutex,
  372.                         pthread_mutexattr_default);
  373.         CHECK_STATUS("pthread_mutex_init");
  374.         status = pthread_cond_init(&sema->cond,
  375.                        pthread_condattr_default);
  376.         CHECK_STATUS("pthread_cond_init");
  377.         if (error) {
  378.             free((void *) sema);
  379.             sema = NULL;
  380.         }
  381.     }
  382.     dprintf(("PyThread_allocate_sema() -> %p\n",  sema));
  383.     return (PyThread_type_sema) sema;
  384. }
  385.  
  386. void 
  387. PyThread_free_sema(PyThread_type_sema sema)
  388. {
  389.     int status, error = 0;
  390.     struct semaphore *thesema = (struct semaphore *) sema;
  391.  
  392.     dprintf(("PyThread_free_sema(%p) called\n",  sema));
  393.     status = pthread_cond_destroy(&thesema->cond);
  394.     CHECK_STATUS("pthread_cond_destroy");
  395.     status = pthread_mutex_destroy(&thesema->mutex);
  396.     CHECK_STATUS("pthread_mutex_destroy");
  397.     free((void *) thesema);
  398. }
  399.  
  400. int 
  401. PyThread_down_sema(PyThread_type_sema sema, int waitflag)
  402. {
  403.     int status, error = 0, success;
  404.     struct semaphore *thesema = (struct semaphore *) sema;
  405.  
  406.     dprintf(("PyThread_down_sema(%p, %d) called\n",  sema, waitflag));
  407.     status = pthread_mutex_lock(&thesema->mutex);
  408.     CHECK_STATUS("pthread_mutex_lock");
  409.     if (waitflag) {
  410.         while (!error && thesema->value <= 0) {
  411.             status = pthread_cond_wait(&thesema->cond,
  412.                            &thesema->mutex);
  413.             CHECK_STATUS("pthread_cond_wait");
  414.         }
  415.     }
  416.     if (error)
  417.         success = 0;
  418.     else if (thesema->value > 0) {
  419.         thesema->value--;
  420.         success = 1;
  421.     }
  422.     else
  423.         success = 0;
  424.     status = pthread_mutex_unlock(&thesema->mutex);
  425.     CHECK_STATUS("pthread_mutex_unlock");
  426.     dprintf(("PyThread_down_sema(%p) return\n",  sema));
  427.     return success;
  428. }
  429.  
  430. void 
  431. PyThread_up_sema(PyThread_type_sema sema)
  432. {
  433.     int status, error = 0;
  434.     struct semaphore *thesema = (struct semaphore *) sema;
  435.  
  436.     dprintf(("PyThread_up_sema(%p)\n",  sema));
  437.     status = pthread_mutex_lock(&thesema->mutex);
  438.     CHECK_STATUS("pthread_mutex_lock");
  439.     thesema->value++;
  440.     status = pthread_cond_signal(&thesema->cond);
  441.     CHECK_STATUS("pthread_cond_signal");
  442.     status = pthread_mutex_unlock(&thesema->mutex);
  443.     CHECK_STATUS("pthread_mutex_unlock");
  444. }
  445.