Пример #1
0
/**
 * Detach thread from group if it is attached to.
 */
IDATA VMCALL hythread_remove_from_group(hythread_t thread)
{
    IDATA status;

    if (!thread->group) {
        return TM_ERROR_NONE;
    }

    status = hythread_global_lock();
    assert(status == TM_ERROR_NONE);

    // The thread can be detached from the other thread in case
    // of forceful termination by hythread_cancel(), but thread
    // local storage can be zeroed only for current thread.
    if (thread == hythread_self() ) {
        hythread_set_self(NULL);
    }
    fast_thread_array[thread->thread_id] = NULL;

    thread->prev->next = thread->next;
    thread->next->prev = thread->prev;
    thread->group->threads_count--;
    thread->group = NULL;

    status = hythread_global_unlock();
    assert(status == TM_ERROR_NONE);

    return TM_ERROR_NONE;
}
Пример #2
0
/**
 * Detaches a thread from the threading library.
 * Assumes that the thread is being detached is already attached.
 *
 * @param[in] thread A hythread_t representing the thread to be detached.
 *                   If this is NULL, the current thread is detached.
 */
void VMCALL hythread_detach_ex(hythread_t thread)
{
    IDATA status;

    // Acquire global TM lock to prevent concurrent access to thread list
    status = hythread_global_lock();
    assert(status == TM_ERROR_NONE);

    if (thread == NULL) {
        thread = hythread_self();
    }
    assert(thread);

    // Detach if thread is attached to group.
    hythread_remove_from_group(thread);

    if (thread == hythread_self()) // Detach current thread only
        port_thread_detach();

    // FIXME - uncomment after TM state transition complete
    // release thread data
    //hythread_struct_release(thread);
    
    status = hythread_global_unlock();
    assert(status == TM_ERROR_NONE);
}
Пример #3
0
/**
 * Returns all monitors owned by the specific thread.
 *
 * @param[in] java_thread thread which owns monitors
 * @param[out] monitor_count_ptr number of owned monitors 
 * @param[out] monitors_ptr array of owned monitors
 */
IDATA VMCALL
jthread_get_owned_monitors(jthread java_thread,
                           jint *monitor_count_ptr,
                           jobject **monitors_ptr)
{
    assert(java_thread);
    assert(monitors_ptr);
    assert(monitor_count_ptr);

    IDATA status = hythread_global_lock();
    if (status != TM_ERROR_NONE) {
        return status;
    }
    vm_thread_t vm_thread = jthread_get_vm_thread_from_java(java_thread);
    if (!vm_thread) {
        status = hythread_global_unlock();
        return status;
    }
    jvmti_thread_t jvmti_thread = &vm_thread->jvmti_thread;
    if (!jvmti_thread)
	{
        status = hythread_global_unlock();
        return status;
	}

    jobject *monitors =
        (jobject *) malloc(sizeof(jobject *) *
                           jvmti_thread->owned_monitors_nmb);
    if (!monitors) {
        hythread_global_unlock();
        return TM_ERROR_OUT_OF_MEMORY;
    }

    tmn_suspend_disable();
    for (int i = 0; i < jvmti_thread->owned_monitors_nmb; i++) {
        jobject new_ref = oh_allocate_local_handle_from_jni();

        if (NULL != new_ref)
            new_ref->object = jvmti_thread->owned_monitors[i]->object;
        else
        {
            tmn_suspend_enable();   
            hythread_global_unlock();
            return TM_ERROR_OUT_OF_MEMORY;
        }
        // change the order of reported monitors to be compliant with RI
        monitors[jvmti_thread->owned_monitors_nmb - 1 - i] = new_ref;
    }
    tmn_suspend_enable();   

    *monitors_ptr = monitors;
    *monitor_count_ptr = jvmti_thread->owned_monitors_nmb;

    status = hythread_global_unlock();
    return status;
} // jthread_get_owned_monitors
Пример #4
0
/*
 * Get Thread CPU Time
 *
 * Return the CPU time utilized by the specified thread.
 *
 * OPTIONAL Functionality.
 */
