Esempio n. 1
0
/**
 * Deallocates the system resources used by the lock.
 */
void RWLOCK_Destroy(RWLock * lock) 
{
    QEntry * e;
    ASSERT(!lock->locks);
    ASSERT(!lock->entriesInUse);
    ASSERT(!lock->entriesActive);
    ASSERT(!lock->shareWaiters.size);
    ASSERT(!lock->exclusiveWaiters.size);
    MUTEX_Destroy(&lock->mutex);
    EVENT_Destroy(&lock->shareEvent);
    EVENT_Destroy(&lock->exclusiveEvent);

    /* free dynamically allocated entries */
    if (lock->moreEntries) {
        MEM_Free(lock->moreEntries);
        lock->moreEntries = NULL;
    }

    /* free waiter cache */
    while ((e = QUEUE_RemoveHead(&lock->waiterCache)) != NULL) {
        RWLockWaiter * w = QCAST(e,RWLockWaiter,entry);
        MEM_Free(w);
    }

    /* free dynamically allocated events */
    while (lock->eventsInCache > 0) {
        lock->eventsInCache--;
        ASSERT(lock->eventCache[lock->eventsInCache]);
        EVENT_Delete(lock->eventCache[lock->eventsInCache]);
        lock->eventCache[lock->eventsInCache] = NULL;
    }

    lock->numEntries = 0;
    lock->locks = -1;  /* to cause ASSERT if destroyed twice */
}
Esempio n. 2
0
/**
 * Creates and starts n worker thread
 */
WorkQueue * WKQ_CreatePool(int n)
{
    size_t size = sizeof(WorkQueue) + sizeof(ThrID)*(MAX(n,1)-1);
    WorkQueue * q = MEM_Alloc(size);
    if (q) {
        ASSERT(WKQ.initcount > 0);
        if (WKQ.initcount == 0) WKQ_InitModule();
        memset(q, 0, size);
        q->nthreads = n;
        if (MUTEX_Init(&q->mutex)) {
            if (EVENT_Init(&q->event)) {
                if (EVENT_Init(&q->stopEvent)) {
                    if (EVENT_Reset(&q->stopEvent)) {
                        int i;
                        q->flags = WKQ_ACTIVE;
                        QUEUE_Init(&q->items);
                        QUEUE_Init(&q->submit);
                        for (i=0; i<n; i++) {
                            if (!THREAD_Create(q->threads+i, WKQ_Thread, q)) {
                                WKQ_Delete(q);
                                return NULL;
                            }
                        }
                        return q;
                    }
                    EVENT_Destroy(&q->stopEvent);
                }
                EVENT_Destroy(&q->event);
            }
            MUTEX_Destroy(&q->mutex);
        }
        MEM_Free(q);
    }
    return NULL;
}
Esempio n. 3
0
/**
 * Deallocates the work queue
 */
STATIC void WKQ_Free(WorkQueue * q)
{
    ASSERT(QUEUE_IsEmpty(&q->submit));
    ASSERT(QUEUE_IsEmpty(&q->items));
    ASSERT(q->flags & WKQ_DEAD);

    EVENT_Destroy(&q->stopEvent);
    EVENT_Destroy(&q->event);
    MUTEX_Destroy(&q->mutex);

    MEM_Free(q);
}
Esempio n. 4
0
/**
 * Deletes and deallocates the event previously allocated with 
 * EVENT_Create()
 */
void EVENT_Delete(Event * e) 
{
    if (e) {
        EVENT_Destroy(e);
        MEM_Free(e);
    }
}
Esempio n. 5
0
/**
 * Puts work item to the global pool or deallocates it. Also deallocates 
 * the events associated with the work item. NOTE: this code is designed 
 * to be efficient, not compact
 */
STATIC void WKQ_ReleaseWorkItem(WorkQueueModule * module, WorkItem * w)
{
    Bool locked = False;

    ASSERT(module->initcount > 0);
    ASSERT(!w->submitQ.queue);
    ASSERT(!w->itemsQ.queue);

    /* deallocate waiters */
    while (w->waiters) {
        Waiter * waiter = w->waiters;
        Waiter * next = waiter->next;

        if (module->nwait < module->maxwait) {
            if (locked) {
                WKQ_WaiterToPool(module, waiter);
                waiter = NULL;
            } else {
                locked = MUTEX_Lock(&module->mutex);
                if (module->nwait < module->maxwait) {                    
                    WKQ_WaiterToPool(module, waiter);
                    waiter = NULL;
                }
            }
        }

        if (waiter) {
            EVENT_Destroy(&waiter->event);
            MEM_Free(waiter);
        }

        w->waiters = next;
    }

    if (QUEUE_Size(&module->itempool) < module->maxitems) {
        if (locked) {
            w->flags = WKI_DETACHED;
            QUEUE_InsertTail(&module->itempool, &w->itemsQ);
        } else {
            locked = MUTEX_Lock(&module->mutex);
            if (QUEUE_Size(&module->itempool) < module->maxitems) {
                w->flags = WKI_DETACHED;
                QUEUE_InsertTail(&module->itempool, &w->itemsQ);
            } else {
                MEM_Free(w);
            }
        }
    } else {
        MEM_Free(w);
    }

    if (locked) {
        MUTEX_Unlock(&module->mutex);
    }
}
Esempio n. 6
0
/**
 * Decrements the reference count and deallocates the ThrData structure
 * when it reaches zero.
 */
