示例#1
0
文件: mprAlloc.c 项目: sangfo/WMI_cmd
static int mprAllocException(MPR_LOC_DEC(ctx, loc), uint size, bool granted)
{
    MprApp		*app;
    MprAlloc	*alloc;
    int			rc;

    mprAssert(VALID_BLK(ctx));

    app = mprGetApp(ctx);
    alloc = &app->alloc;

    if (alloc->cback == 0) {
        return 0;
    }

    mprLock(app->allocLock);
    if (alloc->inAllocException == 0) {
        alloc->inAllocException = 1;
        mprUnlock(app->allocLock);

        rc = (alloc->cback)(app, size, alloc->stats.bytesAllocated, granted);

        mprLock(app->allocLock);
        app->alloc.inAllocException = 0;
        mprUnlock(app->allocLock);

        return rc;
    }
    return 0;
}
示例#2
0
文件: http.c 项目: varphone/ejs-2
static bool iterationsComplete()
{
    mprLock(app->mutex);
    if (app->verbose > 1) mprPrintf(".");
    if (++app->fetchCount >= app->iterations) {
        mprUnlock(app->mutex);
        return 1;
    }
    mprUnlock(app->mutex);
    return 0;
}
示例#3
0
文件: mpr.c 项目: embedthis/mpr-3
bool mprStop(Mpr *mpr)
{
    int     stopped;

    stopped = 1;

    mprLock(mpr->mutex);
    if (! (mpr->flags & MPR_STARTED) || (mpr->flags & MPR_STOPPED)) {
        mprUnlock(mpr->mutex);
        return 0;
    }
    mpr->flags |= MPR_STOPPED;

    /*
        Trigger graceful termination. This will prevent further tasks and events being created.
     */
    mprTerminate(mpr, 1);

#if BLD_FEATURE_HTTP
    mprStopHttpService(mpr->httpService);
#endif
    mprStopSocketService(mpr->socketService);
#if BLD_FEATURE_MULTITHREAD
    if (!mprStopWorkerService(mpr->workerService, MPR_TIMEOUT_STOP_TASK)) {
        stopped = 0;
    }
    if (!mprStopThreadService(mpr->threadService, MPR_TIMEOUT_STOP_TASK)) {
        stopped = 0;
    }
#endif
    mprStopModuleService(mpr->moduleService);
    mprStopOsService(mpr->osService);
    return stopped;
}
示例#4
0
文件: mprCmd.c 项目: embedthis/mpr-3
MprCmd *mprCreateCmd(MprCtx ctx)
{
    MprCmdService   *cs;
    MprCmd          *cmd;
    MprCmdFile      *files;
    int             i;
    
    cmd = mprAllocObjWithDestructorZeroed(ctx, MprCmd, cmdDestructor);
    if (cmd == 0) {
        return 0;
    }
    cmd->completeCond = mprCreateCond(cmd);
    cmd->timeoutPeriod = MPR_TIMEOUT_CMD;
    cmd->timestamp = mprGetTime(cmd);
    cmd->forkCallback = (MprForkCallback) closeFiles;

#if VXWORKS
    cmd->startCond = semCCreate(SEM_Q_PRIORITY, SEM_EMPTY);
    cmd->exitCond = semCCreate(SEM_Q_PRIORITY, SEM_EMPTY);
#endif
    files = cmd->files;
    for (i = 0; i < MPR_CMD_MAX_PIPE; i++) {
        files[i].clientFd = -1;
        files[i].fd = -1;
    }
#if BLD_FEATURE_MULTITHREAD
    cmd->mutex = mprCreateLock(cmd);
#endif
    cs = mprGetMpr(ctx)->cmdService;
    mprLock(cs->mutex);
    mprAddItem(cs->cmds, cmd);
    mprUnlock(cs->mutex);
    return cmd;
}
示例#5
0
static void sslDynLock(int mode, DynLock *dl, cchar *file, int line)
{
    if (mode & CRYPTO_LOCK) {
        mprLock(dl->mutex);
    } else {
        mprUnlock(dl->mutex);
    }
}
示例#6
0
/*
 *  Timer callback 
 */
