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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [compat/] [waitpid.c] - Blame information for rev 1780

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * waitpid.c --
3
 *
4
 *      This procedure emulates the POSIX waitpid kernel call on
5
 *      BSD systems that don't have waitpid but do have wait3.
6
 *      This code is based on a prototype version written by
7
 *      Mark Diekhans and Karl Lehenbauer.
8
 *
9
 * Copyright (c) 1993 The Regents of the University of California.
10
 * Copyright (c) 1994 Sun Microsystems, Inc.
11
 *
12
 * See the file "license.terms" for information on usage and redistribution
13
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14
 *
15
 * RCS: @(#) $Id: waitpid.c,v 1.1.1.1 2002-01-16 10:25:23 markom Exp $
16
 */
17
 
18
#include "tclInt.h"
19
#include "tclPort.h"
20
 
21
/*
22
 * A linked list of the following structures is used to keep track
23
 * of processes for which we received notification from the kernel,
24
 * but the application hasn't waited for them yet (this can happen
25
 * because wait may not return the process we really want).  We
26
 * save the information here until the application finally does
27
 * wait for the process.
28
 */
29
 
30
typedef struct WaitInfo {
31
    int pid;                            /* Pid of process that exited. */
32
    WAIT_STATUS_TYPE status;            /* Status returned when child exited
33
                                         * or suspended. */
34
    struct WaitInfo *nextPtr;           /* Next in list of exited processes. */
35
} WaitInfo;
36
 
37
static WaitInfo *deadList = NULL;       /* First in list of all dead
38
                                         * processes. */
39
 
40
/*
41
 *----------------------------------------------------------------------
42
 *
43
 * waitpid --
44
 *
45
 *      This procedure emulates the functionality of the POSIX
46
 *      waitpid kernel call, using the BSD wait3 kernel call.
47
 *      Note:  it doesn't emulate absolutely all of the waitpid
48
 *      functionality, in that it doesn't support pid's of 0
49
 *      or < -1.
50
 *
51
 * Results:
52
 *      -1 is returned if there is an error in the wait kernel call.
53
 *      Otherwise the pid of an exited or suspended process is
54
 *      returned and *statusPtr is set to the status value of the
55
 *      process.
56
 *
57
 * Side effects:
58
 *      None.
59
 *
60
 *----------------------------------------------------------------------
61
 */
62
 
63
#ifdef waitpid
64
#   undef waitpid
65
#endif
66
 
67
int
68
waitpid(pid, statusPtr, options)
69
    int pid;                    /* The pid to wait on.  Must be -1 or
70
                                 * greater than zero. */
71
    int *statusPtr;             /* Where to store wait status for the
72
                                 * process. */
73
    int options;                /* OR'ed combination of WNOHANG and
74
                                 * WUNTRACED. */
75
{
76
    register WaitInfo *waitPtr, *prevPtr;
77
    int result;
78
    WAIT_STATUS_TYPE status;
79
 
80
    if ((pid < -1) || (pid == 0)) {
81
        errno = EINVAL;
82
        return -1;
83
    }
84
 
85
    /*
86
     * See if there's a suitable process that has already stopped or
87
     * exited. If so, remove it from the list of exited processes and
88
     * return its information.
89
     */
90
 
91
    for (waitPtr = deadList, prevPtr = NULL; waitPtr != NULL;
92
            prevPtr = waitPtr, waitPtr = waitPtr->nextPtr) {
93
        if ((pid != waitPtr->pid) && (pid != -1)) {
94
            continue;
95
        }
96
        if (!(options & WUNTRACED) && (WIFSTOPPED(waitPtr->status))) {
97
            continue;
98
        }
99
        result = waitPtr->pid;
100
        *statusPtr = *((int *) &waitPtr->status);
101
        if (prevPtr == NULL) {
102
            deadList = waitPtr->nextPtr;
103
        } else {
104
            prevPtr->nextPtr = waitPtr->nextPtr;
105
        }
106
        ckfree((char *) waitPtr);
107
        return result;
108
    }
109
 
110
    /*
111
     * Wait for any process to stop or exit.  If it's an acceptable one
112
     * then return it to the caller;  otherwise store information about it
113
     * in the list of exited processes and try again.  On systems that
114
     * have only wait but not wait3, there are several situations we can't
115
     * handle, but we do the best we can (e.g. can still handle some
116
     * combinations of options by invoking wait instead of wait3).
117
     */
118
 
119
    while (1) {
120
#if NO_WAIT3
121
        if (options & WNOHANG) {
122
            return 0;
123
        }
124
        if (options != 0) {
125
            errno = EINVAL;
126
            return -1;
127
        }
128
        result = wait(&status);
129
#else
130
        result = wait3(&status, options, 0);
131
#endif
132
        if ((result == -1) && (errno == EINTR)) {
133
            continue;
134
        }
135
        if (result <= 0) {
136
            return result;
137
        }
138
 
139
        if ((pid != result) && (pid != -1)) {
140
            goto saveInfo;
141
        }
142
        if (!(options & WUNTRACED) && (WIFSTOPPED(status))) {
143
            goto saveInfo;
144
        }
145
        *statusPtr = *((int *) &status);
146
        return result;
147
 
148
        /*
149
         * Can't return this info to caller.  Save it in the list of
150
         * stopped or exited processes.  Tricky point: first check for
151
         * an existing entry for the process and overwrite it if it
152
         * exists (e.g. a previously stopped process might now be dead).
153
         */
154
 
155
        saveInfo:
156
        for (waitPtr = deadList; waitPtr != NULL; waitPtr = waitPtr->nextPtr) {
157
            if (waitPtr->pid == result) {
158
                waitPtr->status = status;
159
                goto waitAgain;
160
            }
161
        }
162
        waitPtr = (WaitInfo *) ckalloc(sizeof(WaitInfo));
163
        waitPtr->pid = result;
164
        waitPtr->status = status;
165
        waitPtr->nextPtr = deadList;
166
        deadList = waitPtr;
167
 
168
        waitAgain: continue;
169
    }
170
}

powered by: WebSVN 2.1.0

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