OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [compat/] [waitpid.c] - Diff between revs 578 and 1765

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 578 Rev 1765
/*
/*
 * waitpid.c --
 * waitpid.c --
 *
 *
 *      This procedure emulates the POSIX waitpid kernel call on
 *      This procedure emulates the POSIX waitpid kernel call on
 *      BSD systems that don't have waitpid but do have wait3.
 *      BSD systems that don't have waitpid but do have wait3.
 *      This code is based on a prototype version written by
 *      This code is based on a prototype version written by
 *      Mark Diekhans and Karl Lehenbauer.
 *      Mark Diekhans and Karl Lehenbauer.
 *
 *
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1993 The Regents of the University of California.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 * Copyright (c) 1994 Sun Microsystems, Inc.
 *
 *
 * See the file "license.terms" for information on usage and redistribution
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 *
 * RCS: @(#) $Id: waitpid.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
 * RCS: @(#) $Id: waitpid.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
 */
 */
 
 
#include "tclInt.h"
#include "tclInt.h"
#include "tclPort.h"
#include "tclPort.h"
 
 
/*
/*
 * A linked list of the following structures is used to keep track
 * A linked list of the following structures is used to keep track
 * of processes for which we received notification from the kernel,
 * of processes for which we received notification from the kernel,
 * but the application hasn't waited for them yet (this can happen
 * but the application hasn't waited for them yet (this can happen
 * because wait may not return the process we really want).  We
 * because wait may not return the process we really want).  We
 * save the information here until the application finally does
 * save the information here until the application finally does
 * wait for the process.
 * wait for the process.
 */
 */
 
 
typedef struct WaitInfo {
typedef struct WaitInfo {
    int pid;                            /* Pid of process that exited. */
    int pid;                            /* Pid of process that exited. */
    WAIT_STATUS_TYPE status;            /* Status returned when child exited
    WAIT_STATUS_TYPE status;            /* Status returned when child exited
                                         * or suspended. */
                                         * or suspended. */
    struct WaitInfo *nextPtr;           /* Next in list of exited processes. */
    struct WaitInfo *nextPtr;           /* Next in list of exited processes. */
} WaitInfo;
} WaitInfo;
 
 
static WaitInfo *deadList = NULL;       /* First in list of all dead
static WaitInfo *deadList = NULL;       /* First in list of all dead
                                         * processes. */
                                         * processes. */


/*
/*
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 *
 *
 * waitpid --
 * waitpid --
 *
 *
 *      This procedure emulates the functionality of the POSIX
 *      This procedure emulates the functionality of the POSIX
 *      waitpid kernel call, using the BSD wait3 kernel call.
 *      waitpid kernel call, using the BSD wait3 kernel call.
 *      Note:  it doesn't emulate absolutely all of the waitpid
 *      Note:  it doesn't emulate absolutely all of the waitpid
 *      functionality, in that it doesn't support pid's of 0
 *      functionality, in that it doesn't support pid's of 0
 *      or < -1.
 *      or < -1.
 *
 *
 * Results:
 * Results:
 *      -1 is returned if there is an error in the wait kernel call.
 *      -1 is returned if there is an error in the wait kernel call.
 *      Otherwise the pid of an exited or suspended process is
 *      Otherwise the pid of an exited or suspended process is
 *      returned and *statusPtr is set to the status value of the
 *      returned and *statusPtr is set to the status value of the
 *      process.
 *      process.
 *
 *
 * Side effects:
 * Side effects:
 *      None.
 *      None.
 *
 *
 *----------------------------------------------------------------------
 *----------------------------------------------------------------------
 */
 */
 
 