static void timerCallback(void *data, MprEvent *event)
{
    mprLock(mutex);
    if (--markCount == 0) {
        mprSignalCond(complete);
    }
    mprStopContinuousEvent(event);
    mprUnlock(mutex);
}
示例#7
0
/*
    Timer callback 
 */
static void timerCallback(void *data, MprEvent *event)
{
    mprLock(app->mutex);
    if (--app->markCount == 0) {
        mprSignalCond(app->complete);
    }
    mprRemoveEvent(event);
    mprUnlock(app->mutex);
}
示例#8
0
文件: http.c 项目: varphone/ejs-2
static void waitForUser()
{
    int     c;

    mprLock(app->mutex);
    mprPrintf("Pause: ");
    if (read(0, (char*) &c, 1) < 0) {}
    mprUnlock(app->mutex);
}
示例#9
0
文件: http.c 项目: varphone/ejs-2
static int reportResponse(HttpConn *conn, cchar *url, MprTime elapsed)
{
    HttpRx      *rx;
    MprOff      bytesRead;
    char        *responseHeaders;
    int         status;

    if (mprShouldAbortRequests(conn)) {
        return 0;
    }
    app->status = status = httpGetStatus(conn);
    bytesRead = httpGetContentLength(conn);
    if (bytesRead < 0 && conn->rx) {
        bytesRead = conn->rx->bytesRead;
    }
    mprLog(6, "Response status %d, elapsed %Ld", status, elapsed);
    if (conn->error) {
        app->success = 0;
    }
    if (conn->rx && bytesRead > 0) {
        if (!app->noout) {
            mprPrintf("\n");
        }
        if (app->showHeaders) {
            responseHeaders = httpGetHeaders(conn);
            rx = conn->rx;
            mprPrintf("%s %d %s\n", conn->protocol, status, rx->statusMessage);
            if (responseHeaders) {
                mprPrintf("%s\n", responseHeaders);
            }
        } else if (app->showStatus) {
            mprPrintf("%d\n", status);
        }
    }
    if (status < 0) {
        mprError("Can't process request for \"%s\" %s", url, httpGetError(conn));
        return MPR_ERR_CANT_READ;

    } else if (status == 0 && conn->protocol == 0) {
        /* Ignore */;

    } else if (!(200 <= status && status <= 206) && !(301 <= status && status <= 304)) {
        if (!app->zeroOnErrors) {
            app->success = 0;
        }
        if (!app->showStatus) {
            mprError("Can't process request for \"%s\" (%d) %s", url, status, httpGetError(conn));
            return MPR_ERR_CANT_READ;
        }
    }
    mprLock(app->mutex);
    if (app->verbose && app->noout) {
        trace(conn, url, app->fetchCount, app->method, status, bytesRead);
    }
    mprUnlock(app->mutex);
    return 0;
}
示例#10
0
文件: http.c 项目: adammendoza/http
static void finishThread(MprThread *tp)
{
    if (tp) {
        mprLock(app->mutex);
        if (--app->activeLoadThreads <= 0) {
            mprTerminate(MPR_EXIT_DEFAULT, -1);
        }
        mprUnlock(app->mutex);
    }
}
示例#11
0
/*
    Event callback 
 */
static void eventCallback(void *data, MprEvent *event)
{
    //  TODO - should have atomic Inc
    mprLock(app->mutex);
    if (--app->markCount == 0) {
        mprSignalCond(app->complete);
    }
    mprRemoveEvent(event);
    mprUnlock(app->mutex);
}
示例#12
0
文件: http.c 项目: gitorup/appweb
static void finishThread(MprThread *tp)
{
    if (tp) {
        mprLock(app->mutex);
        if (--app->activeLoadThreads <= 0) {
            mprShutdown(MPR_EXIT_NORMAL, 0, 0);
        }
        mprUnlock(app->mutex);
    }
}
示例#13
0
/*
    Wait for the event to be triggered when there may be multiple waiters. This routine may return early due to
    other signals or events. The caller must verify if the signalled condition truly exists. If the event is already
    triggered, then it will return immediately. This call will not reset cp->triggered and must be reset manually.
    A timeout of -1 means wait forever. Timeout of 0 means no wait.  Returns 0 if the event was signalled.
    Returns < 0 for a timeout.

    WARNING: On unix, the pthread_cond_timedwait uses an absolute time (Ugh!). So time-warps for daylight-savings may
    cause waits to prematurely return.
 */
