summaryrefslogtreecommitdiffstats
path: root/Utilities
ModeNameSize
-rw-r--r--.NoDartCoverage39logstatsplain
-rw-r--r--.gitattributes76logstatsplain
-rw-r--r--CMakeLists.txt624logstatsplain
d---------Doxygen165logstatsplain
d---------Git122logstatsplain
d---------GitSetup445logstatsplain
d---------KWIML224logstatsplain
d---------KWStyle265logstatsplain
d---------Release821logstatsplain
-rwxr-xr-xSetupForDevelopment.sh392logstatsplain
d---------Sphinx223logstatsplain
-rw-r--r--cmThirdParty.h.in900logstatsplain
-rw-r--r--cm_bzlib.h790logstatsplain
-rw-r--r--cm_curl.h793logstatsplain
-rw-r--r--cm_expat.h790logstatsplain
-rw-r--r--cm_libarchive.h902logstatsplain
-rw-r--r--cm_xmlrpc.h782logstatsplain
-rw-r--r--cm_zlib.h783logstatsplain
d---------cmbzip22287logstatsplain
d---------cmcompress210logstatsplain
d---------cmcurl4725logstatsplain
d---------cmexpat821logstatsplain
d---------cmlibarchive277logstatsplain
d---------cmzlib1229logstatsplain
25'>425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503

#ifdef WITH_SGI_DL
#define USE_DL
#endif

#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;
#ifndef NO_EXIT_PROG
static int do_exit;		/* indicates that the program is to exit */
#endif
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 */

#ifndef NO_EXIT_PROG
/*
 * This routine is called as a signal handler when another thread
 * exits.  When that happens, we must see whether we have to exit as
 * well (because of an PyThread_exit_prog()) or whether we should continue on.
 */
static void exit_sig(void)
{
	d2printf(("exit_sig called\n"));
	if (exiting && getpid() == my_pid) {
		d2printf(("already exiting\n"));
		return;
	}
	if (do_exit) {
		d2printf(("exiting in exit_sig\n"));
#ifdef Py_DEBUG
		if ((thread_debug & 8) == 0)
			thread_debug &= ~1; /* don't produce debug messages */
#endif
		PyThread_exit_thread();
	}
}

/*
 * This routine is called when a process calls exit().  If that wasn't
 * done from the library, we do as if an PyThread_exit_prog() was intended.
 */
static void maybe_exit(void)
{
	dprintf(("maybe_exit called\n"));
	if (exiting) {
		dprintf(("already exiting\n"));
		return;
	}
	PyThread_exit_prog(0);
}
#endif /* NO_EXIT_PROG */

/*
 * Initialization.
 */
static void PyThread__init_thread(void)
{
#ifndef NO_EXIT_PROG
	struct sigaction s;
#endif /* NO_EXIT_PROG */
#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 */
#ifndef NO_EXIT_PROG
	atexit(maybe_exit);
	s.sa_handler = exit_sig;
	sigemptyset(&s.sa_mask);
	/*sigaddset(&s.sa_mask, SIGUSR1);*/
	s.sa_flags = 0;
	sigaction(SIGUSR1, &s, 0);
	if (prctl(PR_SETEXITSIG, SIGUSR1) < 0)
		perror("prctl - PR_SETEXITSIG");
#endif /* NO_EXIT_PROG */
	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++;
	}
}

int 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 < 0 ? 0 : 1;
}

long PyThread_get_thread_ident(void)
{
	return getpid();
}

static void do_PyThread_exit_thread(int no_cleanup)
{
	dprintf(("PyThread_exit_thread called\n"));
	if (!initialized)
		if (no_cleanup)
			_exit(0);
		else
			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;
#ifndef NO_EXIT_PROG
		if (do_exit) {
			int i;

			/* notify other threads */
			clean_threads();
			if (nthreads >= 0) {
				dprintf(("kill other threads\n"));
				for (i = 0; i < maxpidindex; i++)
					if (pidlist[i].child > 0)
						(void) kill(pidlist[i].child,
							    SIGKILL);
				_exit(exit_status);
			}
		}
#endif /* NO_EXIT_PROG */
		waiting_for_threads = 1;
		if (ussetlock(wait_lock) < 0)
			perror("ussetlock (wait_lock)");
		for (;;) {
			if (nthreads < 0) {
				dprintf(("really exit (%d)\n", exit_status));
				if (no_cleanup)
					_exit(exit_status);
				else
					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)");
	}
#ifndef NO_EXIT_PROG
	else if (do_exit)
		(void) kill(my_pid, SIGUSR1);
#endif /* NO_EXIT_PROG */
	if (usunsetlock(count_lock) < 0)
		perror("usunsetlock (count_lock)");
	_exit(0);
}