jvmtiError JNICALL
jvmtiGetThreadCpuTime(jvmtiEnv* env,
                      jthread thread,
                      jlong* nanos_ptr)
{
    TRACE2("jvmti.timer", "GetThreadCpuTime called");
    IDATA status;
    SuspendEnabledChecker sec;
   /*
     * Check given env & current phase.
     */
    jvmtiPhase phases[] = {JVMTI_PHASE_LIVE};

    CHECK_EVERYTHING();

    CHECK_CAPABILITY(can_get_thread_cpu_time);

    if (NULL == nanos_ptr)
        return JVMTI_ERROR_NULL_POINTER;

    if (NULL == thread) {
        status = jthread_get_thread_cpu_time(NULL, nanos_ptr);

    } else {
        if (! is_valid_thread_object(thread))
            return JVMTI_ERROR_INVALID_THREAD;

        // lock thread manager to avoid occasional change of thread state
        hythread_global_lock();

        int state;// =thread_get_thread_state(thread);
        jvmtiError err = jvmtiGetThreadState(env, thread, &state);
        if (err != JVMTI_ERROR_NONE){
   	    return err;
	    }

        switch (state)
        {
        case JVMTI_THREAD_STATE_TERMINATED:     // thread is terminated
        case JVMTI_JAVA_LANG_THREAD_STATE_NEW:  // thread is new
            hythread_global_unlock();
            return JVMTI_ERROR_THREAD_NOT_ALIVE;
        default:    // thread is alive
            status = jthread_get_thread_cpu_time(thread, nanos_ptr);

            break;
        }

        hythread_global_unlock();
    }

    if (status != TM_ERROR_NONE)
        return JVMTI_ERROR_INTERNAL;

    return JVMTI_ERROR_NONE;
}
Пример #5
0
static IDATA jthread_init_jvmti_monitor_table()
{
    IDATA status = hythread_global_lock();
    if (status != TM_ERROR_NONE) {
        return status;
    }
    if (!jvmti_monitor_table) {
        if (array_create(&jvmti_monitor_table)) {
            hythread_global_unlock();
            return TM_ERROR_OUT_OF_MEMORY;
        }
        status = port_mutex_create(&jvmti_monitor_table_lock, APR_THREAD_MUTEX_NESTED);
        if (status != TM_ERROR_NONE) {
            hythread_global_unlock();
            return status;
        }
    }
    status = hythread_global_unlock();
    return status;
} // jthread_init_jvmti_monitor_table
Пример #6
0
ncaiError JNICALL
ncaiTerminateThread(ncaiEnv *env, ncaiThread thread)
{
    TRACE2("ncai.thread", "TerminateThread called");
    SuspendEnabledChecker sec;

    if (env == NULL)
        return NCAI_ERROR_INVALID_ENVIRONMENT;

    if (thread == NULL)
        return NCAI_ERROR_INVALID_THREAD;

    hythread_t hythread = reinterpret_cast<hythread_t>(thread);

    hythread_t self = hythread_self();

    if (hythread == self)
        return NCAI_ERROR_INVALID_THREAD;

    assert(thread);

    // grab hythread global lock
    hythread_global_lock();

    if (!ncai_thread_is_alive(hythread))
    {
        hythread_global_unlock();
        return NCAI_ERROR_THREAD_NOT_ALIVE;
    }

    IDATA UNUSED status = jthread_vm_detach(jthread_get_vm_thread(hythread));
    assert(status == TM_ERROR_NONE);

    hythread_cancel(hythread);

    // release hythread global lock
    hythread_global_unlock();

    return NCAI_ERROR_NONE;
}
Пример #7
0
static IDATA destroy_group_list() {
    hythread_group_t cur;
    IDATA status,status2;
    int i;

    // This method works only if there are no running threads.
    // there is no good way to kill running threads 
    status=hythread_global_lock();
    if (status != TM_ERROR_NONE) return status;

    cur = group_list->next;
    status = TM_ERROR_NONE;
    
    while (cur != group_list) {
        if (hythread_group_release(cur) == TM_ERROR_NONE) {
            cur = group_list->next;
        } else {
            status = TM_ERROR_RUNNING_THREADS;
            cur = cur->next;
        }
    }

    free(lock_table->live_objs);

    for (i = 0; i < HY_MAX_FAT_TABLES && lock_table->tables[i]; i++) {
        free(lock_table->tables[i]);
    }

    port_mutex_destroy(&lock_table->mutex);
    hycond_destroy(&lock_table->write);
    hycond_destroy(&lock_table->read);
    
    free(lock_table);

    status2=hythread_global_unlock();
    if (status2 != TM_ERROR_NONE) return status2;

    return status;
}
Пример #8
0
/**
 * Wrapper around user thread start proc.
 * Used to perform some duty jobs right after thread is started
 * and before thread is finished.
 */
