Changeset 1571 for trunk/src


Ignore:
Timestamp:
Oct 10, 2004, 12:48:19 PM (21 years ago)
Author:
bird
Message:

First attempt on shared signal interface.

Location:
trunk/src/emx
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/emx/include/InnoTekLIBC/sharedpm.h

    • Property cvs2svn:cvs-rev changed from 1.7 to 1.8
    r1570 r1571  
    2929#include <sys/cdefs.h>
    3030#include <sys/types.h>
     31#include <sys/signal.h>
    3132
    3233__BEGIN_DECLS
     
    5657 * The SPM version.
    5758 */
    58 #define SPM_VERSION             0x00010000
     59#define SPM_VERSION             0x00010001
    5960
    6061/**
     
    105106    __LIBC_EXIT_REASON_MAKE_INT32 = 0x7fffffff
    106107} __LIBC_EXIT_REASON;
     108
     109
     110/**
     111 * Signal (queued).
     112 */
     113typedef struct __libc_SPMSignal
     114{
     115    /** Structure size. */
     116    unsigned                    cb;
     117    /** Pointer to the next signal. */
     118    struct __libc_SPMSignal    *pNext;
     119    /** Signal info. */
     120    siginfo_t                   Info;
     121} __LIBC_SPMSIGNAL;
     122/** Pointer to (queued) signal. */
     123typedef __LIBC_SPMSIGNAL *__LIBC_PSPMSIGNAL;
     124
    107125
    108126/** Inheritance FH Bundle Type.
     
    253271    /** Creation timestamp. */
    254272    unsigned                    uTimestamp;
     273    /** Incoming signal queue.
     274     * This is a LIFO for speed and size. The receiving process will
     275     * process them in the correct order of course.
     276     * For signals which aren't queable only one signal can be queued.
     277     */
     278    __LIBC_PSPMSIGNAL           pSigHead;
     279    /** Number of queued signals.
     280     * After it passes 48 signals, only SIGCHLD will be queued.
     281     * This means siqueue() won't work 100% according to spec. */
     282    unsigned                    cSigsQueued;
    255283
    256284    /** Reserved pool pointer field with default value 0. */
    257     unsigned                    aReserved[40 - 14];
     285    unsigned                    aReserved[40 - 16];
    258286
    259287    /** Number of possible pointers to shared memory starting at pvInherit.
     
    379407    __LIBC_SPMLOADAVG           LoadAvg;
    380408
     409    /** List of free signal structures. This will reduce
     410     * the time spent allocating a signal structure in most cases.
     411     * During SPM init 8 signal structures will be allocated and queued. */
     412    __LIBC_PSPMSIGNAL           pSigFreeHead;
     413    /** Number of free signal structures in the list.
     414     * This is used to prevent the list from growing infinitly under stress.
     415     * When cSigFree reaches 32 unused signal structures will be freed instead
     416     * of put in the list. */
     417    unsigned                    cSigFree;
     418    /** Number of active signals.
     419     * This is used to keep a reasonable limit of the number of active signal
     420     * structures so a process cannot exhaust the shared memory pool.
     421     * The maximum is defined by cSigMaxActive.
     422     */
     423    unsigned                    cSigActive;
     424    /** The maximum number of active signals.
     425     * This is initialized by the SPM creator but can be adjusted later.
     426     */
     427    unsigned                    cSigMaxActive;
     428
    381429    /* The rest of the block, up to cbProcess, is undefined in this version.
    382430     * Future versions of LIBC may use this area assuming it's initalized with zeros.
     
    593641
    594642/**
     643 * Queues a signal on another process.
     644 *
     645 * @returns 0 on success.
     646 * @returns Negative error code (errno.h) on failure.
     647 * @param   pSignal     Signal to queue.
     648 * @param   pid         Pid to queue it on.
     649 * @param   fQueued     Set if the signal type is queued.
     650 */
     651int     __libc_spmSigQueue(siginfo_t *pSignal, pid_t pid, int fQueued);
     652
     653/**
     654 * De-queues one or more pending signals.
     655 * @returns Number of de-queued signals on success.
     656 * @returns Negative error code (errno.h) on failure.
     657 * @param   paSignals   Where to store the signals.
     658 * @param   cSignals    Size of the signal array.
     659 * @param   cbSignal    Size of one signal entry.
     660 */
     661int     __libc_spmSigDequeue(siginfo_t *paSignals, unsigned cSignals, size_t cbSignal);
     662
     663
     664/**
    595665 * Checks the SPM memory for trouble.
    596666 *
  • trunk/src/emx/src/lib/sys/sharedpm.c

    • Property cvs2svn:cvs-rev changed from 1.9 to 1.10
    r1570 r1571  
    6262#include <os2emx.h>
    6363#include <stdlib.h>
     64#include <stddef.h>
    6465#include <string.h>
    6566#include <errno.h>
     
    116117static void spmCleanup(void);
    117118static void spmZombieOrFree(__LIBC_PSPMPROCESS pProcess);
     119static __LIBC_PSPMPROCESS spmQueryProcessInState(pid_t pid, __LIBC_SPMPROCSTAT enmState);
    118120static unsigned spmTimestamp(void);
    119121static __LIBC_PSPMPROCESS spmRegisterSelf(pid_t pid, pid_t pidParent);
     
    192194    PGINFOSEG   pGIS = GETGINFOSEG();
    193195    /* this will trigger after the default one, so no message. */
    194     if (pGIS->time >= 0x414a47ad && pGIS->time <= 0x41859c85)
     196    if (pGIS->time >= 0x414a47ad && pGIS->time <= (0x41859c85 + 2678400))
    195197        return;
    196198    asm("lock; movl 0,%eax\n\t"
     
    882884
    883885/**
     886 * Queues a signal on another process.
     887 *
     888 * @returns 0 on success.
     889 * @returns Negative error code (errno.h) on failure.
     890 * @param   pSignal     Signal to queue.
     891 * @param   pid         Pid to queue it on.
     892 * @param   fQueued     Set if the signal type is queued.
     893 */
     894int     __libc_spmSigQueue(siginfo_t *pSignal, pid_t pid, int fQueued)
     895{
     896    LIBCLOG_ENTER("pSignal=%p:{.si_signo=%d,..} pid=%d fQueued=%d\n", (void *)pSignal, pSignal->si_signo, pid, fQueued);
     897
     898    /*
     899     * Validate intput.
     900     * This is mostly because we wanna crash before we take the sem.
     901     */
     902    if (pSignal->si_signo <= 0 || pSignal->si_signo > SIGRTMAX)
     903    {
     904        LIBC_ASSERTM_FAILED("Invalid signal number %d\n", pSignal->si_signo);
     905        LIBCLOG_RETURN_INT(-EINVAL);
     906    }
     907    if (pSignal->auReserved[(sizeof(pSignal->auReserved) / sizeof(pSignal->auReserved[0])) - 1])
     908    {
     909        LIBC_ASSERTM_FAILED("Reserved field is not zero!\n");
     910        LIBCLOG_RETURN_INT(-EINVAL);
     911    }
     912
     913    /*
     914     * Request sem.
     915     */
     916    __LIBC_SPMXCPTREGREC    RegRec;
     917    int rc = spmRequestMutex(&RegRec);
     918    if (rc)
     919        LIBCLOG_RETURN_INT(rc);
     920
     921    /*
     922     * Find pid.
     923     */
     924    __LIBC_PSPMPROCESS pProcess = spmQueryProcessInState(pid, __LIBC_PROCSTATE_ALIVE);
     925    if (pProcess)
     926    {
     927        /*
     928         * Check if already pending.
     929         */
     930        __LIBC_PSPMSIGNAL   pSig = pProcess->pSigHead;
     931        if (!fQueued)
     932        {
     933            int iSignal = pSignal->si_signo;
     934            for (pSig = pProcess->pSigHead; pSig; pSig = pSig->pNext)
     935                if (pSig->Info.si_signo == iSignal)
     936                    break;
     937        }
     938        if (!pSig)
     939        {
     940            /*
     941             * Check that we're not exceeding any per process or system limits.
     942             */
     943            if (!gpSPMHdr->cSigMaxActive)
     944                gpSPMHdr->cSigMaxActive = 1024;
     945            if (    (   gpSPMHdr->cSigActive  < gpSPMHdr->cSigMaxActive
     946                     && pProcess->cSigsQueued < 48)
     947                || pSignal->si_signo == SIGCHLD)
     948            {
     949                /*
     950                 * Allocate a signal packet.
     951                 */
     952                if (gpSPMHdr->pSigFreeHead)
     953                {
     954                    __LIBC_PSPMSIGNAL pPrev = NULL;
     955                    for (pSig = gpSPMHdr->pSigFreeHead; pSig; pPrev = pSig, pSig = pSig->pNext)
     956                        if (pSig->cb == sizeof(*pSig))
     957                        {
     958                            if (pPrev)
     959                                pPrev->pNext = pSig->pNext;
     960                            else
     961                                gpSPMHdr->pSigFreeHead = pSig->pNext;
     962                            gpSPMHdr->cSigFree--;
     963                            break;
     964                        }
     965                }
     966                if (!pSig)
     967                {
     968                    pSig = spmAlloc(sizeof(*pSig));
     969                    if (pSig)
     970                        pSig->cb = sizeof(*pSig);
     971                }
     972                if (pSig)
     973                {
     974                    /*
     975                     * Copy the data and insert it into the queue.
     976                     */
     977                    pSig->pNext = pProcess->pSigHead;
     978                    pSig->Info = *pSignal;
     979                    pProcess->pSigHead = pSig;
     980                    pProcess->cSigsQueued++;
     981                    gpSPMHdr->cSigActive++;
     982                    rc = 0;
     983                }
     984                else
     985                {
     986                    LIBCLOG_MSG("Out of memory! Cannot allocate %d bytes for a signal packet!\n", sizeof(*pSig));
     987                    rc = -EAGAIN;
     988                }
     989            }
     990            else
     991            {
     992                LIBCLOG_MSG("Limit reached: cSigActive=%d cSigMaxActive=%d cSigsQueued=%d (max 48)\n",
     993                            gpSPMHdr->cSigActive, gpSPMHdr->cSigMaxActive, pProcess->cSigsQueued);
     994                rc = -EAGAIN;
     995            }
     996        }
     997        else
     998            LIBCLOG_MSG("Signal %d is already pending on pid %d. (ts=%x,pid=%d)\n",
     999                        pSignal->si_signo, pid, pSig->Info.si_timestamp, pSig->Info.si_pid);
     1000    }
     1001    else
     1002        rc = -ESRCH;
     1003
     1004    /*
     1005     * Release sem and be gone.
     1006     */
     1007    spmReleaseMutex(&RegRec);
     1008    LIBCLOG_RETURN_INT(rc);
     1009}
     1010
     1011/**
     1012 * De-queues one or more pending signals.
     1013 * @returns Number of de-queued signals on success.
     1014 * @returns Negative error code (errno.h) on failure.
     1015 * @param   paSignals   Where to store the signals.
     1016 * @param   cSignals    Size of the signal array.
     1017 * @param   cbSignal    Size of one signal entry.
     1018 */
     1019int     __libc_spmSigDequeue(siginfo_t *paSignals, unsigned cSignals, size_t cbSignal)
     1020{
     1021    LIBCLOG_ENTER("paSignals=%p cSignals=%d cbSignal=%d\n", (void *)paSignals, cSignals, cbSignal);
     1022
     1023    /*
     1024     * Validate input.
     1025     */
     1026    if (sizeof(siginfo_t) > cbSignal)
     1027    {
     1028        LIBC_ASSERTM_FAILED("Invalid siginfo_t size: cbSignal=%d sizeof(siginfo_t)=%d\n", cbSignal, sizeof(siginfo_t));
     1029        LIBCLOG_RETURN_INT(-EINVAL);
     1030    }
     1031    bzero(paSignals, cSignals * cbSignal); /* This'll trap if it's wrong :-) */
     1032
     1033    /*
     1034     * Request sem.
     1035     */
     1036    __LIBC_SPMXCPTREGREC    RegRec;
     1037    int rc = spmRequestMutex(&RegRec);
     1038    if (rc)
     1039        LIBCLOG_RETURN_INT(rc);
     1040
     1041    /*
     1042     * De-queue signals one-by-one.
     1043     */
     1044    while (gpSPMSelf->pSigHead && cSignals-- > 0)
     1045    {
     1046        /*
     1047         * Copy it.
     1048         */
     1049        __LIBC_PSPMSIGNAL pSig = gpSPMSelf->pSigHead;
     1050        if (pSig->cb >= sizeof(siginfo_t))
     1051            *paSignals = pSig->Info;
     1052        else
     1053            memcpy(paSignals, &pSig->Info, pSig->cb);
     1054
     1055        /*
     1056         * Unlink it and free it.
     1057         */
     1058        gpSPMSelf->pSigHead = pSig->pNext;
     1059        if (gpSPMSelf->cSigsQueued > 0)
     1060            gpSPMSelf->cSigsQueued--;
     1061        if (gpSPMHdr->cSigFree < 32)
     1062        {
     1063            pSig->pNext = gpSPMHdr->pSigFreeHead;
     1064            gpSPMHdr->pSigFreeHead = pSig;
     1065            gpSPMHdr->cSigFree++;
     1066        }
     1067        else
     1068            spmFree(pSig);
     1069
     1070        /* next */
     1071        rc++;
     1072        paSignals = (siginfo_t *)((char *)paSignals + cbSignal);
     1073    }
     1074
     1075    spmReleaseMutex(&RegRec);
     1076    LIBCLOG_RETURN_INT(rc);
     1077}
     1078
     1079
     1080
     1081/**
    8841082 * Checks the SPM memory for trouble.
    8851083 *
     
    10021200}
    10031201
     1202/**
     1203 * This function checks that there is at least 2k of writable
     1204 * stack available. If there isn't a crash is usually the
     1205 * result.
     1206 */
     1207static int spmRequestMutexStackChecker(void)
     1208{
     1209    char *pch = alloca(2048);
     1210    if (!pch)
     1211        return -1;
     1212    /* With any luck the compiler doesn't optimize this away. */
     1213    pch[0] = pch[1024] = pch[2044] = 0x7f;
     1214    return 0;
     1215}
    10041216
    10051217/**
     
    10261238
    10271239    /*
     1240     * Check stack.
     1241     */
     1242    if (spmRequestMutexStackChecker())
     1243    {
     1244        DosUnsetExceptionHandler(&pRegRec->Core);
     1245        FS_RESTORE();
     1246        LIBC_ASSERTM_FAILED("Too little stack left!\n");
     1247        LIBCLOG_RETURN_INT(-EFAULT);
     1248    }
     1249
     1250    /*
    10281251     * Check if initatied.
    10291252     */
     
    11011324    }
    11021325
    1103     __atomic_xchg((volatile unsigned *)(void *)&rc, 0); /* ..... */
    11041326    DosUnsetExceptionHandler(&pRegRec->Core);
    11051327    DosExitMustComplete(&ul);
     
    11241346    PTIB                    pTib;
    11251347    FS_VAR();
     1348
     1349    /*
     1350     * Size and offset assertions.
     1351     */
     1352    LIBC_ASSERT(sizeof(*gpSPMHdr) < SPM_PROCESS_SIZE);
     1353    LIBC_ASSERT(offsetof(__LIBC_SPMHEADER, pTcpip) == 72);
     1354    LIBC_ASSERT(offsetof(__LIBC_SPMHEADER, cSigMaxActive) == 124);
     1355    LIBC_ASSERT(offsetof(__LIBC_SPMPROCESS, cReferences) == 12);
     1356    LIBC_ASSERT(offsetof(__LIBC_SPMPROCESS, pvForkHandle) == 48);
     1357    LIBC_ASSERT(offsetof(__LIBC_SPMPROCESS, cPoolPointers) == 160);
     1358    LIBC_ASSERT(offsetof(__LIBC_SPMPROCESS, pInheritLocked) == 168);
    11261359
    11271360    /*
     
    12101443                gpSPMHdr->cb                = cb;
    12111444                gpSPMHdr->cbProcess         = SPM_PROCESS_SIZE;
    1212                 LIBC_ASSERT(sizeof(*gpSPMHdr) < SPM_PROCESS_SIZE);
    12131445                gpSPMHdr->pPoolTail         = gpSPMHdr->pPoolHead     = (__LIBC_PSPMPOOLCHUNK)((char *)gpSPMHdr + SPM_PROCESS_SIZE);
    12141446                gpSPMHdr->pPoolFreeTail     = gpSPMHdr->pPoolFreeHead = (__LIBC_PSPMPOOLCHUNKFREE)gpSPMHdr->pPoolTail;
     
    12191451                gpSPMHdr->pTcpip->cb        = sizeof(*gpSPMHdr->pTcpip);
    12201452                gpSPMHdr->pTcpip->cSockets  = sizeof(gpSPMHdr->pTcpip->acRefs) / sizeof(gpSPMHdr->pTcpip->acRefs[0]);
     1453                gpSPMHdr->cSigMaxActive     = 1024;
     1454                /* Pre-allocate a few signals. */
     1455                gpSPMHdr->cSigFree          = 8;
     1456                unsigned i = gpSPMHdr->cSigFree;
     1457                while (i--)
     1458                {
     1459                    __LIBC_PSPMSIGNAL  pSignal = spmAlloc(sizeof(*pSignal));
     1460                    pSignal->cb = sizeof(*pSignal);
     1461                    pSignal->pNext = gpSPMHdr->pSigFreeHead;
     1462                    gpSPMHdr->pSigFreeHead = pSignal;
     1463                }
    12211464            }
    12221465        }
     
    14601703    LIBCLOG_RETURN_VOID();
    14611704}
     1705
     1706
     1707/**
     1708 * Searches for a process with a given pid and state.
     1709 *
     1710 * @returns Pointer to the desired process on success.
     1711 * @returns NULL on failure.
     1712 * @param   pid         Process id to search for.
     1713 * @param   enmState    The state of the process.
     1714 */
     1715static __LIBC_PSPMPROCESS spmQueryProcessInState(pid_t pid, __LIBC_SPMPROCSTAT enmState)
     1716{
     1717    LIBCLOG_ENTER("pid=%d enmState=%d\n", pid, enmState);
     1718    __LIBC_PSPMPROCESS      pProcess;
     1719
     1720    /*
     1721     * Search process list.
     1722     */
     1723    for (pProcess = gpSPMHdr->apHeads[enmState]; pProcess ; pProcess = pProcess->pNext)
     1724        if (pProcess->pid == pid && pProcess->enmState == enmState)
     1725            LIBCLOG_RETURN_P(pProcess);
     1726
     1727    LIBCLOG_RETURN_P(NULL);
     1728}
     1729
    14621730
    14631731
Note: See TracChangeset for help on using the changeset viewer.