示例#1
0
/*
    Lock a mutex
 */
PUBLIC void mprSpinLock(MprSpin *lock)
{
    if (lock == 0) return;

#if ME_DEBUG
    /*
        Spin locks don't support recursive locking on all operating systems.
     */
    assert(lock->owner != mprGetCurrentOsThread());
#endif

#if USE_MPR_LOCK
    mprTryLock(&lock->cs);
#elif MACOSX
    OSSpinLockLock(&lock->cs);
#elif ME_UNIX_LIKE && ME_COMPILER_HAS_SPINLOCK
    pthread_spin_lock(&lock->cs);
#elif ME_UNIX_LIKE
    pthread_mutex_lock(&lock->cs);
#elif ME_WIN_LIKE
    if (!lock->freed) {
        EnterCriticalSection(&lock->cs);
    }
#elif VXWORKS
    semTake(lock->cs, WAIT_FOREVER);
#endif
#if ME_DEBUG
    assert(lock->owner != mprGetCurrentOsThread());
    lock->owner = mprGetCurrentOsThread();
#endif
}
示例#2
0
/*
    Try to attain a lock. Do not block! Returns true if the lock was attained.
 */
PUBLIC bool mprTrySpinLock(MprSpin *lock)
{
    int     rc;

    if (lock == 0) return 0;

#if USE_MPR_LOCK
    mprTryLock(&lock->cs);
#elif MACOSX
    rc = !OSSpinLockTry(&lock->cs);
#elif ME_UNIX_LIKE && ME_COMPILER_HAS_SPINLOCK
    rc = pthread_spin_trylock(&lock->cs) != 0;
#elif ME_UNIX_LIKE
    rc = pthread_mutex_trylock(&lock->cs) != 0;
#elif ME_WIN_LIKE
    rc = (lock->freed) ? 0 : (TryEnterCriticalSection(&lock->cs) == 0);
#elif VXWORKS
    rc = semTake(lock->cs, NO_WAIT) != OK;
#endif
#if ME_DEBUG && COSTLY
    if (rc == 0) {
        assert(lock->owner != mprGetCurrentOsThread());
        lock->owner = mprGetCurrentOsThread();
    }
#endif
    return (rc) ? 0 : 1;
}
示例#3
0
/*
    Start the dispatcher by putting it on the runQ. This prevents the event service from
    starting any events in parallel. The invoking thread should service events directly by
    calling mprServiceEvents or mprWaitForEvent.
 */
PUBLIC int mprStartDispatcher(MprDispatcher *dispatcher)
{
    if (dispatcher->owner && dispatcher->owner != mprGetCurrentOsThread()) {
        mprLog("error mpr event", 0, "Cannot start dispatcher - owned by another thread");
        return MPR_ERR_BAD_STATE;
    }
    if (!isRunning(dispatcher)) {
        queueDispatcher(dispatcher->service->runQ, dispatcher);
    }
    dispatcher->owner = mprGetCurrentOsThread();
    return 0;
}
示例#4
0
PUBLIC int mprStopDispatcher(MprDispatcher *dispatcher)
{
    if (dispatcher->owner != mprGetCurrentOsThread()) {
        assert(dispatcher->owner == mprGetCurrentOsThread());
        return MPR_ERR_BAD_STATE;
    }
    if (!isRunning(dispatcher)) {
        assert(isRunning(dispatcher));
        return MPR_ERR_BAD_STATE;
    }
    dispatcher->owner = 0;
    dequeueDispatcher(dispatcher);
    mprScheduleDispatcher(dispatcher);
    return 0;
}
示例#5
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);
}
示例#6
0
/*
    Run events for a dispatcher in a worker thread. When complete, reschedule the dispatcher as required.
 */