PUBLIC int mprWaitForMultiCond(MprCond *cp, MprTicks timeout)
{
    int         rc;
#if ME_UNIX_LIKE
    struct timespec     waitTill;
    struct timeval      current;
    int                 usec;
#else
    MprTicks            now, expire;
#endif

    if (timeout < 0) {
        timeout = MAXINT;
    }
#if ME_UNIX_LIKE
    gettimeofday(&current, NULL);
    usec = current.tv_usec + ((int) (timeout % 1000)) * 1000;
    waitTill.tv_sec = current.tv_sec + ((int) (timeout / 1000)) + (usec / 1000000);
    waitTill.tv_nsec = (usec % 1000000) * 1000;
#else
    now = mprGetTicks();
    expire = now + timeout;
#endif

#if ME_WIN_LIKE
    rc = WaitForSingleObject(cp->cv, (int) (expire - now));
    if (rc == WAIT_OBJECT_0) {
        rc = 0;
    } else if (rc == WAIT_TIMEOUT) {
        rc = MPR_ERR_TIMEOUT;
    } else {
        rc = MPR_ERR;
    }
#elif VXWORKS
    rc = semTake(cp->cv, (int) (expire - now));
    if (rc != 0) {
        if (errno == S_objLib_OBJ_UNAVAILABLE) {
            rc = MPR_ERR_TIMEOUT;
        } else {
            rc = MPR_ERR;
        }
    }
#elif ME_UNIX_LIKE
    mprLock(cp->mutex);
    rc = pthread_cond_timedwait(&cp->cv, &cp->mutex->cs,  &waitTill);
    if (rc == ETIMEDOUT) {
        rc = MPR_ERR_TIMEOUT;
    } else if (rc != 0) {
        rc = MPR_ERR;
    }
    mprUnlock(cp->mutex);
#endif
    return rc;
}
示例#14
0
文件: mpr.c 项目: embedthis/mpr-3
/*
 *  Full host name with domain. E.g. "server.domain.com"
 */
void mprSetHostName(MprCtx ctx, cchar *s)
{
    Mpr     *mpr;

    mpr = mprGetMpr(ctx);
    mprLock(mpr->mutex);
    mprFree(mpr->hostName);
    mpr->hostName = mprStrdup(mpr, s);
    mprUnlock(mpr->mutex);
    return;
}
示例#15
0
static void sslStaticLock(int mode, int n, cchar *file, int line)
{
    assert(0 <= n && n < numLocks);

    if (olocks) {
        if (mode & CRYPTO_LOCK) {
            mprLock(olocks[n]);
        } else {
            mprUnlock(olocks[n]);
        }
    }
}
示例#16
0
文件: module.c 项目: embedthis/mpr
PUBLIC void mprStopModuleService()
{
    MprModuleService    *ms;
    MprModule           *mp;
    int                 next;

    ms = MPR->moduleService;
    assert(ms);
    mprLock(ms->mutex);
    for (next = 0; (mp = mprGetNextItem(ms->modules, &next)) != 0; ) {
        mprStopModule(mp);
    }
    mprUnlock(ms->mutex);
}
示例#17
0
文件: mprCmd.c 项目: embedthis/mpr-3
static int cmdDestructor(MprCmd *cmd)
{
    MprCmdService   *cs;

    resetCmd(cmd);
#if VXWORKS
    vxCmdDestructor(cmd);
#endif
    cs = mprGetMpr(cmd)->cmdService;
    mprLock(cs->mutex);
    mprRemoveItem(cs->cmds, cmd);
    mprUnlock(cs->mutex);
    return 0;
}
示例#18
0
PUBLIC void mprResetCond(MprCond *cp)
{
    mprLock(cp->mutex);
    cp->triggered = 0;
#if ME_WIN_LIKE
    ResetEvent(cp->cv);
#elif VXWORKS
    semDelete(cp->cv);
    cp->cv = semCCreate(SEM_Q_PRIORITY, SEM_EMPTY);
#else
    pthread_cond_destroy(&cp->cv);
    pthread_cond_init(&cp->cv, NULL);
#endif
    mprUnlock(cp->mutex);
}
示例#19
0
/*
    Signal a condition and wakeup the waiter. Note: this may be called prior to the waiter waiting.
 */
