Пример #1
0
static IDATA init_group_list() {
    // Initial group, does not contain any actual group, but serves 
    //as a head and a tail of this list;
    hythread_group_t dummy;

    
    //this group will exist as long as TM lives, so it's ok to have 
    //the same pool for them
    ////
    dummy = (hythread_group_t)apr_pcalloc(TM_POOL, sizeof(HyThreadGroup));
    assert(dummy);

    dummy->next = dummy->prev = dummy;
    group_list = dummy;
    groups_count = 0;

    lock_table = (HyFatLockTable *) malloc (sizeof(HyFatLockTable));
    memset(lock_table, 0, sizeof(HyFatLockTable));
    lock_table->tables[0] = (hythread_monitor_t *)calloc(HY_FAT_TABLE_ENTRIES,
                                              sizeof(hythread_monitor_t));
    lock_table->live_objs = (unsigned char *)calloc(HY_FAT_TABLE_ENTRIES,
                                         sizeof(unsigned char));
    lock_table->size = HY_FAT_TABLE_ENTRIES;
    lock_table->array_cursor = 0;

    assert (lock_table);
    assert (lock_table->tables[0]);
    assert (lock_table->live_objs);
    
    if (port_mutex_create(&lock_table->mutex, APR_THREAD_MUTEX_NESTED)) {
        return TM_ERROR_OUT_OF_MEMORY;
    }

    if (hycond_create(&lock_table->write)) {
        return TM_ERROR_OUT_OF_MEMORY;
    }

    if (hycond_create(&lock_table->read)) {
        return TM_ERROR_OUT_OF_MEMORY;
    }
    
    lock_table->readers_reading = 0;
    lock_table->readers_waiting = 0;
    lock_table->writers_waiting = 0;
    lock_table->state = HYTHREAD_LOCKTABLE_IDLE;

    return TM_ERROR_NONE;
}
Пример #2
0
/**
 * Creates new latch.
 *
 * Latch allows one or more threads to wait until a set of operations 
 * being performed in other threads are complete. Latch serves as a gate for the threads 
 * which are waiting until it is opened. Latch initialized to N counts can be used 
 * to make one thread wait until N threads have completed some action, or some
 * action has been performed N times.
 * The key difference between latch and traditional semaphore is that latch notifies 
 * every waiting threads when it reaches zero, while semaphore notifies only one waiting thread.
 *
 * @param[out] latch the memory address where the newly created latch 
 *        will be stored
 * @param[in] count the created key
 * @sa java.util.concurrent.CountDownLatch 
 */
IDATA VMCALL hylatch_create(hylatch_t *latch_ptr, IDATA count) {
    int res;
    hylatch_t latch;
    
    latch = malloc(sizeof(HyLatch));
    if (latch == NULL) {
        return TM_ERROR_OUT_OF_MEMORY;
    }
    res = port_mutex_create(&latch->mutex, APR_THREAD_MUTEX_DEFAULT);
    if (res) {
        goto cleanup;
    }
    res = hycond_create(&latch->condition);
    if (res) {
        goto cleanup_mutex;
    }
    latch->count = count;
    *latch_ptr = latch;
    return TM_ERROR_NONE;

cleanup_mutex:
    port_mutex_destroy(&latch->mutex);

cleanup:
    free(latch);
    return res;
}
Пример #3
0
/**
 * Acquire and initialize a new monitor from the threading library.
 *
 * @param[out] mon_ptr pointer to a hythread_monitor_t to be set to point to the new monitor
 * @param[in] flags initial flag values for the monitor
 * @param[in] name pointer to a C string with a description of how the monitor will be used (may be NULL)<br>
 * If non-NULL, the C string must be valid for the entire life of the monitor
 *
 * @return  0 on success or negative value on failure
 *
 * @see hythread_monitor_destroy
 *
 */
IDATA VMCALL hythread_monitor_init_with_name(hythread_monitor_t *mon_ptr, UDATA flags, const char *name) {
    int r;
    hythread_monitor_t mon;

    mon = calloc(1, sizeof(HyThreadMonitor));
    if (mon == NULL) {
        return TM_ERROR_OUT_OF_MEMORY;
    }
    r = port_mutex_create(&mon->mutex, APR_THREAD_MUTEX_NESTED);
    if (r) {
        goto cleanup;
    }
    r = hycond_create(&mon->condition);
    if (r) {
        goto cleanup;
    }

    mon->flags = flags;
    mon->name  = name;

    *mon_ptr = mon;
    return TM_ERROR_NONE;

cleanup:
    free(mon);
    return r;
}
Пример #4
0
/**
 * Initialize a threading library.
 * 
 * @note This must only be called once.
 * 
 * If any OS threads were created before calling this function, they must be attached using
 * hythread_attach before accessing any thread library functions. 
 * 
 * @param[in] lib pointer to the thread library to be initialized (non-NULL)
 * @return The thread library's initStatus will be set to 0 on success or 
 * a negative value on failure.
 */
void VMCALL hythread_init(hythread_library_t lib) {
    apr_status_t apr_status;
    IDATA status;
    hythread_monitor_t *mon;

    // Current implementation doesn't support more than one library instance.
    if (TM_LIBRARY == NULL) {
        TM_LIBRARY = lib;
    }
    assert(TM_LIBRARY == lib);

    if (hythread_library_state != TM_LIBRARY_STATUS_NOT_INITIALIZED)
        return;
    hythread_library_state = TM_LIBRARY_STATUS_INITIALIZED;
     
    apr_status = apr_initialize();
    assert(apr_status == APR_SUCCESS);
    // TM_POOL will be NULL if hythread_lib_create was not used to create the library
    if (TM_POOL == NULL) {
        apr_status = apr_pool_create(&TM_POOL, NULL);
        assert(apr_status == APR_SUCCESS);
    }

    apr_status = apr_threadkey_private_create(&TM_THREAD_KEY, NULL, TM_POOL);
    assert(apr_status == APR_SUCCESS);
    
    status = port_mutex_create(&lib->TM_LOCK, APR_THREAD_MUTEX_NESTED);
    assert(status == TM_ERROR_NONE);
    status = port_mutex_create(&TM_START_LOCK, APR_THREAD_MUTEX_NESTED);
    assert(status == TM_ERROR_NONE);
     
    status = init_group_list();
    assert(status == TM_ERROR_NONE);

    // Create default group - hosts any thread crated with NULL group
    status = hythread_group_create(&TM_DEFAULT_GROUP);
    assert(status == TM_ERROR_NONE);

    //nondaemon thread barrier
    ////
    lib->nondaemon_thread_count = 0;
    status = hycond_create(&lib->nondaemon_thread_cond);
    assert(status == TM_ERROR_NONE);
 
    // init global monitor
    status=hythread_monitor_init_with_name(&p_global_monitor, 0, "Thread Global Monitor");
    assert(status == TM_ERROR_NONE);

    mon = (hythread_monitor_t*)hythread_global(GLOBAL_MONITOR_NAME);
    *mon = p_global_monitor;
    assert(mon);
}