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

  1.  
  2. /* GNU pth threads interface
  3.    http://www.gnu.org/software/pth
  4.    2000-05-03 Andy Dustman <andy@dustman.net>
  5.  
  6.    Adapted from Posix threads interface 
  7.    12 May 1997 -- david arnold <davida@pobox.com>
  8.  */
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <pth.h>
  13.  
  14. /* A pth mutex isn't sufficient to model the Python lock type
  15.  * because pth mutexes can be acquired multiple times by the
  16.  * same thread.
  17.  *
  18.  * The pth_lock struct implements a Python lock as a "locked?" bit
  19.  * and a <condition, mutex> pair.  In general, if the bit can be acquired
  20.  * instantly, it is, else the pair is used to block the thread until the
  21.  * bit is cleared.
  22.  */
  23.  
  24. typedef struct {
  25.     char             locked; /* 0=unlocked, 1=locked */
  26.     /* a <cond, mutex> pair to handle an acquire of a locked lock */
  27.     pth_cond_t   lock_released;
  28.     pth_mutex_t  mut;
  29. } pth_lock;
  30.  
  31. #define CHECK_STATUS(name)  if (status == -1) { printf("%d ", status); perror(name); error = 1; }
  32.  
  33. /*
  34.  * Initialization.
  35.  */
  36.  
  37. static void PyThread__init_thread(void)
  38. {
  39.     pth_init();
  40. }
  41.  
  42. /*
  43.  * Thread support.
  44.  */
  45.  
  46.  
  47. int PyThread_start_new_thread(void (*func)(void *), void *arg)
  48. {
  49.     pth_t th;
  50.     dprintf(("PyThread_start_new_thread called\n"));
  51.     if (!initialized)
  52.         PyThread_init_thread();
  53.  
  54.     th = pth_spawn(PTH_ATTR_DEFAULT,
  55.                  (void* (*)(void *))func,
  56.                  (void *)arg
  57.                  );
  58.  
  59.     return th == NULL ? 0 : 1;
  60. }
  61.  
  62. long PyThread_get_thread_ident(void)
  63. {
  64.     volatile pth_t threadid;
  65.     if (!initialized)
  66.         PyThread_init_thread();
  67.     /* Jump through some hoops for Alpha OSF/1 */
  68.     threadid = pth_self();
  69.     return (long) *(long *) &threadid;
  70. }
  71.  
  72. static void do_PyThread_exit_thread(int no_cleanup)
  73. {
  74.     dprintf(("PyThread_exit_thread called\n"));
  75.     if (!initialized) {
  76.         if (no_cleanup)
  77.             _exit(0);
  78.         else
  79.             exit(0);
  80.     }
  81. }
  82.  
  83. void PyThread_exit_thread(void)
  84. {
  85.     do_PyThread_exit_thread(0);
  86. }
  87.  
  88. void PyThread__exit_thread(void)
  89. {
  90.     do_PyThread_exit_thread(1);
  91. }
  92.  
  93. #ifndef NO_EXIT_PROG
  94. static void do_PyThread_exit_prog(int status, int no_cleanup)
  95. {
  96.     dprintf(("PyThread_exit_prog(%d) called\n", status));
  97.     if (!initialized)
  98.         if (no_cleanup)
  99.             _exit(status);
  100.         else
  101.             exit(status);
  102. }
  103.  
  104. void PyThread_exit_prog(int status)
  105. {
  106.     do_PyThread_exit_prog(status, 0);
  107. }
  108.  
  109. void PyThread__exit_prog(int status)
  110. {
  111.     do_PyThread_exit_prog(status, 1);
  112. }
  113. #endif /* NO_EXIT_PROG */
  114.  
  115. /*
  116.  * Lock support.
  117.  */
  118. PyThread_type_lock PyThread_allocate_lock(void)
  119. {
  120.     pth_lock *lock;
  121.     int status, error = 0;
  122.  
  123.     dprintf(("PyThread_allocate_lock called\n"));
  124.     if (!initialized)
  125.         PyThread_init_thread();
  126.  
  127.     lock = (pth_lock *) malloc(sizeof(pth_lock));
  128.         memset((void *)lock, '\0', sizeof(pth_lock));
  129.     if (lock) {
  130.         lock->locked = 0;
  131.         status = pth_mutex_init(&lock->mut);
  132.         CHECK_STATUS("pth_mutex_init");
  133.         status = pth_cond_init(&lock->lock_released);
  134.         CHECK_STATUS("pth_cond_init");
  135.         if (error) {
  136.             free((void *)lock);
  137.             lock = NULL;
  138.         }
  139.     }
  140.     dprintf(("PyThread_allocate_lock() -> %p\n", lock));
  141.     return (PyThread_type_lock) lock;
  142. }
  143.  
  144. void PyThread_free_lock(PyThread_type_lock lock)
  145. {
  146.     pth_lock *thelock = (pth_lock *)lock;
  147.  
  148.     dprintf(("PyThread_free_lock(%p) called\n", lock));
  149.  
  150.     free((void *)thelock);
  151. }
  152.  
  153. int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
  154. {
  155.     int success;
  156.     pth_lock *thelock = (pth_lock *)lock;
  157.     int status, error = 0;
  158.  
  159.     dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
  160.  
  161.     status = pth_mutex_acquire(&thelock->mut, !waitflag, NULL);
  162.     CHECK_STATUS("pth_mutex_acquire[1]");
  163.     success = thelock->locked == 0;
  164.         if (success) thelock->locked = 1;
  165.         status = pth_mutex_release( &thelock->mut );
  166.         CHECK_STATUS("pth_mutex_release[1]");
  167.  
  168.         if ( !success && waitflag ) {
  169.                 /* continue trying until we get the lock */
  170.  
  171.                 /* mut must be locked by me -- part of the condition
  172.                  * protocol */
  173.                 status = pth_mutex_acquire( &thelock->mut, !waitflag, NULL );
  174.                 CHECK_STATUS("pth_mutex_acquire[2]");
  175.                 while ( thelock->locked ) {
  176.                         status = pth_cond_await(&thelock->lock_released,
  177.                                                 &thelock->mut, NULL);
  178.                         CHECK_STATUS("pth_cond_await");
  179.                 }
  180.                 thelock->locked = 1;
  181.                 status = pth_mutex_release( &thelock->mut );
  182.                 CHECK_STATUS("pth_mutex_release[2]");
  183.                 success = 1;
  184.         }
  185.         if (error) success = 0;
  186.         dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
  187.     return success;
  188. }
  189.  
  190. void PyThread_release_lock(PyThread_type_lock lock)
  191. {
  192.         pth_lock *thelock = (pth_lock *)lock;
  193.         int status, error = 0;
  194.  
  195.         dprintf(("PyThread_release_lock(%p) called\n", lock));
  196.  
  197.         status = pth_mutex_acquire( &thelock->mut, 0, NULL );
  198.         CHECK_STATUS("pth_mutex_acquire[3]");
  199.  
  200.         thelock->locked = 0;
  201.  
  202.         status = pth_mutex_release( &thelock->mut );
  203.         CHECK_STATUS("pth_mutex_release[3]");
  204.  
  205.         /* wake up someone (anyone, if any) waiting on the lock */
  206.         status = pth_cond_notify( &thelock->lock_released, 0 );
  207.         CHECK_STATUS("pth_cond_notify");
  208. }
  209.  
  210. /*
  211.  * Semaphore support.
  212.  */
  213.  
  214. struct semaphore {
  215.     pth_mutex_t mutex;
  216.     pth_cond_t cond;
  217.     int value;
  218. };
  219.  
  220. PyThread_type_sema PyThread_allocate_sema(int value)
  221. {
  222.     struct semaphore *sema;
  223.     int status, error = 0;
  224.  
  225.     dprintf(("PyThread_allocate_sema called\n"));
  226.     if (!initialized)
  227.         PyThread_init_thread();
  228.  
  229.     sema = (struct semaphore *) malloc(sizeof(struct semaphore));
  230.     if (sema != NULL) {
  231.         sema->value = value;
  232.         status = pth_mutex_init(&sema->mutex);
  233.         CHECK_STATUS("pth_mutex_init");
  234.         status = pth_cond_init(&sema->cond);
  235.         CHECK_STATUS("pth_mutex_init");
  236.         if (error) {
  237.             free((void *) sema);
  238.             sema = NULL;
  239.         }
  240.     }
  241.     dprintf(("PyThread_allocate_sema() -> %p\n",  sema));
  242.     return (PyThread_type_sema) sema;
  243. }
  244.  
  245. void PyThread_free_sema(PyThread_type_sema sema)
  246. {
  247.     struct semaphore *thesema = (struct semaphore *) sema;
  248.  
  249.     dprintf(("PyThread_free_sema(%p) called\n",  sema));
  250.     free((void *) thesema);
  251. }
  252.  
  253. int PyThread_down_sema(PyThread_type_sema sema, int waitflag)
  254. {
  255.     int status, error = 0, success;
  256.     struct semaphore *thesema = (struct semaphore *) sema;
  257.  
  258.     dprintf(("PyThread_down_sema(%p, %d) called\n",  sema, waitflag));
  259.     status = pth_mutex_acquire(&thesema->mutex, !waitflag, NULL);
  260.     CHECK_STATUS("pth_mutex_acquire");
  261.     if (waitflag) {
  262.         while (!error && thesema->value <= 0) {
  263.             status = pth_cond_await(&thesema->cond,
  264.                         &thesema->mutex, NULL);
  265.             CHECK_STATUS("pth_cond_await");
  266.         }
  267.     }
  268.     if (error)
  269.         success = 0;
  270.     else if (thesema->value > 0) {
  271.         thesema->value--;
  272.         success = 1;
  273.     }
  274.     else
  275.         success = 0;
  276.     status = pth_mutex_release(&thesema->mutex);
  277.     CHECK_STATUS("pth_mutex_release");
  278.     dprintf(("PyThread_down_sema(%p) return\n",  sema));
  279.     return success;
  280. }
  281.  
  282. void PyThread_up_sema(PyThread_type_sema sema)
  283. {
  284.     int status, error = 0;
  285.     struct semaphore *thesema = (struct semaphore *) sema;
  286.  
  287.     dprintf(("PyThread_up_sema(%p)\n",  sema));
  288.     status = pth_mutex_acquire(&thesema->mutex, 0, NULL);
  289.     CHECK_STATUS("pth_mutex_acquire");
  290.     thesema->value++;
  291.     status = pth_cond_notify(&thesema->cond, 1);
  292.     CHECK_STATUS("pth_cond_notify");
  293.     status = pth_mutex_release(&thesema->mutex);
  294.     CHECK_STATUS("pth_mutex_release");
  295. }
  296.