PUBLIC void mprSignalCond(MprCond *cp)
{
    mprLock(cp->mutex);
    if (!cp->triggered) {
        cp->triggered = 1;
#if ME_WIN_LIKE
        SetEvent(cp->cv);
#elif VXWORKS
        semGive(cp->cv);
#else
        pthread_cond_signal(&cp->cv);
#endif
    }
    mprUnlock(cp->mutex);
}
示例#20
0
文件: testLock.c 项目: doghell/mpr-3
static void testCriticalSection(MprTestGroup *gp)
{
    int     i, size;

    mprLock(mutex);

    size = sizeof(critical) / sizeof(MprThread*);
    for (i = 0; i < size; i++) {
        critical[i] = mprGetCurrentOsThread();
    }
    for (i = 0; i < size; i++) {
        assert(critical[i] == mprGetCurrentOsThread());
    }
    mprUnlock(mutex);
}
示例#21
0
/*
    Signal a condition and wakeup the all the waiters. Note: this may be called before or after to the waiter waiting.
 */
PUBLIC void mprSignalMultiCond(MprCond *cp)
{
    mprLock(cp->mutex);
#if ME_WIN_LIKE
    /* Pulse event */
    SetEvent(cp->cv);
    ResetEvent(cp->cv);
#elif VXWORKS
    /* Reset sem count and then give once. Prevents accumulation */
    while (semTake(cp->cv, 0) == OK) ;
    semGive(cp->cv);
    semFlush(cp->cv);
#else
    pthread_cond_broadcast(&cp->cv);
#endif
    mprUnlock(cp->mutex);
}
示例#22
0
文件: mprAlloc.c 项目: sangfo/WMI_cmd
static void slabFree(MprBlk *bp)
{
    MprSlab			*slab;
    MprApp			*app;
    void			*ptr;
    int				slabIndex;

    mprAssert(VALID_HDR(bp));

    slabIndex = GET_SLAB(bp->size);
    mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB);

    if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) {
        mprLock(bp->app->allocLock);
        slab = &bp->app->alloc.slabs[slabIndex];
        app = bp->app;

#if BLD_DEBUG
        memset(bp, 0xfc, bp->size + HDR_SIZE);
#endif

        ptr = GET_PTR(bp);
        ((MprSlabBlock*) ptr)->next = slab->next;
        slab->next = ((MprSlabBlock*) ptr);

#if BLD_FEATURE_ALLOC_STATS
        {
            MprSlabStats	*slabStats;
            slabStats = &slab->stats;

            slabStats->freeCount++;
            slabStats->allocCount--;

            if (slabStats->freeCount >= slabStats->peakFreeCount) {
                slabStats->peakFreeCount = slabStats->freeCount;
            }
        }
#endif
        mprUnlock(app->allocLock);
    }
}
示例#23
0
PUBLIC void mprSpinUnlock(MprSpin *lock)
{
    if (lock == 0) return;

#if ME_DEBUG
    lock->owner = 0;
#endif

#if USE_MPR_LOCK
    mprUnlock(&lock->cs);
#elif MACOSX
    OSSpinLockUnlock(&lock->cs);
#elif ME_UNIX_LIKE && ME_COMPILER_HAS_SPINLOCK
    pthread_spin_unlock(&lock->cs);
#elif ME_UNIX_LIKE
    pthread_mutex_unlock(&lock->cs);
#elif ME_WIN_LIKE
    LeaveCriticalSection(&lock->cs);
#elif VXWORKS
    semGive(lock->cs);
#endif
}
示例#24
0
文件: mprAlloc.c 项目: sangfo/WMI_cmd
void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc)
{

#if NO_SLAB
    return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
#else

    MprBlk			*parent, *bp;
    MprSlabBlock	*sb;
    MprApp			*app;
    MprSlab			*slab;
    int				slabIndex;

    if (ctx == 0) {
        mprAssert(ctx);
        return 0;
    }

    mprAssert(size > 0);
    mprAssert(VALID_BLK(ctx));

    parent = GET_HDR(ctx);
    mprAssert(VALID_HDR(parent));

    CHECK_HDR(parent);

    size = SLAB_ALIGN(size);

    app = parent->app;
    mprAssert(app);

    slabIndex = GET_SLAB(size);

    if (slabIndex < 0 || slabIndex >= MPR_MAX_SLAB) {
        return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
    }

    /*
     *	Dequeue a block from the slab. "sb" will point to the user data
     *	portion of the block (i.e. after the MprBlk header). Slabs must be
     *	allocated off the "slabs" context to ensure they don't get freed
     *	until after all other blocks are freed.
     */
    mprLock(app->allocLock);
    slab = &app->alloc.slabs[slabIndex];
    if ((sb = slab->next) == 0) {
        if (growSlab(MPR_LOC_ARGS(parent->app->alloc.slabs),
                     slab, size, inc) < 0) {
            mprUnlock(app->allocLock);
            return 0;
        }
        sb = slab->next;
    }
    mprAssert(sb);

    /*
     *	Dequeue the block
     */
    slab->next = sb->next;

#if BLD_FEATURE_ALLOC_STATS
    {
        MprSlabStats	*slabStats;
        /*
         *	Update the slab stats
         */
        slabStats = &slab->stats;
        slabStats->totalAllocCount++;
        slabStats->freeCount--;
        slabStats->allocCount++;
        if (slabStats->allocCount > slabStats->peakAllocCount) {
            slabStats->peakAllocCount = slabStats->allocCount;
        }
    }
#endif /* BLD_FEATURE_ALLOC_STATS */

    bp = GET_HDR(sb);

#if BLD_DEBUG && !BREW
    if (bp == stopAlloc) {
        mprBreakpoint(MPR_LOC, "breakOnAddr");
    }
#endif

    bp->size = size;
    bp->flags = ALLOC_MAGIC | ALLOC_FLAGS_SLAB_BLOCK;
    bp->destructor = 0;

    bp->parent = parent;

    if (parent->children == 0) {
        parent->children = bp;
        bp->next = bp->prev = bp;

    } else {
        /*
         *	Append to the end of the list. Preserve alloc order
         */
        bp->next = parent->children;
        bp->prev = parent->children->prev;
        parent->children->prev->next = bp;
        parent->children->prev = bp;
    }

    bp->children = 0;

    bp->app = app;

#if BLD_FEATURE_ALLOC_LEAK_TRACK
    bp->location = loc;
#endif
    mprUnlock(app->allocLock);

    return GET_PTR(bp);
#endif
}
示例#25
0
PUBLIC void mprGlobalUnlock()
{
    if (MPR && MPR->mutex) {
        mprUnlock(MPR->mutex);
    }
}
示例#26
0
文件: host.c 项目: jsjohnst/appweb
static void unlock(MaHost *host)
{
#if BLD_FEATURE_MULTITHREAD
    mprUnlock(host->mutex);
#endif
}
示例#27
0
/*
 *  Do a performance benchmark
 */ 
