symbian-qemu-0.9.1-12/python-2.6.1/Python/thread_sgi.h
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 
       
     2 #include <stdlib.h>
       
     3 #include <stdio.h>
       
     4 #include <signal.h>
       
     5 #include <sys/types.h>
       
     6 #include <sys/wait.h>
       
     7 #include <sys/prctl.h>
       
     8 #include <ulocks.h>
       
     9 #include <errno.h>
       
    10 
       
    11 #define HDR_SIZE	2680	/* sizeof(ushdr_t) */
       
    12 #define MAXPROC		100	/* max # of threads that can be started */
       
    13 
       
    14 static usptr_t *shared_arena;
       
    15 static ulock_t count_lock;	/* protection for some variables */
       
    16 static ulock_t wait_lock;	/* lock used to wait for other threads */
       
    17 static int waiting_for_threads;	/* protected by count_lock */
       
    18 static int nthreads;		/* protected by count_lock */
       
    19 static int exit_status;
       
    20 #ifndef NO_EXIT_PROG
       
    21 static int do_exit;		/* indicates that the program is to exit */
       
    22 #endif
       
    23 static int exiting;		/* we're already exiting (for maybe_exit) */
       
    24 static pid_t my_pid;		/* PID of main thread */
       
    25 static struct pidlist {
       
    26 	pid_t parent;
       
    27 	pid_t child;
       
    28 } pidlist[MAXPROC];	/* PIDs of other threads; protected by count_lock */
       
    29 static int maxpidindex;		/* # of PIDs in pidlist */
       
    30 
       
    31 #ifndef NO_EXIT_PROG
       
    32 /*
       
    33  * This routine is called as a signal handler when another thread
       
    34  * exits.  When that happens, we must see whether we have to exit as
       
    35  * well (because of an PyThread_exit_prog()) or whether we should continue on.
       
    36  */
       
    37 static void exit_sig(void)
       
    38 {
       
    39 	d2printf(("exit_sig called\n"));
       
    40 	if (exiting && getpid() == my_pid) {
       
    41 		d2printf(("already exiting\n"));
       
    42 		return;
       
    43 	}
       
    44 	if (do_exit) {
       
    45 		d2printf(("exiting in exit_sig\n"));
       
    46 #ifdef Py_DEBUG
       
    47 		if ((thread_debug & 8) == 0)
       
    48 			thread_debug &= ~1; /* don't produce debug messages */
       
    49 #endif
       
    50 		PyThread_exit_thread();
       
    51 	}
       
    52 }
       
    53 
       
    54 /*
       
    55  * This routine is called when a process calls exit().  If that wasn't
       
    56  * done from the library, we do as if an PyThread_exit_prog() was intended.
       
    57  */
       
    58 static void maybe_exit(void)
       
    59 {
       
    60 	dprintf(("maybe_exit called\n"));
       
    61 	if (exiting) {
       
    62 		dprintf(("already exiting\n"));
       
    63 		return;
       
    64 	}
       
    65 	PyThread_exit_prog(0);
       
    66 }
       
    67 #endif /* NO_EXIT_PROG */
       
    68 
       
    69 /*
       
    70  * Initialization.
       
    71  */
       
    72 static void PyThread__init_thread(void)
       
    73 {
       
    74 #ifndef NO_EXIT_PROG
       
    75 	struct sigaction s;
       
    76 #endif /* NO_EXIT_PROG */
       
    77 #ifdef USE_DL
       
    78 	long addr, size;
       
    79 #endif /* USE_DL */
       
    80 
       
    81 
       
    82 #ifdef USE_DL
       
    83 	if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
       
    84 		perror("usconfig - CONF_INITSIZE (check)");
       
    85 	if (usconfig(CONF_INITSIZE, size) < 0)
       
    86 		perror("usconfig - CONF_INITSIZE (reset)");
       
    87 	addr = (long) dl_getrange(size + HDR_SIZE);
       
    88 	dprintf(("trying to use addr %p-%p for shared arena\n", addr, addr+size));
       
    89 	errno = 0;
       
    90 	if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 && errno != 0)
       
    91 		perror("usconfig - CONF_ATTACHADDR (set)");
       
    92 #endif /* USE_DL */
       
    93 	if (usconfig(CONF_INITUSERS, 16) < 0)
       
    94 		perror("usconfig - CONF_INITUSERS");
       
    95 	my_pid = getpid();	/* so that we know which is the main thread */
       
    96 #ifndef NO_EXIT_PROG
       
    97 	atexit(maybe_exit);
       
    98 	s.sa_handler = exit_sig;
       
    99 	sigemptyset(&s.sa_mask);
       
   100 	/*sigaddset(&s.sa_mask, SIGUSR1);*/
       
   101 	s.sa_flags = 0;
       
   102 	sigaction(SIGUSR1, &s, 0);
       
   103 	if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
       
   104 		perror("prctl - PR_SETEXITSIG");
       
   105 #endif /* NO_EXIT_PROG */
       
   106 	if (usconfig(CONF_ARENATYPE, US_SHAREDONLY) < 0)
       
   107 		perror("usconfig - CONF_ARENATYPE");
       
   108 	usconfig(CONF_LOCKTYPE, US_DEBUG); /* XXX */
       
   109 #ifdef Py_DEBUG
       
   110 	if (thread_debug & 4)
       
   111 		usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
       
   112 	else if (thread_debug & 2)
       
   113 		usconfig(CONF_LOCKTYPE, US_DEBUG);
       
   114 #endif /* Py_DEBUG */
       
   115 	if ((shared_arena = usinit(tmpnam(0))) == 0)
       
   116 		perror("usinit");
       
   117 #ifdef USE_DL
       
   118 	if (usconfig(CONF_ATTACHADDR, addr) < 0) /* reset address */
       
   119 		perror("usconfig - CONF_ATTACHADDR (reset)");
       
   120 #endif /* USE_DL */
       
   121 	if ((count_lock = usnewlock(shared_arena)) == NULL)
       
   122 		perror("usnewlock (count_lock)");
       
   123 	(void) usinitlock(count_lock);
       
   124 	if ((wait_lock = usnewlock(shared_arena)) == NULL)
       
   125 		perror("usnewlock (wait_lock)");
       
   126 	dprintf(("arena start: %p, arena size: %ld\n",  shared_arena, (long) usconfig(CONF_GETSIZE, shared_arena)));
       
   127 }
       
   128 
       
   129 /*
       
   130  * Thread support.
       
   131  */
       
   132 
       
   133 static void clean_threads(void)
       
   134 {
       
   135 	int i, j;
       
   136 	pid_t mypid, pid;
       
   137 
       
   138 	/* clean up any exited threads */
       
   139 	mypid = getpid();
       
   140 	i = 0;
       
   141 	while (i < maxpidindex) {
       
   142 		if (pidlist[i].parent == mypid && (pid = pidlist[i].child) > 0) {
       
   143 			pid = waitpid(pid, 0, WNOHANG);
       
   144 			if (pid > 0) {
       
   145 				/* a thread has exited */
       
   146 				pidlist[i] = pidlist[--maxpidindex];
       
   147 				/* remove references to children of dead proc */
       
   148 				for (j = 0; j < maxpidindex; j++)
       
   149 					if (pidlist[j].parent == pid)
       
   150 						pidlist[j].child = -1;
       
   151 				continue; /* don't increment i */
       
   152 			}
       
   153 		}
       
   154 		i++;
       
   155 	}
       
   156 	/* clean up the list */
       
   157 	i = 0;
       
   158 	while (i < maxpidindex) {
       
   159 		if (pidlist[i].child == -1) {
       
   160 			pidlist[i] = pidlist[--maxpidindex];
       
   161 			continue; /* don't increment i */
       
   162 		}
       
   163 		i++;
       
   164 	}
       
   165 }
       
   166 
       
   167 long PyThread_start_new_thread(void (*func)(void *), void *arg)
       
   168 {
       
   169 #ifdef USE_DL
       
   170 	long addr, size;
       
   171 	static int local_initialized = 0;
       
   172 #endif /* USE_DL */
       
   173 	int success = 0;	/* init not needed when SOLARIS_THREADS and */
       
   174 				/* C_THREADS implemented properly */
       
   175 
       
   176 	dprintf(("PyThread_start_new_thread called\n"));
       
   177 	if (!initialized)
       
   178 		PyThread_init_thread();
       
   179 	switch (ussetlock(count_lock)) {
       
   180 	case 0: return 0;
       
   181 	case -1: perror("ussetlock (count_lock)");
       
   182 	}
       
   183 	if (maxpidindex >= MAXPROC)
       
   184 		success = -1;
       
   185 	else {
       
   186 #ifdef USE_DL
       
   187 		if (!local_initialized) {
       
   188 			if ((size = usconfig(CONF_INITSIZE, 64*1024)) < 0)
       
   189 				perror("usconfig - CONF_INITSIZE (check)");
       
   190 			if (usconfig(CONF_INITSIZE, size) < 0)
       
   191 				perror("usconfig - CONF_INITSIZE (reset)");
       
   192 			addr = (long) dl_getrange(size + HDR_SIZE);
       
   193 			dprintf(("trying to use addr %p-%p for sproc\n",
       
   194 				 addr, addr+size));
       
   195 			errno = 0;
       
   196 			if ((addr = usconfig(CONF_ATTACHADDR, addr)) < 0 &&
       
   197 			    errno != 0)
       
   198 				perror("usconfig - CONF_ATTACHADDR (set)");
       
   199 		}
       
   200 #endif /* USE_DL */
       
   201 		clean_threads();
       
   202 		if ((success = sproc(func, PR_SALL, arg)) < 0)
       
   203 			perror("sproc");
       
   204 #ifdef USE_DL
       
   205 		if (!local_initialized) {
       
   206 			if (usconfig(CONF_ATTACHADDR, addr) < 0)
       
   207 				/* reset address */
       
   208 				perror("usconfig - CONF_ATTACHADDR (reset)");
       
   209 			local_initialized = 1;
       
   210 		}
       
   211 #endif /* USE_DL */
       
   212 		if (success >= 0) {
       
   213 			nthreads++;
       
   214 			pidlist[maxpidindex].parent = getpid();
       
   215 			pidlist[maxpidindex++].child = success;
       
   216 			dprintf(("pidlist[%d] = %d\n",
       
   217 				 maxpidindex-1, success));
       
   218 		}
       
   219 	}
       
   220 	if (usunsetlock(count_lock) < 0)
       
   221 		perror("usunsetlock (count_lock)");
       
   222 	return success;
       
   223 }
       
   224 
       
   225 long PyThread_get_thread_ident(void)
       
   226 {
       
   227 	return getpid();
       
   228 }
       
   229 
       
   230 static void do_PyThread_exit_thread(int no_cleanup)
       
   231 {
       
   232 	dprintf(("PyThread_exit_thread called\n"));
       
   233 	if (!initialized)
       
   234 		if (no_cleanup)
       
   235 			_exit(0);
       
   236 		else
       
   237 			exit(0);
       
   238 	if (ussetlock(count_lock) < 0)
       
   239 		perror("ussetlock (count_lock)");
       
   240 	nthreads--;
       
   241 	if (getpid() == my_pid) {
       
   242 		/* main thread; wait for other threads to exit */
       
   243 		exiting = 1;
       
   244 #ifndef NO_EXIT_PROG
       
   245 		if (do_exit) {
       
   246 			int i;
       
   247 
       
   248 			/* notify other threads */
       
   249 			clean_threads();
       
   250 			if (nthreads >= 0) {
       
   251 				dprintf(("kill other threads\n"));
       
   252 				for (i = 0; i < maxpidindex; i++)
       
   253 					if (pidlist[i].child > 0)
       
   254 						(void) kill(pidlist[i].child,
       
   255 							    SIGKILL);
       
   256 				_exit(exit_status);
       
   257 			}
       
   258 		}
       
   259 #endif /* NO_EXIT_PROG */
       
   260 		waiting_for_threads = 1;
       
   261 		if (ussetlock(wait_lock) < 0)
       
   262 			perror("ussetlock (wait_lock)");
       
   263 		for (;;) {
       
   264 			if (nthreads < 0) {
       
   265 				dprintf(("really exit (%d)\n", exit_status));
       
   266 				if (no_cleanup)
       
   267 					_exit(exit_status);
       
   268 				else
       
   269 					exit(exit_status);
       
   270 			}
       
   271 			if (usunsetlock(count_lock) < 0)
       
   272 				perror("usunsetlock (count_lock)");
       
   273 			dprintf(("waiting for other threads (%d)\n", nthreads));
       
   274 			if (ussetlock(wait_lock) < 0)
       
   275 				perror("ussetlock (wait_lock)");
       
   276 			if (ussetlock(count_lock) < 0)
       
   277 				perror("ussetlock (count_lock)");
       
   278 		}
       
   279 	}
       
   280 	/* not the main thread */
       
   281 	if (waiting_for_threads) {
       
   282 		dprintf(("main thread is waiting\n"));
       
   283 		if (usunsetlock(wait_lock) < 0)
       
   284 			perror("usunsetlock (wait_lock)");
       
   285 	}
       
   286 #ifndef NO_EXIT_PROG
       
   287 	else if (do_exit)
       
   288 		(void) kill(my_pid, SIGUSR1);
       
   289 #endif /* NO_EXIT_PROG */
       
   290 	if (usunsetlock(count_lock) < 0)
       
   291 		perror("usunsetlock (count_lock)");
       
   292 	_exit(0);
       
   293 }
       
   294 
       
   295 void PyThread_exit_thread(void)
       
   296 {
       
   297 	do_PyThread_exit_thread(0);
       
   298 }
       
   299 
       
   300 void PyThread__exit_thread(void)
       
   301 {
       
   302 	do_PyThread_exit_thread(1);
       
   303 }
       
   304 
       
   305 #ifndef NO_EXIT_PROG
       
   306 static void do_PyThread_exit_prog(int status, int no_cleanup)
       
   307 {
       
   308 	dprintf(("PyThread_exit_prog(%d) called\n", status));
       
   309 	if (!initialized)
       
   310 		if (no_cleanup)
       
   311 			_exit(status);
       
   312 		else
       
   313 			exit(status);
       
   314 	do_exit = 1;
       
   315 	exit_status = status;
       
   316 	do_PyThread_exit_thread(no_cleanup);
       
   317 }
       
   318 
       
   319 void PyThread_exit_prog(int status)
       
   320 {
       
   321 	do_PyThread_exit_prog(status, 0);
       
   322 }
       
   323 
       
   324 void PyThread__exit_prog(int status)
       
   325 {
       
   326 	do_PyThread_exit_prog(status, 1);
       
   327 }
       
   328 #endif /* NO_EXIT_PROG */
       
   329 
       
   330 /*
       
   331  * Lock support.
       
   332  */
       
   333 PyThread_type_lock PyThread_allocate_lock(void)
       
   334 {
       
   335 	ulock_t lock;
       
   336 
       
   337 	dprintf(("PyThread_allocate_lock called\n"));
       
   338 	if (!initialized)
       
   339 		PyThread_init_thread();
       
   340 
       
   341 	if ((lock = usnewlock(shared_arena)) == NULL)
       
   342 		perror("usnewlock");
       
   343 	(void) usinitlock(lock);
       
   344 	dprintf(("PyThread_allocate_lock() -> %p\n", lock));
       
   345 	return (PyThread_type_lock) lock;
       
   346 }
       
   347 
       
   348 void PyThread_free_lock(PyThread_type_lock lock)
       
   349 {
       
   350 	dprintf(("PyThread_free_lock(%p) called\n", lock));
       
   351 	usfreelock((ulock_t) lock, shared_arena);
       
   352 }
       
   353 
       
   354 int PyThread_acquire_lock(PyThread_type_lock lock, int waitflag)
       
   355 {
       
   356 	int success;
       
   357 
       
   358 	dprintf(("PyThread_acquire_lock(%p, %d) called\n", lock, waitflag));
       
   359 	errno = 0;		/* clear it just in case */
       
   360 	if (waitflag)
       
   361 		success = ussetlock((ulock_t) lock);
       
   362 	else
       
   363 		success = uscsetlock((ulock_t) lock, 1); /* Try it once */
       
   364 	if (success < 0)
       
   365 		perror(waitflag ? "ussetlock" : "uscsetlock");
       
   366 	dprintf(("PyThread_acquire_lock(%p, %d) -> %d\n", lock, waitflag, success));
       
   367 	return success;
       
   368 }
       
   369 
       
   370 void PyThread_release_lock(PyThread_type_lock lock)
       
   371 {
       
   372 	dprintf(("PyThread_release_lock(%p) called\n", lock));
       
   373 	if (usunsetlock((ulock_t) lock) < 0)
       
   374 		perror("usunsetlock");
       
   375 }