STATIC void THREAD_Deref(ThrData* thr)
{
    ASSERT(thr->refCount > 0);
    ASSERT(thr->signature == ThrData_Signature);
    if (InterlockedDecrement(&thr->refCount) == 0) {
        ASSERT(!thr->cleanupList.data);
        if (!CloseHandle(thr->handle)) WIN32_FAILURE(CloseHandle);
        EVENT_Destroy(&thr->exitEvent);
        thr->signature = 0;
        MEM_Free(thr);
    }
}
Esempio n. 7
0
/**
 * Puts event back to the pool or deallocates it.
 */
STATIC void WKQ_ReleaseWaiter(WorkQueueModule * module, Waiter * waiter)
{
    ASSERT(module->initcount > 0);
    if (module->nwait < module->maxwait) {
        MUTEX_Lock(&module->mutex);
        if (module->nwait < module->maxwait) {
            WKQ_WaiterToPool(module, waiter);
            waiter = NULL;
        }
        MUTEX_Unlock(&module->mutex);
    }
    if (waiter) {
        EVENT_Destroy(&waiter->event);
        MEM_Free(waiter);
    }
}
Esempio n. 8
0
/**
 * Create a new thread, returning True on success
 */
Bool THREAD_Create(ThrID* id, ThrProc proc, void * arg)
{
    ThrData * thr = NULL;
    ASSERT(THREAD_IsInited());

    if (id) *id = NULL;
    if (!THREAD_IsInited()) return False;

    /* allocate thread data */
    thr = MEM_New(ThrData);
    if (thr) {
        memset(thr, 0, sizeof(*thr));
        if (EVENT_Init(&thr->exitEvent)) {
            InterlockedIncrement(&WIN32_ThreadCount);
            thr->signature = ThrData_Signature;
            thr->refCount = 2;
            thr->proc = proc;
            thr->arg = arg;

            /* create Win32 thread */
            thr->handle = CreateThread(NULL, 0, WIN32_ThreadProc, thr,
                                       CREATE_SUSPENDED, &thr->thrid);

            ASSERT(thr->handle);
            if (thr->handle) {
                if (ResumeThread(thr->handle) != (DWORD)-1) {
                    if (id) *id = thr;
                    return True;
                } else {
                    WIN32_FAILURE(ResumeThread);
                    VERIFY(CloseHandle(thr->handle));
                }

            } else {
                WIN32_FAILURE(CreateThread);
            }

            EVENT_Destroy(&thr->exitEvent);
            InterlockedDecrement(&WIN32_ThreadCount);
        }
        MEM_Free(thr);
    }

    return False;
}
Esempio n. 9
0
void WKQ_Shutdown()
{
    if ((--WKQ.initcount) == 0) {
        while (WKQ.waitpool) {
            Waiter * next = WKQ.waitpool->next;
            EVENT_Destroy(&WKQ.waitpool->event);
            MEM_Free(WKQ.waitpool);
            WKQ.waitpool = next;
            WKQ.nwait--;
        }
        ASSERT(WKQ.nwait == 0);
        while (!QUEUE_IsEmpty(&WKQ.itempool)) {
            QEntry * e = QUEUE_RemoveHead(&WKQ.itempool);
            WorkItem * w = QCAST(e,WorkItem,itemsQ);
            MEM_Free(w);
        }
        MUTEX_Destroy(&WKQ.mutex);
        THREAD_Shutdown();
    }
}
Esempio n. 10
0
/**
 * Initialize the lock.
 */
Bool RWLOCK_Init(RWLock * lock) 
{
    LOCK_InitCheck();
    memset(lock, 0, sizeof(*lock));
    if (MUTEX_Init(&lock->mutex)) {
        if (EVENT_Init(&lock->shareEvent)) {
            if (EVENT_Init(&lock->exclusiveEvent)) {
                QUEUE_Init(&lock->shareWaiters);
                QUEUE_Init(&lock->exclusiveWaiters);
                QUEUE_Init(&lock->waiterCache);
                lock->numEntries = COUNT(lock->staticEntries);
                lock->lock.type = &LockType_RWLock;
                return True;
            }
            EVENT_Destroy(&lock->shareEvent);
        }
        MUTEX_Destroy(&lock->mutex);
    }
    return False;
}
Esempio n. 11
0
/**
 * The program entry point
 */