static void doBenchmark(Mpr *mpr, void *thread)
{
    MprTime     start;
    MprList     *list;
    void        *mp;
    int         count, i;
#if BLD_FEATURE_MULTITHREAD
    MprMutex    *lock;
#endif

    complete = mprCreateCond(mpr);

    mprPrintf(mpr, "Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec");

    /*
     *  Alloc (1K)
     */
    mprPrintf(mpr, "Alloc Benchmarks\n");
    count = 2000000 * iterations;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mp = mprAlloc(mpr, 1024);
        memset(mp, 0, 1024);
        mprFree(mp);
    }
    endMark(mpr, start, count, "Alloc mprAlloc(1K)|mprFree");
    start = startMark(mpr);

#if BLD_FEATURE_MULTITHREAD
    /*
     *  Locking primitives
     */
    mprPrintf(mpr, "Lock Benchmarks\n");
    lock = mprCreateLock(mpr);
    count = 5000000 * iterations;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprLock(lock);
        mprUnlock(lock);
    }
    endMark(mpr, start, count, "Mutex lock|unlock");
    mprFree(lock);

    /*
     *  Condition signal / wait
     */
    mprPrintf(mpr, "Cond Benchmarks\n");
    count = 1000000 * iterations;
    start = startMark(mpr);
    mprResetCond(complete);
    for (i = 0; i < count; i++) {
        mprSignalCond(complete);
        mprWaitForCond(complete, -1);
    }
    endMark(mpr, start, count, "Cond signal|wait");