void PyThread_exit_thread(void)
{
	do_PyThread_exit_thread(0);
}

void PyThread__exit_thread(void)
{
	do_PyThread_exit_thread(1);
}

#ifndef NO_EXIT_PROG
static void do_PyThread_exit_prog(int status, int no_cleanup)
{
	dprintf(("PyThread_exit_prog(%d) called\n", status));
	if (!initialized)
		if (no_cleanup)
			_exit(status);
		else
			exit(status);
	do_exit = 1;
	exit_status = status;
	do_PyThread_exit_thread(no_cleanup);
}

void PyThread_exit_prog(int status)
{
	do_PyThread_exit_prog(status, 0);
}

void PyThread__exit_prog(int status)
{
	do_PyThread_exit_prog(status, 1);
}
#endif /* NO_EXIT_PROG */

/*
 * 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");
}

/*
 * Semaphore support.
 */
PyThread_type_sema PyThread_allocate_sema(int value)
{
	usema_t *sema;
	dprintf(("PyThread_allocate_sema called\n"));
	if (!initialized)
		PyThread_init_thread();

	if ((sema = usnewsema(shared_arena, value)) == NULL)
		perror("usnewsema");
	dprintf(("PyThread_allocate_sema() -> %p\n",  sema));
	return (PyThread_type_sema) sema;
}

void PyThread_free_sema(PyThread_type_sema sema)
{
	dprintf(("PyThread_free_sema(%p) called\n",  sema));
	usfreesema((usema_t *) sema, shared_arena);
}

int PyThread_down_sema(PyThread_type_sema sema, int waitflag)
{
	int success;

	dprintf(("PyThread_down_sema(%p) called\n",  sema));
	if (waitflag)
		success = uspsema((usema_t *) sema);
	else
		success = uscpsema((usema_t *) sema);
	if (success < 0)
		perror(waitflag ? "uspsema" : "uscpsema");
	dprintf(("PyThread_down_sema(%p) return\n",  sema));
	return success;
}

void PyThread_up_sema(PyThread_type_sema sema)
{
	dprintf(("PyThread_up_sema(%p)\n",  sema));
	if (usvsema((usema_t *) sema) < 0)
		perror("usvsema");
}

/*
 * Per-thread data ("key") support.
 */

struct key {
	struct key *next;
	long id;
	int key;
	void *value;
};

static struct key *keyhead = NULL;
static int nkeys = 0;
static PyThread_type_lock keymutex = NULL;

static struct key *find_key(int key, void *value)
{
	struct key *p;
	long id = PyThread_get_thread_ident();
	for (p = keyhead; p != NULL; p = p->next) {
		if (p->id == id && p->key == key)
			return p;
	}
	if (value == NULL)
		return NULL;
	p = (struct key *)malloc(sizeof(struct key));
	if (p != NULL) {
		p->id = id;
		p->key = key;
		p->value = value;
		PyThread_acquire_lock(keymutex, 1);
		p->next = keyhead;
		keyhead = p;
		PyThread_release_lock(keymutex);
	}
	return p;
}

int PyThread_create_key(void)
{
	if (keymutex == NULL)
		keymutex = PyThread_allocate_lock();
	return ++nkeys;
}

void PyThread_delete_key(int key)
{
	struct key *p, **q;
	PyThread_acquire_lock(keymutex, 1);
	q = &keyhead;
	while ((p = *q) != NULL) {
		if (p->key == key) {
			*q = p->next;
			free((void *)p);
			/* NB This does *not* free p->value! */
		}
		else
			q = &p->next;
	}
	PyThread_release_lock(keymutex);
}

int PyThread_set_key_value(int key, void *value)
{
	struct key *p = find_key(key, value);
	if (p == NULL)
		return -1;
	else
		return 0;
}

void *PyThread_get_key_value(int key)
{
	struct key *p = find_key(key, NULL);
	if (p == NULL)
		return NULL;
	else
		return p->value;
}