static int HYTHREAD_PROC hythread_wrapper_start_proc(void *arg) {
    IDATA UNUSED status;
    hythread_t thread;
    hythread_start_proc_data start_proc_data;
    hythread_entrypoint_t start_proc;
    
    // store procedure arguments to local
    start_proc_data = *(hythread_start_proc_data_t) arg;
    free(arg);

    // get hythread global lock
    status = hythread_global_lock();
    assert(status == TM_ERROR_NONE);

    // get native thread
    thread = start_proc_data.thread;
    start_proc = start_proc_data.proc;

    CTRACE(("TM: native thread started: native: %p tm: %p",
        port_thread_current(), thread));

    // check hythread library state
    if (hythread_lib_state() != TM_LIBRARY_STATUS_INITIALIZED) {
        // set TERMINATED state
        port_mutex_lock(&thread->mutex);
        thread->state = TM_THREAD_STATE_TERMINATED;
        port_mutex_unlock(&thread->mutex);

        // set hythread_self()
        hythread_set_self(thread);
        assert(thread == hythread_self());

        // release thread structure data
        hythread_detach(thread);

        // zero hythread_self() because we don't do it in hythread_detach_ex()
        hythread_set_self(NULL);

        CTRACE(("TM: native thread terminated due to shutdown: native: %p tm: %p",
            port_thread_current(), thread));

        // release hythread global lock
        status = hythread_global_unlock();
        assert(status == TM_ERROR_NONE);

        return 0;
    }

    // register to group and set ALIVE & RUNNABLE states
    status = hythread_set_to_group(thread, start_proc_data.group);
    assert(status == TM_ERROR_NONE);

    // set hythread_self()
    hythread_set_self(thread);
    assert(thread == hythread_self());

    // set priority
    status = hythread_set_priority(thread, thread->priority);
    // FIXME - cannot set priority
    //assert(status == TM_ERROR_NONE);

    // release hythread global lock
    status = hythread_global_unlock();
    assert(status == TM_ERROR_NONE);

    // Do actual call of the thread body supplied by the user.
    start_proc(start_proc_data.proc_args);

    assert(hythread_is_suspend_enabled());

    // get hythread global lock
    status = hythread_global_lock();
    assert(status == TM_ERROR_NONE);

    // set TERMINATED state
    port_mutex_lock(&thread->mutex);
    thread->state = TM_THREAD_STATE_TERMINATED;
    port_mutex_unlock(&thread->mutex);

    // detach and free thread
    hythread_detach(thread);

    // release hythread global lock
    status = hythread_global_unlock();
    assert(status == TM_ERROR_NONE);

    return 0;
}
Пример #9
0
IDATA VMCALL hythread_set_to_group(hythread_t thread, hythread_group_t group) {

#ifdef ORDER
    int map_id;
#endif

    IDATA status;
    hythread_t cur, prev;

    assert(thread);
    assert(group);

Retry_lock:    
    // Acquire global TM lock to prevent concurrent access to thread list
    status = hythread_global_lock();
    assert(status == TM_ERROR_NONE);

#ifdef ORDER
#ifdef ORDER_DEBUG
    printf("[TEST]: hythread mapping to object (%d, %d)\n", thread->p_tid, thread->p_count);
#endif
    if(hythread_vm_is_initializing || (thread->p_tid == 0 && thread->p_count == 0)){
    }
    else{
        if(hythread_get_IsRecord()){
#ifdef ORDER_DEBUG
            printf("[RECORD]: RECORD IN hythread_set_to_group!!!\n");
#endif
            threadRunOrderFile = fopen("THREAD_CREATE_ORDER.log", "a+");
#ifdef ORDER_DEBUG
            assert(threadRunOrderFile);
#endif
            fprintf(threadRunOrderFile, "%d %d\n", thread->p_tid, thread->p_count);
            fflush(threadRunOrderFile);
            fclose(threadRunOrderFile);
            threadRunOrderFile = NULL;
        }
        else{
//#ifdef ORDER_DEBUG
            printf("[REPLAY]: REPLAY IN hythread_set_to_group!!!\n");
//#endif
            if(threadRunOrderFile == NULL){
                threadRunOrderFile = fopen("THREAD_CREATE_ORDER.log", "r");
            }
#ifdef ORDER_DEBUG
            assert(threadRunOrderFile);
#endif
            if(p_tid == -1 && p_count == -1){
#ifdef ORDER_DEBUG
                if(feof(threadRunOrderFile)){
                    assert(0);
                }
#endif
                fscanf(threadRunOrderFile, "%d %d\n", &p_tid, &p_count);
            }

            if(p_tid == thread->p_tid && p_count == thread->p_count){
                p_tid = -1;
                p_count = -1;
            }
            else{
                IDATA status_temp = hythread_global_unlock();
                assert(status_temp == TM_ERROR_NONE);
//#ifdef ORDER_DEBUG
	       printf("[THREAD_CREATE]: This is not the correct order of thread create, pthread_self %d\n", pthread_self());
//#endif
                usleep(1000);
                hythread_yield();
				
                goto Retry_lock;
            }
        }
    }
#endif

    assert(thread->os_handle);
    
    if (!thread->thread_id) {
        char free_slot_found = 0;

        unsigned int i;
        for(i = 0; i < MAX_ID; i++) {
            // increase next_id to allow thread_id change 
            next_id++;
            if (next_id == MAX_ID) {
	            next_id = 1;
            }
            if (fast_thread_array[next_id] == NULL) {
                thread->thread_id = next_id;
	            free_slot_found = 1;


#ifdef ORDER

                {
                    char name[40];
                    FILE* thread_map = NULL;
                    int current_pthread_id = (int)thread->os_handle;

                    sprintf(name, "THREAD_MAP_WORKING_CLASSLIB.log");

                    thread_map = fopen(name, "a+");
#ifdef ORDER_DEBUG
                    assert(thread_map);
#endif

                    fwrite(&next_id, sizeof(int), 1, thread_map);
                    fwrite(&current_pthread_id, sizeof(int), 1, thread_map);

                    fflush(thread_map);
                    fclose(thread_map);
                }





//    printf("create thread id : %d\n", (int)new_thread->os_handle);
                for (map_id = 0 ; map_id < ORDER_THREAD_NUM ; map_id ++ )
                {
                   if (pthreadid_tid_mapping[map_id][0] == (int)thread->os_handle)
                   {
                       Thread_Map tmap;
                       tmap.thread_global_id = next_id;
                       tmap.pthread_id = (int)thread->os_handle;
                       tmap.thread_assigned_id = pthreadid_tid_mapping[map_id][1];
//                       if (threadMapFile == NULL)
                       threadMapFile = fopen("RECORD_THREAD_MAP.log", "a+");
                       fwrite((char *)&tmap, 1, sizeof(Thread_Map), threadMapFile);
                       fflush(threadMapFile);
                       fclose(threadMapFile);
                       threadMapFile = NULL;

#ifdef ORDER_DEBUG
                       printf("pthread id exists : %d\n", (int)pthreadid_tid_mapping[map_id][0]);
                       printf("tid mapping : %d -> %d\n",pthreadid_tid_mapping[map_id][0], pthreadid_tid_mapping[map_id][1]);
#endif

                       break;
                   }
                   else if (pthreadid_tid_mapping[map_id][0] == 0)
                   {
                       Thread_Map tmap;
                       tmap.thread_global_id = next_id;
                       tmap.pthread_id = (int)thread->os_handle;
                       tmap.thread_assigned_id = next_id;
//                       if (threadMapFile == NULL)
                       threadMapFile = fopen("RECORD_THREAD_MAP.log", "a+");
                       fwrite((char *)&tmap, 1, sizeof(Thread_Map), threadMapFile);
                       fflush(threadMapFile);
                       fclose(threadMapFile);
                       threadMapFile = NULL;

                       pthreadid_tid_mapping[map_id][0] = (int)(int)thread->os_handle;
                       pthreadid_tid_mapping[map_id][1] = next_id;

#ifdef ORDER_DEBUG
                       printf("new pthread id : %d\n", (int)pthreadid_tid_mapping[map_id][0]);
                       printf("tid mapping : %d -> %d\n", pthreadid_tid_mapping[map_id][0], pthreadid_tid_mapping[map_id][1]);
#endif

                       break;
                   }
                   if(i == (ORDER_THREAD_NUM - 1))
                   {
                       printf("[yzm]Error : Thread Map overflow!\n");
			  assert(0);
                       exit(0);
                   }
                }
#endif

                break;
            }
        }

        if (!free_slot_found) {
            status = hythread_global_unlock();
            assert(status == TM_ERROR_NONE);
            return TM_ERROR_OUT_OF_MEMORY;
        }
    }

    assert(thread->thread_id);
    fast_thread_array[thread->thread_id] = thread;

    thread->group = group;
    group->threads_count++;
    cur  = group->thread_list->next;
    prev = cur->prev;
    thread->next = cur;
    thread->prev = prev;
    prev->next = cur->prev = thread;

    port_mutex_lock(&thread->mutex);
    thread->state |= TM_THREAD_STATE_ALIVE | TM_THREAD_STATE_RUNNABLE;
    port_mutex_unlock(&thread->mutex);

    status = hythread_global_unlock();
    assert(status == TM_ERROR_NONE);

    return TM_ERROR_NONE;
}
Пример #10
0
/**
 * Creates a new thread in a given group.
 *
 * @param[in] new_thread a new allocated thread.
 * @param[in] group      a thread group or NULL
 *                       in case of NULL this thread will go to the default group.
 * @param[in] stacksize  a new thread stack size or 0
 *                       in case of 0 the thread will be set the default stack size
 * @param[in] priority   a new thread priority or 0
 *                       in case of 0 the thread will be set HYTHREAD_PRIORITY_NORMAL priority
 * @param[in] func       a function to run in the new thread
 * @param[in] data       an argument to be passed to starting function
 */