#endif

    /*
     *  List
     */
    mprPrintf(mpr, "List Benchmarks\n");
    count = 500000 * iterations;
    list = mprCreateList(mpr);
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprAddItem(list, (void*) (long) i);
        mprRemoveItem(list, (void*) (long) i);
    }
    endMark(mpr, start, count, "Link insert|remove");
    mprFree(list);;

    /*
     *  Events
     */
    mprPrintf(mpr, "Event Benchmarks\n");
    mprResetCond(complete);
    count = 200000 * iterations;
    markCount = count;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprCreateEvent(mprGetDispatcher(mpr), eventCallback, 0, 0, (void*) (long) i, 0);
    }
    endMark(mpr, start, count, "Event (create)");
    mprWaitForCondWithService(complete, -1);
    endMark(mpr, start, count, "Event (run|delete)");


    /*
     *  Test timer creation, run and delete (make a million timers!)
     */
    mprPrintf(mpr, "Timer\n");
    mprResetCond(complete);
    count = 50000 * iterations;
    markCount = count;
    start = startMark(mpr);
    for (i = 0; i < count; i++) {
        mprCreateTimerEvent(mprGetDispatcher(mpr), timerCallback, 0, 0, (void*) (long) i, 0);
    }
    endMark(mpr, start, count, "Timer (create)");
    mprWaitForCondWithService(complete, -1);
    endMark(mpr, start, count, "Timer (delete)");

    testComplete = 1;
}
示例#28
0
文件: mprAlloc.c 项目: sangfo/WMI_cmd
void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size)
{
    MprBlk	*bp, *newbp, *firstChild, *cp;
    MprApp	*app;
    void	*newPtr;

    mprAssert(VALID_BLK(ctx));
    mprAssert(size > 0);

    if (ptr == 0) {
        return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
    }

    mprAssert(VALID_BLK(ptr));
    bp = GET_HDR(ptr);
    mprAssert(bp);
    mprAssert(VALID_HDR(bp));

    CHECK_HDR(bp);

    if (size < bp->size) {
        return ptr;
    }

    newPtr = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);
    if (newPtr == 0) {
        bp->flags &= ~ALLOC_FLAGS_FREE;
        free(bp);
        return 0;
    }

    newbp = GET_HDR(newPtr);
    mprAssert(newbp->size >= size);
    memcpy((char*) newbp + HDR_SIZE, (char*) bp + HDR_SIZE, bp->size);
    mprAssert(newbp->size >= size);

    /*
     *	Fix the next / prev pointers
     */
    app = bp->app;
    mprLock(app->allocLock);
    newbp->next->prev = newbp;
    newbp->prev->next = newbp;

    /*
     *	Need to fix the parent pointer of all children
     */
    if ((firstChild = newbp->children) != 0) {
        cp = firstChild;
        do {
            cp->parent = newbp;
            cp = cp->next;
        } while (cp != firstChild);
    }

    /*
     *	May need to set the children pointer of our parent
     */
    if (newbp->parent->children == bp) {
        newbp->parent->children = newbp;
    }

    /*
     *	Free the original block
     */
    mprFree(ptr);

    mprUnlock(app->allocLock);

    return GET_PTR(newbp);
}
示例#29
0
/*
    Wait for the event to be triggered. Should only be used when there are single waiters. If the event is already
    triggered, then it will return immediately. Timeout of -1 means wait forever. Timeout of 0 means no wait.
    Returns 0 if the event was signalled. Returns < 0 for a timeout.

    WARNING: On unix, the pthread_cond_timedwait uses an absolute time (Ugh!). So time-warps for daylight-savings may
    cause waits to prematurely return.
 */