int main(int argc, char * argv[]) 
{
    int mask = ECMTGW_LISTEN_DEFAULT_MASK;
    Bool traceReceive = False;
    Bool traceSend  = False;
    Str host = NULL;
    Str file = NULL;
    CmdLine* c;
    GwTrace trace;
    XRpcRegistry * r;

    /* Initialize the XRPC library */
    XRPC_Init();

    /* First step of initializing GwTrace context */ 
    memset(&trace, 0, sizeof(trace));
    VECTOR_Init(&trace.includeUid, 0, NULL, NULL);
    VECTOR_Init(&trace.excludeUid, 0, NULL, NULL);

    /* Parse command line */
    c = CMDLINE_Create(pname);
    if (c) {
        CmdOpt* includeOpt;
        CmdOpt* excludeOpt;
        Bool done = False;
        Bool help = False;

        CMDLINE_SetMaxArgs(c, 1);
        CMDLINE_AddTrueOpt(c,'h',"help",
            "print this help and exit",&help);
        CMDLINE_AddTrueOpt(c,'s',"sent",
            "trace packets sent to the handset",&traceSend);
        CMDLINE_AddTrueOpt(c,'r',"receive",
            "trace packets received from the handset",&traceReceive);
        includeOpt = CMDLINE_AddOpt(c,'u',"include",
            "include this UID in the trace (repeatable)",
            GWTRACE_ParseUidOpt, &trace.includeUid, "UID");
        excludeOpt = CMDLINE_AddOpt(c,'x',"exclude",
            "exclude this UID from the trace (repeatable)",
            GWTRACE_ParseUidOpt, &trace.excludeUid, "UID");
        CMDLINE_SetParamName(CMDLINE_AddStrOpt(c,'o',"output",
            "write binary Ecmt messages into a file",&file),"FILE");

        CMDLINE_SetRepeatable(includeOpt);
        CMDLINE_SetRepeatable(excludeOpt);
        CMDLINE_Exclude(includeOpt, excludeOpt);
        if (!CMDLINE_Parse1(c,argv+1,argc-1,0,&host) || help) {
            CMDLINE_Usage(c, "[HOST]", 0);
            CMDLINE_Delete(c);
            VECTOR_Destroy(&trace.includeUid);
            VECTOR_Destroy(&trace.excludeUid);
            XRPC_Deinit();
            return 0;
        }
        CMDLINE_Delete(c);
    }

    if (traceReceive || traceSend) {
        mask = 0;
        if (traceReceive) mask |= ECMTGW_LISTEN_MASK_RECEIVE;
        if (traceSend) mask |= ECMTGW_LISTEN_MASK_SEND;
    }

    /* connect to the registry */
    r = XREG_ConnectRegistry(host, XREG_DEFAULT_PORT);
    if (r) {

        /* find the server port */
        XRpcPort gwPort = 0;
        XREG_List(r, ECMTGW_PROTOCOL, GWTRACE_ListCB, &gwPort);
        XREG_FreeRegistry(r);

        if (gwPort) {
            if (EVENT_Init(&exitEvent)) {
                if (GWTRACE_Init(&trace, host, gwPort, file)) {

                    /* Install signal handlers */
                    #ifndef _WIN32
                    signal(SIGPIPE, GWTRACE_Interrupt);
                    #endif /* _WIN32 */
                    signal(SIGINT, GWTRACE_Interrupt);

                    /* Enable notifications */
                    XRPC_FormatNotify(XRPC_GetClient(trace.session), 
                        ECMTGW_PROTOCOL, 
                        ECMTGW_REGISTER_LISTENER_METHOD,"%"
                        ECMTGW_LISTENER_PROTOCOL_PARAM"!s%"
                        ECMTGW_LISTENER_MASK_PARAM"!i", 
                        ECMTGW_LISTENER_PROTOCOL, mask);

                    /* Wait */
                    EVENT_Wait(&exitEvent);

                    /* cleanup */
                    XRPC_FreeSession(trace.session);
                    XRPC_FreeServer(trace.server);
                    if (trace.file) FILE_Close(trace.file);
                }
                EVENT_Destroy(&exitEvent);
            }
        } else {
            PRINT_Error("%s: Ecmt Gateway is not running.\n",pname);
        }
    } else if (host) {
        PRINT_Verbose("%s: XRPC registry is not running on %s\n",pname,host);
        PRINT_Error("%s: Ecmt Gateway is not running on %s.\n",pname,host);
    } else {
        PRINT_Verbose("%s: XRPC registry is not running\n",pname);
        PRINT_Error("%s: Ecmt Gateway is not running.\n",pname);
    }

    VECTOR_Destroy(&trace.includeUid);
    VECTOR_Destroy(&trace.excludeUid);

    /* Deinitialize the XRPC library */
    XRPC_Deinit();
    return 0;
}