static void build_histogram_thread_create(void) { int error; pthread_attr_init(&build_histogram_attr); pthread_attr_setstacksize(&build_histogram_attr, STACK_SIZE); #ifdef HW_HISTOGRAM printf("building histogram in hardware...\n"); rthread_attr_init(&build_histogram_rattr); rthread_attr_setslotnum(&build_histogram_rattr, 0); rthread_attr_setresources(&build_histogram_rattr, build_histogram_resources, 2); error = rthread_create( &build_histogram_thread, &build_histogram_attr, &build_histogram_rattr, NULL); #else printf("building histogram in software...\n"); error = pthread_create( &build_histogram_thread, &build_histogram_attr, build_histogram_entry, NULL); #endif if(error){ perror("pthread_create: build_histogram"); exit(1); } }
static inline int posix_hwt_create(int nslot, void * init_data, reconos_res_t * res, int nres) { rthread_attr_init(&rattr[nslot]); rthread_attr_setslotnum(&rattr[nslot], nslot); rthread_attr_setresources(&rattr[nslot], res, nres); //pthread_attr_init(&posix_attr); return rthread_create(&posix_thread[nslot], &rattr[nslot], init_data); }
/** creates sample HW threads (and deletes 'old' hw threads) (static) @param number_of_threads: number of threads for sampling step @param reconos_slots: pointer to array including the slot numbers, where the sampling hw threads are connected with @param parameter: pointer to a array filled with parameter (size <= 128 byte) @param number_of_parameter: number of parameter in parameter array */ void set_sample_hw_static (unsigned int number_of_threads, unsigned int * reconos_slots, int * parameter, unsigned int number_of_parameter){ int i; // terminate old sw threads if needed if (hw_number_of_threads_s > 0) { sample_hw_delete_static(); for (i=0; i<hw_number_of_threads_s;i++){ free(hw_thread_s_stack[i]); } free(hw_thread_s); free(hw_thread_s_stack); free(hw_thread_s_handle); free(res_s); free(hw_thread_s_attr); free(information_s); } // set number of hw threads hw_number_of_threads_s = number_of_threads; if (number_of_threads < 1) return; // set information information_s = (information_struct_s *) malloc (sizeof(information_struct_s)); // set information information_s[0].particles = particles; information_s[0].number_of_particles = N; information_s[0].particle_size = sizeof(particle); information_s[0].max_number_of_particles = 8096 / sizeof(particle); information_s[0].block_size = block_size; // parameter information_s[0].parameter = parameter; information_s[0].number_of_parameter = number_of_parameter; //diag_printf("\ninformation address (sampling): %d", (int)information_s); //diag_printf("\nparticle address: %d", (int)particles); // create hw threads variables hw_thread_s = (cyg_thread *) malloc (number_of_threads * sizeof(cyg_thread)); // create hw thread stacks hw_thread_s_stack = (char **) malloc (number_of_threads * sizeof (char *)); for (i=0; i<number_of_threads; i++){ hw_thread_s_stack[i] = (char *) malloc (STACK_SIZE * sizeof(char)); } // create hw handles hw_thread_s_handle = (cyg_handle_t *) malloc (number_of_threads * sizeof(cyg_handle_t)); // attributes for hw threads hw_thread_s_attr = malloc (number_of_threads * sizeof(rthread_attr_t)); // set ressources res_s = (reconos_res_t *) malloc (4 * sizeof(reconos_res_t)); res_s[0].ptr = mb_sampling_handle; res_s[0].type = CYG_MBOX_HANDLE_T ; res_s[1].ptr = mb_sampling_done_handle; res_s[1].type = CYG_MBOX_HANDLE_T ; res_s[2].ptr = hw_mb_sampling_measurement_handle; res_s[2].type = CYG_MBOX_HANDLE_T ; res_s[3].ptr = hw_mb_sampling_exit_handle; res_s[3].type = CYG_MBOX_HANDLE_T ; // create and resume hw sampling threads in eCos for (i = 0; i < number_of_threads; i++){ // set attributes rthread_attr_init(&hw_thread_s_attr[i]); // set slot number rthread_attr_setslotnum(&hw_thread_s_attr[i], reconos_slots[i]); // add ressources rthread_attr_setresources(&hw_thread_s_attr[i], res_s, 3); //diag_printf("\n--> hw sampling (%d, slot %d) dcr address: %d", // i, reconos_slots[i], hw_thread_s_attr[i].dcr_base_addr); // create hw sampling thread reconos_hwthread_create( (cyg_addrword_t) PRIO_HW, // priority &hw_thread_s_attr[i], // attributes (cyg_addrword_t) &information_s[0], // entry data "HW_SAMPLING", // thread name hw_thread_s_stack[i], // stack STACK_SIZE, // stack size &hw_thread_s_handle[i], // thread handle &hw_thread_s[i] // thread object ); // resume threads cyg_thread_resume(hw_thread_s_handle[i]); } }
/** creates observation HW threads @param number_of_threads: number of threads for observation step @param reconos_slots: pointer to array including the slot numbers, where the observation hw threads are connected to @param parameter: pointer to a array filled with parameter (size <= 128 byte) @param number_of_parameter: number of parameter in parameter array */ void set_observe_hw (unsigned int number_of_threads, unsigned int * reconos_slots, int * parameter, unsigned int number_of_parameter){ int i; // terminate old sw threads if needed if (hw_number_of_threads_o > 0){ observation_hw_delete(); // free all variables for (i=0; i<hw_number_of_threads_o;i++){ free(hw_thread_o_stack[i]); } free(hw_thread_o); free(hw_thread_o_stack); free(hw_thread_o_handle); free(res_o); free(hw_thread_o_attr); free(information_o); } // set number of hw threads hw_number_of_threads_o = number_of_threads; if (number_of_threads < 1) return; // set information information_o = (information_struct_o *) malloc (sizeof(information_struct_o)); // set information particles information_o[0].particles = particles; information_o[0].number_of_particles = N; information_o[0].particle_size = sizeof(particle); information_o[0].block_size = block_size; information_o[0].observation_size = sizeof(observation); information_o[0].observations = observations; information_o[0].input = &observations_input; information_o[0].parameter_size = (int) number_of_parameter; information_o[0].parameter = parameter; // create hw threads variables hw_thread_o = (cyg_thread *) malloc (number_of_threads * sizeof(cyg_thread)); // create hw thread stacks hw_thread_o_stack = (char **) malloc (number_of_threads * sizeof (char *)); for (i=0; i<number_of_threads; i++){ hw_thread_o_stack[i] = (char *) malloc (STACK_SIZE * sizeof(char)); } // create hw handles hw_thread_o_handle = (cyg_handle_t *) malloc (number_of_threads * sizeof(cyg_handle_t)); // set ressources res_o = (reconos_res_t *) malloc (3 * sizeof(reconos_res_t)); res_o[0].ptr = mb_sampling_done_handle; res_o[0].type = CYG_MBOX_HANDLE_T ; res_o[1].ptr = mb_importance_handle; res_o[1].type = CYG_MBOX_HANDLE_T ; res_o[2].ptr = hw_mb_observation_measurement_handle; res_o[2].type = CYG_MBOX_HANDLE_T ; // attributes for hw threads hw_thread_o_attr = malloc (number_of_threads * sizeof(rthread_attr_t)); // create and resume hw observation threads in eCos for (i = 0; i < number_of_threads; i++){ // set attributes rthread_attr_init(&hw_thread_o_attr[i]); // set slot number rthread_attr_setslotnum(&hw_thread_o_attr[i], reconos_slots[i]); // add ressources rthread_attr_setresources(&hw_thread_o_attr[i], res_o, 3); //diag_printf("\n--> hw observation (%d, slot %d) dcr address: %d", i, reconos_slots[i], hw_thread_o_attr[i].dcr_base_addr); // create hw observation thread reconos_hwthread_create( (cyg_addrword_t) PRIO_HW, // priority &hw_thread_o_attr[i], // attributes (cyg_addrword_t) &information_o[0] , // entry data "HW_OBSERVATION", // thread name hw_thread_o_stack[i], // stack STACK_SIZE, // stack size &hw_thread_o_handle[i], // thread handle &hw_thread_o[i] // thread object ); // resume threads cyg_thread_resume(hw_thread_o_handle[i]); } }
int main( int argc, char *argv[] ) { unsigned int i, start_count = 0, done_count = 0; timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge = 0, t_check = 0; unsigned int *addr; unsigned int dummy; int retval; printf( "-------------------------------------------------------\n" "ReconOS hardware multithreading case study (sort)\n" "(c) Computer Engineering Group, University of Paderborn\n\n" "eCos/POSIX, multi-threaded hardware version (" __FILE__ ")\n" "Compiled on " __DATE__ ", " __TIME__ ".\n" "-------------------------------------------------------\n\n" ); #ifdef USE_CACHE printf( "enabling data cache for external ram\n" ); XCache_EnableDCache( 0x80000000 ); #else printf( "data cache disabled\n" ); XCache_DisableDCache( ); #endif data = buf_a; //---------------------------------- //-- GENERATE DATA //---------------------------------- printf( "Generating data..." ); t_start = gettime( ); generate_data( data, SIZE ); t_stop = gettime( ); t_gen = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); #ifdef USE_CACHE // flush cache contents - the hardware can only read from main memory // TODO: storing could be more efficient printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- SORT DATA //---------------------------------- // create mail boxes for 'start' and 'complete' messages mb_start_attr.mq_flags = mb_done_attr.mq_flags = 0; mb_start_attr.mq_maxmsg = mb_done_attr.mq_maxmsg = 10; mb_start_attr.mq_msgsize = mb_done_attr.mq_msgsize = 4; mb_start_attr.mq_curmsgs = mb_done_attr.mq_curmsgs = 0; // unlink mailboxes, if they exist retval = mq_unlink("/mb_start"); if (retval != 0 && errno != ENOENT) { // we don't care if it doesn't exist diag_printf("unable to unlink mb_start"); } retval = mq_unlink("/mb_done"); if (retval != 0 && errno != ENOENT) { // we don't care if it doesn't exist diag_printf("unable to unlink mb_done"); } // open/create mailboxes mb_start = mq_open("/mb_start", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, &mb_start_attr); if (mb_start == (mqd_t)-1) { diag_printf("unable to create mb_start"); } mb_done = mq_open("/mb_done", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, &mb_done_attr); if (mb_done == (mqd_t)-1) { diag_printf("unable to create mb_done"); } // create sorting sowftware threads for ( i = 0; i < MT_HW_NUM_SW_THREADS; i++ ) { pthread_attr_init(&thread_sorter_attr[i]); pthread_create(&thread_sorter[i], &thread_sorter_attr[i], sort8k_entry_posix, (void*)i); } // create sorting hardware thread pthread_attr_init(&hwthread_sorter_attr); pthread_attr_setstacksize(&hwthread_sorter_attr, STACK_SIZE); rthread_attr_init(&hwthread_sorter_hwattr); rthread_attr_setslotnum(&hwthread_sorter_hwattr, 0); rthread_attr_setresources(&hwthread_sorter_hwattr, hwthread_sorter_resources, 2); rthread_create(&hwthread_sorter, &hwthread_sorter_attr, &hwthread_sorter_hwattr, (void*)0); printf( "Sorting data..." ); i = 0; t_start = gettime( ); // put 9 messages into mb_start while ( start_count < 9 ) { addr = &data[i]; if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) { start_count++; i += N; } else { perror("while sending to mq_send"); break; } } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); while ( done_count < SIZE / N ) { t_start = gettime( ); // if we have something to distribute, // put one into the start mailbox if ( start_count < SIZE / N ) { addr = &data[i]; if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) { start_count++; i += N; } else { perror("while sending to mq_send"); break; } } // see whether anybody's done if ( mq_receive( mb_done, (void*)&dummy, sizeof(dummy), 0 ) == sizeof(dummy) ) { done_count++; } else { perror( "while receiving from mq_done" ); break; } t_stop = gettime( ); t_sort += calc_timediff_ms( t_start, t_stop ); } printf( "done\n" ); #ifdef USE_CACHE // flush cache contents // TODO: invalidating would suffice printf( "Flushing cache..." ); XCache_EnableDCache( 0x80000000 ); printf( "done\n" ); #endif //---------------------------------- //-- MERGE DATA //---------------------------------- printf( "Merging data..." ); t_start = gettime( ); data = recursive_merge( data, buf_b, SIZE, N, simple_merge ); t_stop = gettime( ); t_merge = calc_timediff_ms( t_start, t_stop ); printf( "done\n" ); //---------------------------------- //-- CHECK DATA //---------------------------------- printf( "Checking sorted data..." ); t_start = gettime( ); if ( check_data( data, SIZE ) != 0 ) printf( "CHECK FAILED!\n" ); else printf( "check successful.\n" ); t_stop = gettime( ); t_check = calc_timediff_ms( t_start, t_stop ); printf( "\nRunning times (size: %d words):\n" "\tGenerate data: %d ms\n" "\tSort data : %d ms\n" "\tMerge data : %d ms\n" "\tCheck data : %d ms\n" "\nTotal computation time (sort & merge): %d ms\n", SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge ); return 0; }
int main() { // send message queue char *send_buf; char *recv_buf; size_t len = 4; unsigned int prio = 1; int n = 0; struct mq_attr hw_sw_attr; struct mq_attr sw_hw_attr; mqd_t mqd_hw_sw; mqd_t mqd_sw_hw; hw_sw_attr.mq_flags = 0; hw_sw_attr.mq_maxmsg = 10; hw_sw_attr.mq_msgsize = len; hw_sw_attr.mq_curmsgs = 0; sw_hw_attr.mq_flags = 0; sw_hw_attr.mq_maxmsg = 10; sw_hw_attr.mq_msgsize = len; sw_hw_attr.mq_curmsgs = 0; if ((mqd_hw_sw = mq_open("/hw_sw", O_RDWR|O_CREAT, 777, &hw_sw_attr)) < 0) perror("open hw_sw"); if ((mqd_sw_hw = mq_open("/sw_hw", O_RDWR|O_CREAT, 777, &sw_hw_attr)) < 0) perror("open sw_hw"); send_buf = malloc(1024); recv_buf = malloc(1024); memset(send_buf, 0, 1024); memset(recv_buf, 0, 1024); rthread_attr_t rcv_attr; rthread_attr_init(&rcv_attr); reconos_res_t res[2] = {{&mqd_sw_hw,PTHREAD_MQD_T }, {&mqd_hw_sw,PTHREAD_MQD_T }}; rthread_attr_init(&rcv_attr); rthread_attr_setslotnum(&rcv_attr, 0); rthread_attr_setresources(&rcv_attr, res, 2); rthread_t mythread; rthread_create( &mythread, &rcv_attr, NULL); if (mq_send(mqd_sw_hw, &send_buf, len, prio) < 0) perror("mq_send"); fprintf(stderr, "--------------->message sent, ptr = %i\n", send_buf); if (mq_send(mqd_sw_hw, &recv_buf, len, prio) < 0) perror("mq_send"); fprintf(stderr, "--------------->message sent, ptr = %i\n", recv_buf); int msglen = 12; memcpy(send_buf, "hello world", msglen); if (mq_send(mqd_sw_hw, &msglen, len, prio) < 0) perror("mq_send"); fprintf(stderr, "--------------->message sent, ptr = %i\n", recv_buf); if ((n = mq_receive(mqd_hw_sw, &msglen, len, &prio)) < 0) perror("my_receive"); fprintf(stderr, "--------------->message received \n"); fprintf(stderr, "------------------> new message is %d bytes long \n", msglen); fprintf(stderr, "memory at location \"recv_buf\" %s\n", recv_buf); fprintf(stderr, "memory at location \"recv_buf + 16\" %s\n", recv_buf + 16); sleep(10); return 1; }
/// /// Application entry function. Sets up data strctures and threads. /// void cyg_user_start() { struct udp_connection *con; // cyg_sem_t *sem_array[8]; reconos_res_t sem_array_laplace[8]; reconos_res_t sem_array_display[8]; int i; #if defined(USE_DCACHE) // enable caches for DRAM XCache_EnableDCache(0x80000000); #endif diag_printf("Hello embedded world!\n" "This is " __FILE__ " (ReconOS), built " __DATE__ ", " __TIME__ "\n"); // initialize hardware diag_printf("Initializing hardware...\n"); init(); // initialize image buffers diag_printf("Initializing image buffers...\n"); for (i = 0; i < 2; i++) { byte_buffer_init(&input_buffer[i], WIDTH, HEIGHT); // one image + four lines (???) byte_buffer_fill(&input_buffer[i], 0); byte_buffer_init(&laplace_buffer[i], WIDTH, HEIGHT); // one image byte_buffer_fill(&laplace_buffer[i], 0); } // initialize fake output image buffer output_buffer[0].width = WIDTH; // irrelevant output_buffer[0].height = HEIGHT; // irrelevant output_buffer[0].data = fb_info.fb; // this points to the VGA frame buffer // NOTE: the semaphores of this buffer are not used and therefore not initialized diag_printf ("Buffer addresses: input: 0x%08X, laplace: 0x%08X, output: 0x%08X\n", input_buffer[0].data, laplace_buffer[0].data, output_buffer[0].data); // set up UDP connection diag_printf("Setting up UDP networking...\n"); con = udp_connection_create(inet_addr("192.168.1.2")); // initialize thread info structures diag_printf("Initializing thread info structures...\n"); buffer_thread_info_init(&input_thread_info, 2, NULL, input_buffer);/*, NULL, &laplace_rdy, NULL, &input_new);*/ buffer_thread_info_init(&laplace_thread_info, 2, input_buffer, laplace_buffer);/*, &laplace_rdy, &display_rdy, &input_new, &laplace_new);*/ buffer_thread_info_init(&display_thread_info, 2, laplace_buffer, output_buffer);/*, &display_rdy, NULL, &laplace_new, NULL);*/ // initialize semaphores /* diag_printf("Initializing semaphores...\n"); cyg_semaphore_init(&input_new, 0); cyg_semaphore_init(&laplace_rdy, 1); cyg_semaphore_init(&laplace_new, 0); cyg_semaphore_init(&display_rdy, 1);*/ // pass connection info to input thread input_thread_info.data = (cyg_addrword_t) con; diag_printf("Creating threads..."); // create input thread diag_printf("input..."); cyg_thread_create(16, // scheduling info (eg pri) entry_buffer_recv, // entry point function (cyg_addrword_t) & input_thread_info, // entry data "INPUT THREAD", // optional thread name input_stack, // stack base MYTHREAD_STACK_SIZE, // stack size, &input_handle, // returned thread handle &input_thread // put thread here ); #if !defined(USE_HW_LAPLACE) // create laplace software thread diag_printf("laplace_sw..."); cyg_thread_create(16, // scheduling info (eg pri) entry_buffer_laplace, // entry point function (cyg_addrword_t) & laplace_thread_info, // entry data "LAPLACE THREAD (SW)", // optional thread name laplace_stack, // stack base MYTHREAD_STACK_SIZE, // stack size, &laplace_handle, // returned thread handle &laplace_thread // put thread here ); #else // create laplace hardware thread diag_printf("laplace_hw..."); fill_sem_array(sem_array_laplace, &laplace_thread_info); rthread_attr_init(&laplace_hwthread_attr); rthread_attr_setslotnum(&laplace_hwthread_attr, 0); rthread_attr_setresources(&laplace_hwthread_attr, sem_array_laplace, 8); reconos_hwthread_create(16, // scheduling info (eg pri) &laplace_hwthread_attr, // hw thread attributes shm_init(&laplace_thread_info), // init data "LAPLACE_THREAD (HW)", // optional thread name laplace_stack, // stack base MYTHREAD_STACK_SIZE, // stack size, &laplace_handle, // returned thread handle &laplace_hwthread); // put thread here #endif #if !defined(USE_HW_DISPLAY) // create display software thread diag_printf("display_sw..."); cyg_thread_create(16, // scheduling info (eg pri) entry_buffer_display, // entry point function (cyg_addrword_t) & display_thread_info, // entry data "DISPLAY THREAD", // optional thread name display_stack, // stack base MYTHREAD_STACK_SIZE, // stack size, &display_handle, // returned thread handle &display_thread // put thread here ); #else // create display hardware thread diag_printf("display_hw..."); fill_sem_array(sem_array_display, &display_thread_info); rthread_attr_init(&display_hwthread_attr); rthread_attr_setslotnum(&display_hwthread_attr, 0); rthread_attr_setresources(&display_hwthread_attr, sem_array_display, 8); reconos_hwthread_create(16, // scheduling info (eg pri) &display_hwthread_attr, // hw thread attributes shm_init(&display_thread_info), // init data "DISPLAY_THREAD (HW)", // optional thread name display_stack, // stack base MYTHREAD_STACK_SIZE, // stack size, &display_handle, // returned thread handle &display_hwthread, // put thread here (void *) XPAR_PLB_RECONOS_SLOT_1_BASEADDR, XPAR_OPB_INTC_0_PLB_RECONOS_SLOT_1_INTERRUPT_INTR + 1, // associated interrupt vector shm_init(&display_thread_info), SHM_SIZE, sem_array, 8); #endif diag_printf("\nStarting threads...\n"); cyg_thread_resume(input_handle); cyg_thread_resume(laplace_handle); cyg_thread_resume(display_handle); diag_printf("end of main()\n"); }