//------------------------------------------// // Software_Create // // Description: Function used to create // // software threads only. Used if creating // // a hardware thread fails. // //------------------------------------------// Huint software_create ( hthread_t * tid, hthread_attr_t * attr, Huint func_id, void * arg) { void * func; // --------------------------------------------- // Make sure tables are setup // --------------------------------------------- if (!table_initialized_flag) { // Assert flag table_initialized_flag = 1; // Init thread table init_thread_table(&global_thread_table); // Load entries with app-specific data load_my_table(); // Init function-to-accelerator table init_func_2_acc_table(); #ifdef ICAP // Initialize mutexes, ICAP, and bitfiles // for Partial Reconfiguration. init_PR_data(); #endif } #ifdef DEBUG_DISPATCH printf("Software thread\n"); #endif // Create a native/software thread on the host processor func = lookup_handle(&global_thread_table, func_id, TYPE_HOST); // Increment thread counter thread_counter++; return (hthread_create(tid, attr, func, arg)); }
/****************************************************************************** * copy_handle * * Copies a handle. Increments the reference count of the object referenced * by the handle. * * PARAMS * lpTable [I] Pointer to the handle table, which holds the handle to be copied. * handle [I] The handle to be copied. * copy [O] Pointer to a handle variable, where the copied handle is put. * * RETURNS * non zero, if successful * zero, if not successful (invalid handle or out of memory) */ int copy_handle(HANDLETABLE *lpTable, unsigned int handle, DWORD dwType, unsigned int *copy) { OBJECTHDR *pObject; int ret; TRACE("(lpTable=%p, handle=%d, copy=%p)\n", lpTable, handle, copy); EnterCriticalSection(&lpTable->mutex); if (!lookup_handle(lpTable, handle, dwType, &pObject)) { *copy = (unsigned int)INVALID_HANDLE_VALUE; LeaveCriticalSection(&lpTable->mutex); return 0; } ret = alloc_handle(lpTable, pObject, copy); LeaveCriticalSection(&lpTable->mutex); return ret; }
/****************************************************************************** * copy_handle * * Copies a handle. Increments the reference count of the object referenced * by the handle. * * PARAMS * lpTable [I] Pointer to the handle table, which holds the handle to be copied. * handle [I] The handle to be copied. * copy [O] Pointer to a handle variable, where the copied handle is put. * * RETURNS * non zero, if successful * zero, if not successful (invalid handle or out of memory) */ int copy_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy) { OBJECTHDR *pObject; int ret; TRACE("(lpTable=%p, handle=%ld, copy=%p)\n", lpTable, handle, copy); EnterCriticalSection(&lpTable->mutex); if (!lookup_handle(lpTable, handle, dwType, &pObject)) { *copy = (HCRYPTKEY)INVALID_HANDLE_VALUE; LeaveCriticalSection(&lpTable->mutex); return 0; } ret = alloc_handle(lpTable, pObject, copy); LeaveCriticalSection(&lpTable->mutex); return ret; }
Huint microblaze_create( hthread_t * tid, hthread_attr_t * attr, Huint func_id, void * arg, Huint ublaze) { Huint ret; void * func; assert(attr!=NULL); // Efficient NULL pointer check // --------------------------------------------- // Make sure tables are initialized // --------------------------------------------- if (table_initialized_flag == 0) { // Assert flag table_initialized_flag = 1; // Init thread table init_thread_table(&global_thread_table); // Load entries with app-specific data load_my_table(); // Init function-to-accelerator table init_func_2_acc_table(); } // --------------------------------------------- // Check if that specific MB is free // --------------------------------------------- if( !get_utilized_flags((void *) hwti_array[ublaze])) { // Create a native thread printf("Microblaze %d is either not Free or does not exist!\n",ublaze); func = lookup_handle(&global_thread_table, func_id, TYPE_HOST); if (func == (void*)TABLE_INIT) { ret = TABLE_INIT; } else { // Ignore passed in attribute #ifdef DEBUG_DISPATCH printf("Creating Native Thread!\n"); #endif ret = hthread_create(tid, NULL, func, arg); } } // --------------------------------------------- // Otherwise create a hetero thread // --------------------------------------------- else { // Create a heterogeneous thread func = lookup_handle(&global_thread_table, func_id, slave_table[ublaze].processor_type); if (func == (void*)TABLE_INIT) { ret = TABLE_INIT; } else { // Create thread hetero using V-HWTI[found] #ifdef DEBUG_DISPATCH printf("Creating Hetero Thread (CPU#%d)!\n",ublaze); #endif hthread_attr_init(attr); hthread_attr_sethardware( attr, (void*)hwti_array[ublaze] ); ret = hthread_create(tid, attr, func, arg); } } return ret; }
// (SMART) Dynamic thread creation function Huint dynamic_create_smart( hthread_t * tid, hthread_attr_t * attr, Huint func_id, void * arg) { Huint ret; void * func; // Efficient NULL pointer check assert(attr!=NULL); // --------------------------------------------- // Make sure tables are initialized // --------------------------------------------- if (table_initialized_flag == 0) { // Assert flag table_initialized_flag = 1; // Init thread table init_thread_table(&global_thread_table); // Load entries with app-specific data load_my_table(); // Init function-to-accelerator table init_func_2_acc_table(); } // --------------------------------------------- // Look for any free heterogeneous processors // --------------------------------------------- int i = 0; int found = NOT_FOUND; for (i = 0; i < NUM_AVAILABLE_HETERO_CPUS; i++) { if( get_utilized_flags((void *) &i)) { // Mark CPU that was found, and break out of loop found = i; break; } } // --------------------------------------------- // Create a native thread if no hetero CPUs are free // --------------------------------------------- if (found == NOT_FOUND) { // Create a native/software thread on MB func = lookup_handle(&global_thread_table, func_id, TYPE_HOST); if (func == (void*)TABLE_INIT) { ret = TABLE_INIT; } else { // Ignore passed in attribute #ifdef DEBUG_DISPATCH printf("Creating Native Thread!\n"); #endif ret = hthread_create(tid, NULL, func, arg); } } // --------------------------------------------- // Otherwise create a hetero thread // --------------------------------------------- else { // Create a heterogeneous thread func = lookup_handle(&global_thread_table, func_id, slave_table[found].processor_type); if (func == (void*)TABLE_INIT) { ret = TABLE_INIT; } else { // Create thread hetero using V-HWTI[found] #ifdef DEBUG_DISPATCH printf("Creating Hetero Thread (CPU#%d)!\n",found); #endif hthread_attr_init(attr); hthread_attr_sethardware( attr, (void*)hwti_array[found] ); ret = hthread_create(tid, attr, func, arg); } } return ret; }
//--------------------------------------------------------------------------------------------// // Thread Create // Description: This function encapsulates all of the thread create functions (i.e. dynamic // create smart, microblaze create, hthread create, etc. // Arguments: // 1) Thread ID - Thread ID returned by the OS. Assigned during hthread_setup(). // 2) Thread Attribute - Attribute structure for the thread // 3) Function ID - The function number the thread will execute // 4) Argument - Argument to be passed to the function // 5) Type - The type of thread you want to be created. (i.e. Software, dynamic_hw, etc. // 6) Dma Length - the length of the parameter, arg. Passing a zero indicates no DMA'ing // // NOTE: DMA LENGTH IS NOT USED AT THIS TIME. //--------------------------------------------------------------------------------------------// Huint thread_create( hthread_t * tid, hthread_attr_t * attr, Huint func_id, void * arg, Huint type, Huint dma_length) { Huint ret; void * func; assert(attr!=NULL); // Efficient NULL pointer check // --------------------------------------------- // Make sure tables are initialized // --------------------------------------------- if (!table_initialized_flag) { // Assert flag table_initialized_flag = 1; // Init thread table init_thread_table(&global_thread_table); // Load entries with app-specific data load_my_table(); // Init function-to-accelerator table init_func_2_acc_table(); // Initialize mutexes, ICAP, and bitfiles // for Partial Reconfiguration. init_PR_data(); } // Check if we have not passed our threshold // TODO: Remove? //while( (NUM_AVAILABLE_HETERO_CPUS - get_num_free_slaves() + thread_counter) > (NUM_AVAILABLE_HETERO_CPUS + SW_THREAD_COUNT)) //hthread_yield(); //-------------------------------- // Is this a software thread? //-------------------------------- if (type == SOFTWARE_THREAD) { // Create a native/software thread on the host processor // Make sure user didn't call hthread_attr_sethardware() if (attr->hardware) { #ifdef DEBUG_DISPATCH printf("Your thread attribute is set for hardware but"); printf(" you are creating a software thread!\n"); #endif ret = FAILURE; } else ret = software_create(tid, attr, func_id, arg); //------------------------------------------------------------ // For hardware threads, should we dynamically schedule them? //------------------------------------------------------------ } else if(type == DYNAMIC_HW) { // Identify a slave processor the best fits our needs (i.e., is // available, is available and has an accelerator we want, etc.) Hint slave_num = find_best_match(func_id); // If we did not find any processors available. if (slave_num == MAGIC_NUMBER) { #ifdef DEBUG_DISPATCH printf("No Free Slaves:Creating software thread\n"); #endif ret = software_create(tid, NULL, func_id, arg); } else { // Grab the function handle according to the processor type. func = lookup_handle(&global_thread_table, func_id, slave_table[slave_num].processor_type); #ifdef DEBUG_DISPATCH printf("Creating Hetero Thread (CPU#%d)!\n",slave_num); #endif // -------------------------------------------------------------- // // Write extra parameters for PR functionality // // -------------------------------------------------------------- // // Write pointer for first_used_accelerator so slave can update the table. // This assumes that for a particular function (id), slaves will also have // the same first accelerator used. _hwti_set_first_accelerator_ptr( (Huint) hwti_array[slave_num], (Huint) &func_2_acc_table[func_id]); // -------------------------------------------------------------- // // Create the hardware thread using better target // // -------------------------------------------------------------- // hthread_attr_sethardware( attr, (void*)hwti_array[slave_num] ); ret = hthread_create(tid, attr, func, arg); } //------------------------------------------------------- // For hardware threads, we will statically schedule them //------------------------------------------------------- } else { // Determine the exact slave processor number Huint slave_num = type + STATIC_HW_OFFSET; // Check if valid slave number. Since 'slave_num' is // and unsigned int, it cannot be negative, right? if (slave_num >= NUM_AVAILABLE_HETERO_CPUS) { #ifdef DEBUG_DISPATCH printf("Invalid slave number: %d\n", slave_num); printf("Creating a software thread instead\n"); #endif ret = software_create(tid, NULL, func_id, arg); } // If that slave number exists, is it Free? if (_hwti_get_utilized_flag(hwti_array[slave_num]) == FLAG_HWTI_UTILIZED) { #ifdef DEBUG_DISPATCH printf("Slave number %d is busy! Creating software thread\n", slave_num); #endif ret = software_create(tid, NULL, func_id, arg); } else { #ifdef DEBUG_DISPATCH printf("Creating Hetero Thread (CPU#%d)!\n",slave_num); #endif // -------------------------------------------------------------- // // Write extra parameters for PR functionality // // -------------------------------------------------------------- // // Write pointer for first_used_accelerator so slave can update the table. // This assumes that for a particular function (id), slaves will also have // the same first accelerator used. _hwti_set_first_accelerator_ptr( (Huint) hwti_array[slave_num], (Huint) &func_2_acc_table[func_id]); // Grab the function according to the processor type func = lookup_handle(&global_thread_table, func_id, slave_table[slave_num].processor_type); // -------------------------------------------------------------- // // Create the hardware thread using slave num // // -------------------------------------------------------------- // hthread_attr_sethardware( attr, (void*)hwti_array[slave_num] ); ret = hthread_create(tid, attr, func, arg); } } return ret; }