static void dispatchEventsWorker(MprDispatcher *dispatcher)
{
    if (dispatcher->flags & MPR_DISPATCHER_DESTROYED) {
        /* Dispatcher destroyed after worker started */
        return;
    }
    dispatcher->owner = mprGetCurrentOsThread();
    dispatchEvents(dispatcher);

    assert(dispatcher->owner == 0 || dispatcher->owner == mprGetCurrentOsThread());
    dispatcher->owner = 0;

    if (!(dispatcher->flags & MPR_DISPATCHER_DESTROYED)) {
        dequeueDispatcher(dispatcher);
        mprScheduleDispatcher(dispatcher);
    }
}
示例#7
0
PUBLIC void mprLock(MprMutex *lock)
{
    if (lock == NULL)
        return;
#if PLATFORM_LINUX
    pthread_mutex_lock(&lock->cs);
#endif
    lock->owner = mprGetCurrentOsThread();
}
示例#8
0
文件: mpr.c 项目: embedthis/mpr-3
/*
 *  If this thread is not responsibile for running the Mpr dispatcher then return true.
 */
bool mprMustWakeDispatcher(MprCtx ctx)
{
    Mpr     *mpr;

    mpr = mprGetMpr(ctx);

#if BLD_FEATURE_MULTITHREAD
    return mprGetCurrentOsThread() != mpr->serviceThread;
#else
    return 0;
#endif
}
示例#9
0
/*
    Wait for an event to occur on the dispatcher and service the event. This is not called by mprServiceEvents.
    The dispatcher may be "started" and owned by the thread, or it may be unowned.
    WARNING: the event may have already happened by the time this API is invoked.
    WARNING: this will enable GC while sleeping.
 */
PUBLIC int mprWaitForEvent(MprDispatcher *dispatcher, MprTicks timeout, int64 mark)
{
    MprEventService     *es;
    MprTicks            expires, delay;
    int                 runEvents, changed;

    if (dispatcher == NULL) {
        dispatcher = MPR->dispatcher;
    }
    if (dispatcher->flags & MPR_DISPATCHER_DESTROYED) {
        return 0;
    }
    if ((runEvents = (dispatcher->owner == mprGetCurrentOsThread())) != 0) {
        /* Called from an event on a running dispatcher */
        assert(isRunning(dispatcher) || (dispatcher->flags & MPR_DISPATCHER_DESTROYED));
        if (dispatchEvents(dispatcher)) {
            return 0;
        }
    }
    es = MPR->eventService;
    es->now = mprGetTicks();
    expires = timeout < 0 ? MPR_MAX_TIMEOUT : (es->now + timeout);
    if (expires < 0) {
        expires = MPR_MAX_TIMEOUT;
    }
    delay = expires - es->now;

    lock(es);
    delay = getDispatcherIdleTicks(dispatcher, delay);
    dispatcher->flags |= MPR_DISPATCHER_WAITING;
    changed = dispatcher->mark != mark && mark != -1;
    unlock(es);

    if (changed) {
        return 0;
    }
    mprYield(MPR_YIELD_STICKY);
    mprWaitForCond(dispatcher->cond, delay);
    mprResetYield();
    es->now = mprGetTicks();

    lock(es);
    dispatcher->flags &= ~MPR_DISPATCHER_WAITING;
    unlock(es);

    if (runEvents) {
        dispatchEvents(dispatcher);
        assert(isRunning(dispatcher) || (dispatcher->flags & MPR_DISPATCHER_DESTROYED));
    }
    return 0;
}
示例#10
0
PUBLIC int mprTryLock(MprMutex *lock)
{
    int rc;
    if (lock == NULL)
        return 0;
    
#if PLATFORM_LINUX
    rc = (pthread_mutex_trylock(&lock->cs) != 0);
#endif
    
    lock->owner = mprGetCurrentOsThread();
    
    return (rc) ? 0 : 1;
}
示例#11
0
/*
    Lock a mutex
 */
PUBLIC void mprLock(MprMutex *lock)
{
    if (lock == 0) return;
#if ME_UNIX_LIKE
    pthread_mutex_lock(&lock->cs);
#elif ME_WIN_LIKE
    if (!lock->freed) {
        EnterCriticalSection(&lock->cs);
    }
#elif VXWORKS
    semTake(lock->cs, WAIT_FOREVER);
#endif
#if ME_DEBUG
    /* Store last locker only */
    lock->owner = mprGetCurrentOsThread();
#endif
}
示例#12
0
/*
    Try to attain a lock. Do not block! Returns true if the lock was attained.
 */
