mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 03:04:41 +00:00 
			
		
		
		
	 7f14f0d8a0
			
		
	
	
		7f14f0d8a0
		
	
	
	
	
		
			
			svn+ssh://pythondev@svn.python.org/python/branches/py3k
................
  r81032 | antoine.pitrou | 2010-05-09 17:52:27 +0200 (dim., 09 mai 2010) | 9 lines
  Recorded merge of revisions 81029 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk
  ........
    r81029 | antoine.pitrou | 2010-05-09 16:46:46 +0200 (dim., 09 mai 2010) | 3 lines
    Untabify C files. Will watch buildbots.
  ........
................
		
	
			
		
			
				
	
	
		
			259 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			259 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <signal.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/wait.h>
 | |
| #include <sys/prctl.h>
 | |
| #include <ulocks.h>
 | |
| #include <errno.h>
 | |
| 
 | |
| #define HDR_SIZE        2680    /* sizeof(ushdr_t) */
 | |
| #define MAXPROC         100     /* max # of threads that can be started */
 | |
| 
 | |
| static usptr_t *shared_arena;
 | |
| static ulock_t count_lock;      /* protection for some variables */
 | |
| static ulock_t wait_lock;       /* lock used to wait for other threads */
 | |
| static int waiting_for_threads; /* protected by count_lock */
 | |
| static int nthreads;            /* protected by count_lock */
 | |
| static int exit_status;
 | |
| static int exiting;             /* we're already exiting (for maybe_exit) */
 | |
| static pid_t my_pid;            /* PID of main thread */
 | |
| static struct pidlist {
 | |
|     pid_t parent;
 | |
|     pid_t child;
 | |
| } pidlist[MAXPROC];     /* PIDs of other threads; protected by count_lock */
 | |
| static int maxpidindex;         /* # of PIDs in pidlist */
 | |
| /*
 | |
|  * Initialization.
 | |
|  */
 | |
| static void PyThread__init_thread(void)
 | |