PUBLIC int mprWaitForCond(MprCond *cp, MprTicks timeout)
{
    MprTicks            now, expire;
    int                 rc;
#if ME_UNIX_LIKE
    struct timespec     waitTill;
    struct timeval      current;
    int                 usec;
#endif
    /*
        Avoid doing a mprGetTicks() if timeout is < 0
     */
    rc = 0;
    if (timeout >= 0) {
        if (timeout > MAXINT) {
            timeout = MAXINT;
        }
        now = mprGetTicks();
        expire = now + timeout;
        if (expire < 0) {
            expire = MPR_MAX_TIMEOUT;
        }
#if ME_UNIX_LIKE
        gettimeofday(&current, NULL);
        usec = current.tv_usec + ((int) (timeout % 1000)) * 1000;
        waitTill.tv_sec = current.tv_sec + ((int) (timeout / 1000)) + (usec / 1000000);
        waitTill.tv_nsec = (usec % 1000000) * 1000;
#endif
    } else {
        expire = -1;
        now = 0;
    }
    mprLock(cp->mutex);
    /*
        NOTE: The WaitForSingleObject and semTake APIs keeps state as to whether the object is signalled.
        WaitForSingleObject and semTake will not block if the object is already signalled. However, pthread_cond_
        is different and does not keep such state. If it is signalled before pthread_cond_wait, the thread will
        still block. Consequently we need to keep our own state in cp->triggered. This also protects against
        spurious wakeups which can happen (on windows).
     */
    do {
#if ME_WIN_LIKE
        /*
            Regardless of the state of cp->triggered, we must call WaitForSingleObject to consume the signalled
            internal state of the object.
         */
        mprUnlock(cp->mutex);
        rc = WaitForSingleObject(cp->cv, (int) (expire - now));
        mprLock(cp->mutex);
        if (rc == WAIT_OBJECT_0) {
            rc = 0;
            ResetEvent(cp->cv);
        } else if (rc == WAIT_TIMEOUT) {
            rc = MPR_ERR_TIMEOUT;
        } else {
            rc = MPR_ERR;
        }
#elif VXWORKS
        /*
            Regardless of the state of cp->triggered, we must call semTake to consume the semaphore signalled state
         */
        mprUnlock(cp->mutex);
        rc = semTake(cp->cv, (int) (expire - now));
        mprLock(cp->mutex);
        if (rc != 0) {
            if (errno == S_objLib_OBJ_UNAVAILABLE) {
                rc = MPR_ERR_TIMEOUT;
            } else {
                rc = MPR_ERR;
            }
        }

#elif ME_UNIX_LIKE
        /*
            The pthread_cond_wait routines will atomically unlock the mutex before sleeping and will relock on awakening.
            WARNING: pthreads may do spurious wakeups without being triggered
         */
        if (!cp->triggered) {
            do {
                if (now) {
                    rc = pthread_cond_timedwait(&cp->cv, &cp->mutex->cs,  &waitTill);
                } else {
                    rc = pthread_cond_wait(&cp->cv, &cp->mutex->cs);
                }
            } while ((rc == 0 || rc == EAGAIN) && !cp->triggered);
            if (rc == ETIMEDOUT) {
                rc = MPR_ERR_TIMEOUT;
            } else if (rc == EAGAIN) {
                rc = 0;
            } else if (rc != 0) {
                mprLog("error mpr thread", 0, "pthread_cond_timedwait error rc %d", rc);
                rc = MPR_ERR;
            }
        }
#endif
    } while (!cp->triggered && rc == 0 && (!now || (now = mprGetTicks()) < expire));

    if (cp->triggered) {
        cp->triggered = 0;
        rc = 0;
    } else if (rc == 0) {
        rc = MPR_ERR_TIMEOUT;
    }
    mprUnlock(cp->mutex);
    return rc;
}
示例#30
0
/*
    Do a performance benchmark
 */ 