IDATA VMCALL hythread_create_ex(hythread_t new_thread,
                                hythread_group_t group,
                                UDATA stacksize,
                                UDATA priority,
                                hythread_wrapper_t wrapper,
                                hythread_entrypoint_t func,
                                void *data)
{
    int result;
    hythread_t self;

    assert(new_thread);
	
#ifdef ORDER
    U_32 p_tid = new_thread->p_tid;
    U_32 p_count = new_thread->p_count;
#endif

    hythread_struct_init(new_thread);

#ifdef ORDER
    new_thread->p_tid = p_tid;
    new_thread->p_count = p_count;
#endif

    self = hythread_self();
    new_thread->library = self ? self->library : TM_LIBRARY;
    new_thread->priority = priority ? priority : HYTHREAD_PRIORITY_NORMAL;
    
    if (!wrapper) {
        hythread_start_proc_data_t start_proc_data;

        // No need to zero allocated memory because all fields are initilized below.
        start_proc_data =
            (hythread_start_proc_data_t) malloc(sizeof(hythread_start_proc_data));
        if (start_proc_data == NULL) {
            return TM_ERROR_OUT_OF_MEMORY;
        }

        // Set up thread body procedure 
        start_proc_data->thread = new_thread;
        start_proc_data->group = group == NULL ? TM_DEFAULT_GROUP : group;
        start_proc_data->proc = func;
        start_proc_data->proc_args = data;

        data = (void*)start_proc_data;

        // Set wrapper procedure
        wrapper = hythread_wrapper_start_proc;
    }

    // Need to make sure thread will not register itself with a thread group
    // until port_thread_create returned and initialized thread->os_handle properly.
    hythread_global_lock();
    result = port_thread_create(&new_thread->os_handle,
            stacksize ? stacksize : TM_DEFAULT_STACKSIZE,
            priority, wrapper, data);
    assert(/* error */ result || new_thread->os_handle /* or thread created ok */);

    hythread_global_unlock();

    return result;
}