Example #1
0
void
linux_to_bsd_sigset(l_sigset_t *lss, sigset_t *bss)
{
	int b, l;

	SIGEMPTYSET(*bss);
	bss->__bits[0] = lss->__bits[0] & ~((1U << LINUX_SIGTBLSZ) - 1);
	bss->__bits[1] = lss->__bits[1];
	for (l = 1; l <= LINUX_SIGTBLSZ; l++) {
		if (LINUX_SIGISMEMBER(*lss, l)) {
			b = linux_to_bsd_signal[_SIG_IDX(l)];
			if (b)
				SIGADDSET(*bss, b);
		}
	}
}
Example #2
0
/*
 * Advise a kernel process to suspend (or resume) in its main loop.
 * Participation is voluntary.
 */
int
kproc_suspend(struct proc *p, int timo)
{
	/*
	 * Make sure this is indeed a system process and we can safely
	 * use the p_siglist field.
	 */
	PROC_LOCK(p);
	if ((p->p_flag & P_KTHREAD) == 0) {
		PROC_UNLOCK(p);
		return (EINVAL);
	}
	SIGADDSET(p->p_siglist, SIGSTOP);
	wakeup(p);
	return msleep(&p->p_siglist, &p->p_mtx, PPAUSE | PDROP, "suspkp", timo);
}
Example #3
0
void
_pthread_exit_mask(void *status, sigset_t *mask)
{
    struct pthread *curthread = _get_curthread();

    /* Check if this thread is already in the process of exiting: */
    if (curthread->cancelling) {
        char msg[128];
        snprintf(msg, sizeof(msg), "Thread %p has called "
                 "pthread_exit() from a destructor. POSIX 1003.1 "
                 "1996 s16.2.5.2 does not allow this!", curthread);
        PANIC(msg);
    }

    /* Flag this thread as exiting. */
    curthread->cancelling = 1;
    curthread->no_cancel = 1;
    curthread->cancel_async = 0;
    curthread->cancel_point = 0;
    if (mask != NULL)
        __sys_sigprocmask(SIG_SETMASK, mask, NULL);
    if (curthread->unblock_sigcancel) {
        sigset_t set;

        curthread->unblock_sigcancel = 0;
        SIGEMPTYSET(set);
        SIGADDSET(set, SIGCANCEL);
        __sys_sigprocmask(SIG_UNBLOCK, mask, NULL);
    }

    /* Save the return value: */
    curthread->ret = status;
#ifdef _PTHREAD_FORCED_UNWIND

#ifdef PIC
    thread_uw_init();
#endif /* PIC */

#ifdef PIC
    if (uwl_forcedunwind != NULL) {
#else
    if (_Unwind_ForcedUnwind != NULL) {
#endif
        if (curthread->unwind_disabled) {
            if (message_printed == 0) {
                message_printed = 1;
                _thread_printf(2, "Warning: old _pthread_cleanup_push was called, "
                               "stack unwinding is disabled.\n");
            }
            goto cleanup;
        }
        thread_unwind();

    } else {
cleanup:
        while (curthread->cleanup != NULL) {
            __pthread_cleanup_pop_imp(1);
        }
        exit_thread();
    }

#else
    while (curthread->cleanup != NULL) {
        __pthread_cleanup_pop_imp(1);
    }

    exit_thread();
#endif /* _PTHREAD_FORCED_UNWIND */
}

static void
exit_thread(void)
{
    struct pthread *curthread = _get_curthread();

    /* Check if there is thread specific data: */
    if (curthread->specific != NULL) {
        /* Run the thread-specific data destructors: */
        _thread_cleanupspecific();
    }

    if (!_thr_isthreaded())
        exit(0);

    if (atomic_fetchadd_int(&_thread_active_threads, -1) == 1) {
        exit(0);
        /* Never reach! */
    }

    /* Tell malloc that the thread is exiting. */
    _malloc_thread_cleanup();

    THR_LOCK(curthread);
    curthread->state = PS_DEAD;
    if (curthread->flags & THR_FLAGS_NEED_SUSPEND) {
        curthread->cycle++;
        _thr_umtx_wake(&curthread->cycle, INT_MAX, 0);
    }
    if (!curthread->force_exit && SHOULD_REPORT_EVENT(curthread, TD_DEATH))
        _thr_report_death(curthread);
    /*
     * Thread was created with initial refcount 1, we drop the
     * reference count to allow it to be garbage collected.
     */
    curthread->refcount--;
    _thr_try_gc(curthread, curthread); /* thread lock released */

#if defined(_PTHREADS_INVARIANTS)
    if (THR_IN_CRITICAL(curthread))
        PANIC("thread exits with resources held!");
#endif
    /*
     * Kernel will do wakeup at the address, so joiner thread
     * will be resumed if it is sleeping at the address.
     */
    thr_exit(&curthread->tid);
    PANIC("thr_exit() returned");
    /* Never reach! */
}
Example #4
0
File: process.c Project: kraj/ltp
/*
 * This is the meat and potatoes of the program.  Spawn creates a tree
 * of processes with Dval depth and Bval breadth.  Each parent will spawn
 * Bval children.  Each child will store information about themselves
 * in shared memory.  The leaf nodes will communicate the existence
 * of one another through message queues, once each leaf node has
 * received communication from all of her siblings she will reduce
 * the semaphore count and exit.  Meanwhile all parents are waiting
 * to hear from their children through the use of semaphores.  When
 * the semaphore count reaches zero then the parent knows all the
 * children have talked to one another.  Locking of the connter semaphore
 * is provided by the use of another (binary) semaphore.
 */
int spawn(int val)
{
	extern int sem_count;	/* used to keep track of childern */
	extern int sem_lock;	/* used to lock access to sem_count semaphore */

	int i;			/* Breadth counter */
	static int level = 0;	/* level counter */
	int lvlflg = 0;		/* level toggle, limits parental spawning
				   to one generation */
	int pslot = 0;
#ifdef __64LDT__
	pid_t pid;		/* pid of child process */
#else
	int pid;		/* pid of child process */
#endif
	Pinfo *pinfo;		/* pointer to process information in shared mem */
	int semval;		/* value of semaphore ( equals BVAL initially */
	static int tval = 1;	/* tree node value of child. */

	char foo[1024];

	level++;

	for (i = 1; i <= BVAL; i++) {
		tval = (val * BVAL) + i;
		if (!lvlflg) {
			pid = fork();
			if (!pid) {	/* CHILD */
				if (AUSDEBUG) {
					sprintf(foo, "%sslot%d", SLOTDIR, tval);
					debugfp = fopen(foo, "a+");
				}
				pinfo = put_proc_info(tval);

				debugout
				    ("pid: %-6d ppid: %-6d lev: %-2d i: %-2d val: %-3d\n",
				     pinfo->pid, pinfo->ppid, level, i, tval);

				set_timer();	/* set up signal handlers and initialize pgrp */
				if (level < DVAL) {
					if (spawn(tval) == -1) {
						pslot =
						    semoper(tval, sem_lock, -1);
						semarg.val = 0;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
						semval =
						    semctl(sem_count, pslot,
							   GETVAL, semarg);
						semarg.val = --semval;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
						semctl(sem_count, pslot, SETVAL,
						       semarg);
						semarg.val = 1;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
						semctl(sem_lock, pslot, SETVAL,
						       semarg);
					}
					lvlflg++;
				} else {	/* leaf node */
					notify(tval);
					return (-1);
				}
			}
#ifdef __64LDT__
			else if (pid > 0 && i >= BVAL) {	/* PARENT */
#else
			else if (pid > (pid_t) 0 && i >= BVAL) {	/* PARENT */
#endif
				pslot = semoper(tval, sem_count, 0);
				pslot = semoper(pslot, sem_lock, -1);
				semarg.val = 0;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
				semval =
				    semctl(sem_count, pslot, GETVAL, semarg);
				semarg.val = --semval;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
				semctl(sem_count, pslot, SETVAL, semarg);
				semarg.val = 1;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
				semctl(sem_lock, pslot, SETVAL, semarg);
				(shmaddr + val)->msg++;
			}
#ifdef __64LDT__
			else if (pid < (pid_t) 0) {
#else
			else if (pid < 0) {
#endif
				perror("spawn: fork failed");
				severe
				    ("spawn: fork failed, exiting with errno %d\n",
				     errno);
				exit(1);
			} else
				(shmaddr + val)->msg++;
		}
	}
	return (pslot);
}

/*
 * Allocate message queues.
 */
void setup_msgqueue(void)
{
	extern int msgid;
	extern int msgerr;

	msgid = msgget(IPC_PRIVATE,
		       IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP |
		       S_IWGRP);
	if (msgid == -1) {
		perror("msgget msgid failed");
		fprintf(stderr, " SEVERE : msgget msgid failed: errno %d\n",
			errno);
		exit(1);
	}

	msgerr = msgget(IPC_PRIVATE,
			IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP |
			S_IWGRP);
	if (msgerr == -1) {
		perror("msgget msgerr failed");
		fprintf(stderr, " SEVERE : msgget msgerr failed: errno %d\n",
			errno);
		exit(1);
	}
}

/*
 * Set up and initialize all semaphores
 */
void setup_semaphores(void)
{
	extern int sem_count;
	extern int sem_lock;

	int i;
	int rc;

	prtln();
	sem_lock = semget(IPC_PRIVATE, nodesum - 1,
			  IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP |
			  S_IWGRP);
	dprt("nodesum = %d, sem_lock = %d\n", nodesum, sem_lock);

	prtln();
	if (sem_lock == -1) {
		perror("semget failed for sem_lock");
		fprintf(stderr,
			" SEVERE : semget failed for sem_lock, errno: %d\n",
			errno);
		rm_shmseg();
		exit(1);
	}

	prtln();
	sem_count = semget(IPC_PRIVATE, nodesum - 1,
			   IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP |
			   S_IWGRP);

	if (sem_count == -1) {
		perror("semget failed for sem_count");
		fprintf(stderr,
			" SEVERE : semget failed for sem_count, errno: %d\n",
			errno);
		rm_shmseg();
		exit(1);
	}
	prtln();

	for (i = 0; i < (nodesum - 1); i++) {
		semarg.val = 1;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
		rc = semctl(sem_lock, i, SETVAL, semarg);
		prtln();
		if (rc == -1) {
			perror("semctl failed for sem_lock failed");
			fprintf(stderr,
				" SEVERE : semctl failed for sem_lock, errno: %d\n",
				errno);
			rm_shmseg();
			exit(1);
		}

		semarg.val = BVAL;	/* to fix problem with 4th arg of semctl in 64 bits MARIOG */
		rc = semctl(sem_count, i, SETVAL, semarg);
		prtln();
		if (rc == -1) {
			perror("semctl failed for sem_lock failed");
			fprintf(stderr,
				" SEVERE : semctl failed for sem_lock, errno: %d\n",
				errno);
			rm_shmseg();
			exit(1);
		}
	}
}

/*
 * Set up and allocate shared memory.
 */
void setup_shm(void)
{
	extern int nodesum;	/* global shared memory id */
	extern int shmid;	/* global shared memory id */
	extern Pinfo *shmaddr;

	int i, j;		/* counters */
	Pinfo *shmad = NULL;	/* ptr to start of shared memory. */
	Pinfo *pinfo = NULL;	/* ptr to struct in shared memory. */

	debugout("size = %d, size (in hex) =  %#x  nodes: %d\n",
		 sizeof(Pinfo) * nodesum + (nodesum * BVAL * sizeof(int)),
		 sizeof(Pinfo) * nodesum + (nodesum * BVAL * sizeof(int)),
		 nodesum);

	/* Get shared memory id */
	shmid = shmget(IPC_PRIVATE,
		       sizeof(Pinfo) * nodesum + (nodesum * BVAL * sizeof(int)),
		       IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR | S_IRGRP |
		       S_IWGRP);
	if (shmid < 0) {
		perror("shmget failed");
		fprintf(stderr, " SEVERE : shmget failed: errno %d\n", errno);
		exit(1);
	}

	/* allocate shared memory */

	if ((shmad = shmat(shmid, (char *)shmad, 0)) == MAP_FAILED) {
		printf("SEVERE : shmat failed\n");
		exit(1);
	} else {
		shmctl(shmid, IPC_RMID, NULL);
	}

	/* set all fields in shared memory to -1 */
	for (pinfo = shmad, i = 0; i < nodesum; i++, pinfo++) {
#ifdef __64LDT__
		pinfo->pid = (pid_t) - 1;
		pinfo->ppid = (pid_t) - 1;
#else
		pinfo->pid = -1;
		pinfo->ppid = -1;
#endif
		pinfo->msg = -1;
		pinfo->err = -1;

		/* Changed 10/9/97 */
		/* pinfo->list = (int *)((ulong)shmad + nodesum * sizeof(Pinfo)
		   + (sizeof(int) * BVAL * i)); */
		pinfo->list =
		    (int *)((long)shmad + nodesum * sizeof(Pinfo) +
			    (sizeof(int) * BVAL * i));
		for (j = 0; j < BVAL; j++)
			*(pinfo->list + j) = -1;
	}
	shmaddr = shmad;
}

/*
 * Set up Signal handler and which signals to catch
 */
void set_signals(void *sighandler())
{
	int i;
	int rc;

	struct sigaction action;

	/* list of signals we want to catch */
	static struct signalinfo {
		int signum;
		char *signame;
	} siginfo[] = {
		{
		SIGHUP, "SIGHUP"}, {
		SIGINT, "SIGINT"}, {
		SIGQUIT, "SIGQUIT"}, {
		SIGABRT, "SIGABRT"}, {
		SIGBUS, "SIGBUS"}, {
		SIGSEGV, "SIGSEGV"}, {
		SIGALRM, "SIGALRM"}, {
		SIGUSR1, "SIGUSR1"}, {
		SIGUSR2, "SIGUSR2"}, {
		-1, "ENDSIG"}
	};

	char tmpstr[1024];

	action.sa_handler = (void *)sighandler;

#ifdef _LINUX
	sigfillset(&action.sa_mask);
#else
	SIGINITSET(action.sa_mask);
#endif
	action.sa_flags = 0;

	/* Set the signal handler up */
#ifdef _LINUX
	sigaddset(&action.sa_mask, SIGTERM);
#else
	SIGADDSET(action.sa_mask, SIGTERM);
#endif
	for (i = 0; siginfo[i].signum != -1; i++) {
#ifdef _LINUX
		sigaddset(&action.sa_mask, siginfo[i].signum);
#else
		SIGADDSET(action.sa_mask, siginfo[i].signum);
#endif
		rc = sigaction(siginfo[i].signum, &action, NULL);
		if (rc == -1) {
			sprintf(tmpstr, "sigaction: %s\n", siginfo[i].signame);
			perror(tmpstr);
			fprintf(stderr,
				" SEVERE : Could not set %s signal action, errno=%d.",
				siginfo[i].signame, errno);
			exit(1);
		}
	}
}
Example #5
0
static void
pmclog_loop(void *arg)
{
	struct pmclog_proc_init_args *ia;
	struct pmc_owner *po;
	struct pmclog_buffer *lb;
	struct proc *p;
	struct ucred *ownercred;
	struct ucred *mycred;
	struct thread *td;
	sigset_t unb;
	struct uio auio;
	struct iovec aiov;
	size_t nbytes;
	int error;

	td = curthread;

	SIGEMPTYSET(unb);
	SIGADDSET(unb, SIGHUP);
	(void)kern_sigprocmask(td, SIG_UNBLOCK, &unb, NULL, 0);

	ia = arg;
	MPASS(ia->kthr == curproc);
	MPASS(!ia->acted);
	mtx_lock(&pmc_kthread_mtx);
	while (ia->po == NULL && !ia->exit)
		msleep(ia, &pmc_kthread_mtx, PWAIT, "pmclogi", 0);
	if (ia->exit) {
		ia->acted = true;
		wakeup(ia);
		mtx_unlock(&pmc_kthread_mtx);
		kproc_exit(0);
	}
	MPASS(ia->po != NULL);
	po = ia->po;
	ia->acted = true;
	wakeup(ia);
	mtx_unlock(&pmc_kthread_mtx);
	ia = NULL;

	p = po->po_owner;
	mycred = td->td_ucred;

	PROC_LOCK(p);
	ownercred = crhold(p->p_ucred);
	PROC_UNLOCK(p);

	PMCDBG2(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
	KASSERT(po->po_kthread == curthread->td_proc,
	    ("[pmclog,%d] proc mismatch po=%p po/kt=%p curproc=%p", __LINE__,
		po, po->po_kthread, curthread->td_proc));

	lb = NULL;


	/*
	 * Loop waiting for I/O requests to be added to the owner
	 * struct's queue.  The loop is exited when the log file
	 * is deconfigured.
	 */

	mtx_lock(&pmc_kthread_mtx);

	for (;;) {

		/* check if we've been asked to exit */
		if ((po->po_flags & PMC_PO_OWNS_LOGFILE) == 0)
			break;

		if (lb == NULL) { /* look for a fresh buffer to write */
			mtx_lock_spin(&po->po_mtx);
			if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
				mtx_unlock_spin(&po->po_mtx);

				/* No more buffers and shutdown required. */
				if (po->po_flags & PMC_PO_SHUTDOWN)
					break;

				(void) msleep(po, &pmc_kthread_mtx, PWAIT,
				    "pmcloop", 0);
				continue;
			}

			TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next);
			mtx_unlock_spin(&po->po_mtx);
		}

		mtx_unlock(&pmc_kthread_mtx);

		/* process the request */
		PMCDBG3(LOG,WRI,2, "po=%p base=%p ptr=%p", po,
		    lb->plb_base, lb->plb_ptr);
		/* change our thread's credentials before issuing the I/O */

		aiov.iov_base = lb->plb_base;
		aiov.iov_len  = nbytes = lb->plb_ptr - lb->plb_base;

		auio.uio_iov    = &aiov;
		auio.uio_iovcnt = 1;
		auio.uio_offset = -1;
		auio.uio_resid  = nbytes;
		auio.uio_rw     = UIO_WRITE;
		auio.uio_segflg = UIO_SYSSPACE;
		auio.uio_td     = td;

		/* switch thread credentials -- see kern_ktrace.c */
		td->td_ucred = ownercred;
		error = fo_write(po->po_file, &auio, ownercred, 0, td);
		td->td_ucred = mycred;

		if (error) {
			/* XXX some errors are recoverable */
			/* send a SIGIO to the owner and exit */
			PROC_LOCK(p);
			kern_psignal(p, SIGIO);
			PROC_UNLOCK(p);

			mtx_lock(&pmc_kthread_mtx);

			po->po_error = error; /* save for flush log */

			PMCDBG2(LOG,WRI,2, "po=%p error=%d", po, error);

			break;
		}

		mtx_lock(&pmc_kthread_mtx);

		/* put the used buffer back into the global pool */
		PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);

		mtx_lock_spin(&pmc_bufferlist_mtx);
		TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next);
		mtx_unlock_spin(&pmc_bufferlist_mtx);

		lb = NULL;
	}

	wakeup_one(po->po_kthread);
	po->po_kthread = NULL;

	mtx_unlock(&pmc_kthread_mtx);

	/* return the current I/O buffer to the global pool */
	if (lb) {
		PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);

		mtx_lock_spin(&pmc_bufferlist_mtx);
		TAILQ_INSERT_HEAD(&pmc_bufferlist, lb, plb_next);
		mtx_unlock_spin(&pmc_bufferlist_mtx);
	}

	/*
	 * Exit this thread, signalling the waiter
	 */

	crfree(ownercred);

	kproc_exit(0);
}