static void doBenchmark(void *thread)
{
    MprTime         start;
    MprList         *list;
    int             count, i;
    MprMutex        *lock;
    MprSpin         *spin;

    mprPrintf("Group\t%-30s\t%13s\t%12s\n", "Benchmark", "Microsec", "Elapsed-sec");

    testMalloc();

    if (!app->testAllocOnly) {
        /*
            Locking primitives
         */
        mprPrintf("Lock Benchmarks\n");
        lock = mprCreateLock();
        count = 5000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprLock(lock);
            mprUnlock(lock);
        }
        endMark(start, count, "Mutex lock|unlock");
        
        /*
            Locking primitives
         */
        mprPrintf("Lock Benchmarks\n");
        spin = mprCreateSpinLock();
        count = 5000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprSpinLock(spin);
            mprSpinUnlock(spin);
        }
        endMark(start, count, "Spin lock|unlock");
        
        /*
            Condition signal / wait
         */
        mprPrintf("Cond Benchmarks\n");
        count = 1000000 * app->iterations;
        start = startMark();
        mprResetCond(app->complete);
        for (i = 0; i < count; i++) {
            mprSignalCond(app->complete);
            mprWaitForCond(app->complete, -1);
        }
        endMark(start, count, "Cond signal|wait");
        
        /*
            List
         */
        mprPrintf("List Benchmarks\n");
        count = 2000000 * app->iterations;
        list = mprCreateList(count, 0);
        start = startMark();
        for (i = 0; i < count; i++) {
            mprAddItem(list, (void*) (long) i);
            mprRemoveItem(list, (void*) (long) i);
        }
        endMark(start, count, "Link insert|remove");

        /*
            Events
         */
        mprPrintf("Event Benchmarks\n");
        mprResetCond(app->complete);
        count = 30000 * app->iterations;
        app->markCount = count;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprCreateEvent(NULL, "eventBenchmark", 0, eventCallback, ITOP(i), MPR_EVENT_QUICK);
        }
        mprWaitForCond(app->complete, -1);
        endMark(start, count, "Event (create|run|delete)");

        /*
            Test timer creation, run and remove
            These create a new dispatcher and run a worker thread.
         */
        mprPrintf("Timer\n");
        mprResetCond(app->complete);
        count = 20000 * app->iterations;
        app->markCount = count;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprCreateTimerEvent(NULL, "timerBenchmark", 0, timerCallback, (void*) (long) i, 0);
        }
        mprWaitForCond(app->complete, -1);
        endMark(start, count, "Timer (create|delete)");

        /*
            Alloc (1K)
         */
        mprPrintf("Alloc 1K Benchmarks\n");
        count = 2000000 * app->iterations;
        start = startMark();
        for (i = 0; i < count; i++) {
            mprAlloc(1024);
            if ((i % 128) == 0) {
                mprGC(0);
            }
        }
        endMark(start, count, "Alloc mprAlloc(1K)");
    }
    testComplete = 1;
}