home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / palmos / pippy-0.6beta-src.tar.gz / pippy-0.6beta-src.tar / pippy-0.6beta-src / src / Python / thread_pthread.h < prev    next >
C/C++ Source or Header  |  2000-12-21  |  12KB  |  445 lines

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