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; }
/** * 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; }
/** * 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; }
/** * 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); }