| {
 | |
| #ifdef USE_DL
 | |
|     long addr, size;
 | |
| #endif /* USE_DL */
 | |
| 
 | |
| 
 | |
| #ifdef USE_DL
 | |
|     if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
 | |
|         perror("usconfig - CONF_INITSIZE (check)");
 | |
|     if (usconfig(CONF_INITSIZE, size) < 0)
 | |
|         perror("usconfig - CONF_INITSIZE (reset)");
 | |
|     addr = (long) dl_getrange(size + HDR_SIZE);
 | |
|     dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
 | |
|     errno = 0;
 | |
|     if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
 | |
|         perror("usconfig - CONF_ATTACHADDR (set)");
 | |
| #endif /* USE_DL */
 | |
|     if (usconfig(CONF_INITUSERS, 16) < 0)
 | |
|         perror("usconfig - CONF_INITUSERS");
 | |
|     my_pid = getpid();          /* so that we know which is the main thread */
 | |
|     if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
 | |
|         perror("usconfig - CONF_ARENATYPE");
 | |
|     usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
 | |
| #ifdef Py_DEBUG
 | |
|     if (thread_debug & 4)
 | |
|         usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
 | |
|     else if (thread_debug & 2)
 | |
|         usconfig(CONF_LOCKTYPE, US_DEBUG);
 | |
| #endif /* Py_DEBUG */
 | |
|     if ((shared_arena = usinit(tmpnam(0))) == 0)
 | |
|         perror("usinit");
 | |
| #ifdef USE_DL
 | |
|     if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
 | |
|         perror("usconfig - CONF_ATTACHADDR (reset)");
 | |
| #endif /* USE_DL */
 | |
|     if ((count_lock = usnewlock(shared_arena)) == NULL)
 | |
|         perror("usnewlock (count_lock)");
 | |
|     (void) usinitlock(count_lock);
 | |
|     if ((wait_lock = usnewlock(shared_arena)) == NULL)
 | |
|         perror("usnewlock (wait_lock)");
 | |
|     dprintf(("arena start: %p, arena size: %ld\n",  shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Thread support.
 | |
|  */
 | |
| 
 | |
| static void clean_threads(void)
 | |
| {
 | |
|     int i, j;
 | |
|     pid_t mypid, pid;
 | |
| 
 | |
|     /* clean up any exited threads */
 | |
|     mypid = getpid();
 | |
|     i = 0;
 | |
|     while (i < maxpidindex) {
 | |
|         if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
 | |
|             pid = waitpid(pid, 0, WNOHANG);
 | |
|             if (pid > 0) {
 | |
|                 /* a thread has exited */
 | |
|                 pidlist[i] = pidlist[--maxpidindex];
 | |
|                 /* remove references to children of dead proc */
 | |
|                 for (j = 0; j < maxpidindex; j++)
 | |
|                     if (pidlist[j].parent == pid)
 | |
|                         pidlist[j].child = -1;
 | |
|                 continue; /* don't increment i */
 | |
|             }
 | |
|         }
 | |
|         i++;
 | |
|     }
 | |
|     /* clean up the list */
 | |
|     i = 0;
 | |
|     while (i < maxpidindex) {
 | |
|         if (pidlist[i].child == -1) {
 | |
|             pidlist[i] = pidlist[--maxpidindex];
 | |
|             continue; /* don't increment i */
 | |
|         }
 | |
|         i++;
 | |
|     }
 | |
| }
 | |
| 
 | |
| long PyThread_start_new_thread(void (*func)(void *), void *arg)
 | |
| {
 | |
| #ifdef USE_DL
 | |
|     long addr, size;
 | |
|     static int local_initialized = 0;
 | |
| #endif /* USE_DL */
 | |
|     int success = 0;            /* init not needed when SOLARIS_THREADS and */
 | |
|                 /* C_THREADS implemented properly */
 | |
| 
 | |
|     dprintf(("PyThread_start_new_thread called\n"));
 | |
|     if (!initialized)
 | |
|         PyThread_init_thread();
 | |
|     switch (ussetlock(count_lock)) {
 | |
|     case 0: return 0;
 | |
|     case -1: perror("ussetlock (count_lock)");
 | |
|     }
 | |
|     if (maxpidindex >= MAXPROC)
 | |
|         success = -1;
 | |
|     else {
 | |
| #ifdef USE_DL
 | |
|         if (!local_initialized) {
 | |
|             if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
 | |
|                 perror("usconfig - CONF_INITSIZE (check)");
 | |
|             if (usconfig(CONF_INITSIZE, size) < 0)
 | |
|                 perror("usconfig - CONF_INITSIZE (reset)");
 | |
|             addr = (long) dl_getrange(size + HDR_SIZE);
 | |
|             dprintf(("trying to use addr %p-%p for sproc\n",
 | |
|                      addr, addr+size));
 | |
|             errno = 0;
 | |
|             if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
 | |
|                 errno != 0)
 | |
|                 perror("usconfig - CONF_ATTACHADDR (set)");
 | |
|         }
 | |
| #endif /* USE_DL */
 | |
|         clean_threads();
 | |
|         if ((success = sproc(func, PR_SALL, arg)) < 0)
 | |
|             perror("sproc");
 | |
| #ifdef USE_DL
 | |
|         if (!local_initialized) {
 | |
|             if (usconfig(CONF_ATTACHADDR, addr) < 0)
 | |
|                 /* reset address */
 | |
|                 perror("usconfig - CONF_ATTACHADDR (reset)");
 | |
|             local_initialized = 1;
 | |
|         }
 | |
| #endif /* USE_DL */
 | |
|         if (success >= 0) {
 | |
|             nthreads++;
 | |
|             pidlist[maxpidindex].parent = getpid();
 | |
|             pidlist[maxpidindex++].child = success;
 | |
|             dprintf(("pidlist[%d] = %d\n",
 | |
|                      maxpidindex-1, success));
 | |
|         }
 | |
|     }
 | |
|     if (usunsetlock(count_lock) < 0)
 | |
|         perror("usunsetlock (count_lock)");
 | |
|     return success;
 | |
| }
 | |
| 
 | |
| long PyThread_get_thread_ident(void)
 | |
| {
 | |
|     return getpid();
 | |
| }
 | |
| 
 | |
| void PyThread_exit_thread(void)
 | |
| {
 | |
|     dprintf(("PyThread_exit_thread called\n"));
 | |
|     if (!initialized)
 | |
|         exit(0);
 | |
|     if (ussetlock(count_lock) < 0)
 | |
|         perror("ussetlock (count_lock)");
 | |
|     nthreads--;
 | |
|     if (getpid() == my_pid) {
 | |
|         /* main thread; wait for other threads to exit */
 | |
|         exiting = 1;
 | |
|         waiting_for_threads = 1;
 | |
|         if (ussetlock(wait_lock) < 0)
 | |
|             perror("ussetlock (wait_lock)");
 | |
|         for (;;) {
 | |
|             if (nthreads < 0) {
 | |
|                 dprintf(("really exit (%d)\n", exit_status));
 | |
|                 exit(exit_status);
 | |
|             }
 | |
|             if (usunsetlock(count_lock) < 0)
 | |
|                 perror("usunsetlock (count_lock)");
 | |
|             dprintf(("waiting for other threads (%d)\n", nthreads));
 | |
|             if (ussetlock(wait_lock) < 0)
 | |
|                 perror("ussetlock (wait_lock)");
 | |
|             if (ussetlock(count_lock) < 0)
 | |
|                 perror("ussetlock (count_lock)");
 | |
|         }
 | |
|     }
 | |
|     /* not the main thread */
 | |
|     if (waiting_for_threads) {
 | |
|         dprintf(("main thread is waiting\n"));
 | |
|         if (usunsetlock(wait_lock) < 0)
 | |
|             perror("usunsetlock (wait_lock)");
 | |
|     }
 | |
|     if (usunsetlock(count_lock) < 0)
 | |
|         perror("usunsetlock (count_lock)");
 | |
|     _exit(0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Lock support.
 | |
|  */
 | |
| PyThread_type_lock PyThread_allocate_lock(void)
 | |
| {
 | |
|     ulock_t lock;
 | |
| 
 | |
|     dprintf(("PyThread_allocate_lock called\n"));
 | |
|     if (!initialized)
 | |
|         PyThread_init_thread();
 | |
| 
 | |
|     if ((lock = usnewlock(shared_arena)) == NULL)
 | |
|         perror("usnewlock");
 | |
|     (void) usinitlock(lock);
 | |
|     dprintf(("PyThread_allocate_lock() -> %p\n", lock));
 | |
|     return (PyThread_type_lock) lock;
 | |
| }
 | |
| 
 | |
| void PyThread_free_lock(PyThread_type_lock lock)
 | |
| {
 | |
|     dprintf(("PyThread_free_lock(%p) called\n", lock));
 | |
|     usfreelock((ulock_t) lock, shared_arena);
 | |
| }
 | |
| 
 | |
| int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
 | |
| {
 | |
|     int success;
 | |
| 
 | |
|     dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
 | |
|     errno = 0;                  /* clear it just in case */
 | |
|     if (waitflag)
 | |
|         success = ussetlock((ulock_t) lock);
 | |
|     else
 | |
|         success = uscsetlock((ulock_t) lock, 1); /* Try it once */
 | |
|     if (success < 0)
 | |
|         perror(waitflag ? "ussetlock" : "uscsetlock");
 | |
|     dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
 | |
|     return success;
 | |
| }
 | |
| 
 | |
| void PyThread_release_lock(PyThread_type_lock lock)
 | |
| {
 | |
|     dprintf(("PyThread_release_lock(%p) called\n", lock));
 | |
|     if (usunsetlock((ulock_t) lock) < 0)
 | |
|         perror("usunsetlock");
 | |
| }
 |