PUBLIC bool mprTryLock(MprMutex *lock)
{
    int     rc;

    if (lock == 0) return 0;

#if ME_UNIX_LIKE
    rc = pthread_mutex_trylock(&lock->cs) != 0;
#elif ME_WIN_LIKE
    rc = TryEnterCriticalSection(&lock->cs) == 0;
#elif VXWORKS
    rc = semTake(lock->cs, NO_WAIT) != OK;
#endif
#if ME_DEBUG
    lock->owner = mprGetCurrentOsThread();
#endif
    return (rc) ? 0 : 1;
}
示例#13
0
/*
    Get the next (ready) dispatcher off given runQ and move onto the runQ
 */
static MprDispatcher *getNextReadyDispatcher(MprEventService *es)
{
    MprDispatcher   *dp, *next, *pendingQ, *readyQ, *waitQ, *dispatcher;
    MprEvent        *event;

    waitQ = es->waitQ;
    readyQ = es->readyQ;
    pendingQ = es->pendingQ;
    dispatcher = 0;

    lock(es);
    if (pendingQ->next != pendingQ && mprAvailableWorkers() > 0) {
        dispatcher = pendingQ->next;

    } else if (readyQ->next == readyQ) {
        /*
            ReadyQ is empty, try to transfer a dispatcher with due events onto the readyQ
         */
        for (dp = waitQ->next; dp != waitQ; dp = next) {
            next = dp->next;
            event = dp->eventQ->next;
            if (event->due <= es->now) {
                queueDispatcher(es->readyQ, dp);
                break;
            }
        }
    }
    if (!dispatcher && readyQ->next != readyQ) {
        dispatcher = readyQ->next;
    }
    /*
        Reserve the dispatcher. This may get transferred to a worker
     */
    if (dispatcher) {
        dispatcher->owner = mprGetCurrentOsThread();
    }
    unlock(es);
    return dispatcher;
}
示例#14
0
/*
    Run events for a dispatcher
 */
static int dispatchEvents(MprDispatcher *dispatcher)
{
    MprEventService     *es;
    MprEvent            *event;
    MprOsThread         priorOwner;
    int                 count;

    if (mprIsStopped()) {
        return 0;
    }
    assert(isRunning(dispatcher));
    es = dispatcher->service;

    priorOwner = dispatcher->owner;
    assert(priorOwner == 0 || priorOwner == mprGetCurrentOsThread());

    dispatcher->owner = mprGetCurrentOsThread();

    /*
        Events are removed from the dispatcher queue and put onto the currentQ. This is so they will be marked for GC.
        If the callback calls mprRemoveEvent, it will not remove from the currentQ. If it was a continuous event,
        mprRemoveEvent will clear the continuous flag.

        OPT - this could all be simpler if dispatchEvents was never called recursively. Then a currentQ would not be needed,
        and neither would a running flag. See mprRemoveEvent().
     */
    for (count = 0; (event = mprGetNextEvent(dispatcher)) != 0; count++) {
        assert(!(event->flags & MPR_EVENT_RUNNING));
        event->flags |= MPR_EVENT_RUNNING;

        assert(event->proc);
        mprAtomicAdd64(&dispatcher->mark, 1);

        (event->proc)(event->data, event);
        if (event->cond) {
            mprSignalCond(event->cond);
        }

        if (dispatcher->flags & MPR_DISPATCHER_DESTROYED) {
            break;
        }
        event->flags &= ~MPR_EVENT_RUNNING;

        lock(es);
        if (event->flags & MPR_EVENT_CONTINUOUS) {
            /*
                Reschedule if continuous
             */
            if (event->next) {
                mprDequeueEvent(event);
            }
            event->timestamp = dispatcher->service->now;
            event->due = event->timestamp + (event->period ? event->period : 1);
            mprQueueEvent(dispatcher, event);
        } else {
            mprDequeueEvent(event);
        }
        es->eventCount++;
        unlock(es);
        assert(dispatcher->owner == mprGetCurrentOsThread());
    }
    dispatcher->owner = priorOwner;
    return count;
}
示例#15
0
static ulong sslThreadId()
{
    return (long) mprGetCurrentOsThread();
}