#ifdef waitpid
#ifdef waitpid
#   undef waitpid
#   undef waitpid
#endif
#endif
 
 
int
int
waitpid(pid, statusPtr, options)
waitpid(pid, statusPtr, options)
    int pid;                    /* The pid to wait on.  Must be -1 or
    int pid;                    /* The pid to wait on.  Must be -1 or
                                 * greater than zero. */
                                 * greater than zero. */
    int *statusPtr;             /* Where to store wait status for the
    int *statusPtr;             /* Where to store wait status for the
                                 * process. */
                                 * process. */
    int options;                /* OR'ed combination of WNOHANG and
    int options;                /* OR'ed combination of WNOHANG and
                                 * WUNTRACED. */
                                 * WUNTRACED. */
{
{
    register WaitInfo *waitPtr, *prevPtr;
    register WaitInfo *waitPtr, *prevPtr;
    int result;
    int result;
    WAIT_STATUS_TYPE status;
    WAIT_STATUS_TYPE status;
 
 
    if ((pid < -1) || (pid == 0)) {
    if ((pid < -1) || (pid == 0)) {
        errno = EINVAL;
        errno = EINVAL;
        return -1;
        return -1;
    }
    }
 
 
    /*
    /*
     * See if there's a suitable process that has already stopped or
     * See if there's a suitable process that has already stopped or
     * exited. If so, remove it from the list of exited processes and
     * exited. If so, remove it from the list of exited processes and
     * return its information.
     * return its information.
     */
     */
 
 
    for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
    for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
            prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) {
            prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) {
        if ((pid != waitPtr->pid) && (pid != -1)) {
        if ((pid != waitPtr->pid) && (pid != -1)) {
            continue;
            continue;
        }
        }
        if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) {
        if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) {
            continue;
            continue;
        }
        }
        result = waitPtr->pid;
        result = waitPtr->pid;
        *statusPtr = *((int *) &waitPtr->status);
        *statusPtr = *((int *) &waitPtr->status);
        if (prevPtr == NULL) {
        if (prevPtr == NULL) {
            deadList = waitPtr->nextPtr;
            deadList = waitPtr->nextPtr;
        } else {
        } else {
            prevPtr->nextPtr = waitPtr->nextPtr;
            prevPtr->nextPtr = waitPtr->nextPtr;
        }
        }
        ckfree((char *) waitPtr);
        ckfree((char *) waitPtr);
        return result;
        return result;
    }
    }
 
 
    /*
    /*
     * Wait for any process to stop or exit.  If it's an acceptable one
     * Wait for any process to stop or exit.  If it's an acceptable one
     * then return it to the caller;  otherwise store information about it
     * then return it to the caller;  otherwise store information about it
     * in the list of exited processes and try again.  On systems that
     * in the list of exited processes and try again.  On systems that
     * have only wait but not wait3, there are several situations we can't
     * have only wait but not wait3, there are several situations we can't
     * handle, but we do the best we can (e.g. can still handle some
     * handle, but we do the best we can (e.g. can still handle some
     * combinations of options by invoking wait instead of wait3).
     * combinations of options by invoking wait instead of wait3).
     */
     */
 
 
    while (1) {
    while (1) {
#if NO_WAIT3
#if NO_WAIT3
        if (options & WNOHANG) {
        if (options & WNOHANG) {
            return 0;
            return 0;
        }
        }
        if (options != 0) {
        if (options != 0) {
            errno = EINVAL;
            errno = EINVAL;
            return -1;
            return -1;
        }
        }
        result = wait(&status);
        result = wait(&status);
#else
#else
        result = wait3(&status, options, 0);
        result = wait3(&status, options, 0);
#endif
#endif
        if ((result == -1) && (errno == EINTR)) {
        if ((result == -1) && (errno == EINTR)) {
            continue;
            continue;
        }
        }
        if (result <= 0) {
        if (result <= 0) {
            return result;
            return result;
        }
        }
 
 
        if ((pid != result) && (pid != -1)) {
        if ((pid != result) && (pid != -1)) {
            goto saveInfo;
            goto saveInfo;
        }
        }
        if (!(options & WUNTRACED) && (WIFSTOPPED(status))) {
        if (!(options & WUNTRACED) && (WIFSTOPPED(status))) {
            goto saveInfo;
            goto saveInfo;
        }
        }
        *statusPtr = *((int *) &status);
        *statusPtr = *((int *) &status);
        return result;
        return result;
 
 
        /*
        /*
         * Can't return this info to caller.  Save it in the list of
         * Can't return this info to caller.  Save it in the list of
         * stopped or exited processes.  Tricky point: first check for
         * stopped or exited processes.  Tricky point: first check for
         * an existing entry for the process and overwrite it if it
         * an existing entry for the process and overwrite it if it
         * exists (e.g. a previously stopped process might now be dead).
         * exists (e.g. a previously stopped process might now be dead).
         */
         */
 
 
        saveInfo:
        saveInfo:
        for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
        for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
            if (waitPtr->pid == result) {
            if (waitPtr->pid == result) {
                waitPtr->status = status;
                waitPtr->status = status;
                goto waitAgain;
                goto waitAgain;
            }
            }
        }
        }
        waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo));
        waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo));
        waitPtr->pid = result;
        waitPtr->pid = result;
        waitPtr->status = status;
        waitPtr->status = status;
        waitPtr->nextPtr = deadList;
        waitPtr->nextPtr = deadList;
        deadList = waitPtr;
        deadList = waitPtr;
 
 
        waitAgain: continue;
        waitAgain: continue;
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.