nc_test_slave.c
来自「eCos操作系统源码」· C语言 代码 · 共 794 行 · 第 1/2 页
C
794 行
close(test_chan);}//// Protocol driver for testing slave.//// This function is the main routine running here, handling requests sent from// the master and providing various responses.//static voidnc_slave(test_param_t param){ int s, masterlen; struct sockaddr_in my_addr, master; struct nc_request req; struct nc_reply reply; int done = false; test_printf("Start test for eth%d\n", param); s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { pexit("datagram socket"); } memset((char *) &my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_len = sizeof(my_addr); my_addr.sin_addr.s_addr = htonl(INADDR_ANY); my_addr.sin_port = htons(NC_SLAVE_PORT); if (bind(s, (struct sockaddr *) &my_addr, sizeof(my_addr)) < 0) { pexit("bind"); } while (!done) { masterlen = sizeof(master); if (recvfrom(s, &req, sizeof(req), 0, (struct sockaddr *)&master, &masterlen) < 0) { pexit("recvfrom"); }#if 0 test_printf("Request %d from %s:%d\n", ntohl(req.type), inet_ntoa(master.sin_addr), ntohs(master.sin_port));#endif reply.response = htonl(NC_REPLY_ACK); reply.seq = req.seq; switch (ntohl(req.type)) { case NC_REQUEST_DISCONNECT: done = true; break; case NC_REQUEST_UDP_SEND: test_printf("UDP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_UDP_RECV: test_printf("UDP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_UDP_ECHO: test_printf("UDP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_SEND: test_printf("TCP send - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_RECV: test_printf("TCP recv - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_TCP_ECHO: test_printf("TCP echo - %d buffers, %d bytes\n", ntohl(req.nbufs), ntohl(req.buflen)); break; case NC_REQUEST_SET_LOAD: start_load(ntohl(req.nbufs)); break; case NC_REQUEST_START_IDLE: test_printf("Start IDLE thread\n"); idle_thread_count = 0; idle_thread_start_time = cyg_current_time(); cyg_semaphore_post(&idle_thread_sem); break; case NC_REQUEST_STOP_IDLE: cyg_semaphore_wait(&idle_thread_sem); idle_thread_stop_time = cyg_current_time(); test_printf("Stop IDLE thread\n"); reply.misc.idle_results.elapsed_time = htonl(idle_thread_stop_time - idle_thread_start_time); reply.misc.idle_results.count[0] = htonl(idle_thread_count >> 32); reply.misc.idle_results.count[1] = htonl((long)idle_thread_count); break; default: test_printf("Unrecognized request: %d\n", ntohl(req.type)); reply.response = htonl(NC_REPLY_NAK); reply.reason = htonl(NC_REPLY_NAK_UNKNOWN_REQUEST); break; } if (sendto(s, &reply, sizeof(reply), 0, (struct sockaddr *)&master, masterlen) < 0) { pexit("sendto"); } if (reply.response == ntohl(NC_REPLY_NAK)) { continue; } switch (ntohl(req.type)) { case NC_REQUEST_UDP_SEND: case NC_REQUEST_UDP_RECV: case NC_REQUEST_UDP_ECHO: do_udp_test(s, &req, &master); break; case NC_REQUEST_TCP_SEND: case NC_REQUEST_TCP_RECV: case NC_REQUEST_TCP_ECHO: do_tcp_test(s, &req, &master); break; case NC_REQUEST_START_IDLE: case NC_REQUEST_STOP_IDLE: case NC_REQUEST_SET_LOAD: default: break; } } close(s);}voidnet_test(test_param_t param){// int i; if (param == 0) { test_printf("Start Network Characterization - SLAVE\n"); calibrate_load(DESIRED_BACKGROUND_LOAD); } nc_slave(param);#ifdef CYGDBG_NET_TIMING_STATS show_net_times();#endif#if LWIP_STATS_DISPLAY stats_display();#endif cyg_test_exit();}//// This function is called to calibrate the "background load" which can be// applied during testing. It will be called before any commands from the// host are managed.//static voidcalibrate_load(int desired_load){ long long no_load_idle, load_idle; int percent_load; int high, low; // Set limits high = MAX_LOAD_THREAD_LEVEL; low = MIN_LOAD_THREAD_LEVEL; test_printf("Start Network Characterization - SLAVE\n"); // Compute the "no load" idle value idle_thread_count = 0; cyg_semaphore_post(&idle_thread_sem); // Start idle thread test_printf("Start Network Characterization - SLAVE\n"); cyg_thread_delay(1*100); // Pause for one second test_printf("Start Network Characterization - SLAVE\n"); cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread test_printf("Start Network Characterization - SLAVE\n"); no_load_idle = idle_thread_count; diag_printf("No load = %d\n", (int)idle_thread_count); // First ensure that the HIGH level is indeed higher while (true) { load_thread_level = high; start_load(desired_load); // Start up a given load idle_thread_count = 0; cyg_semaphore_post(&idle_thread_sem); // Start idle thread cyg_thread_delay(1*100); // Pause for one second cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread load_idle = idle_thread_count; start_load(0); // Shut down background load percent_load = 100 - ((load_idle * 100) / no_load_idle); diag_printf("High Load[%d] = %d => %d%%\n", load_thread_level, (int)idle_thread_count, percent_load); if ( percent_load > desired_load ) break; // HIGH level is indeed higher low = load_thread_level; // known to be lower high *= 2; // else double it and try again } // Now chop down to the level required while (true) { load_thread_level = (high + low) / 2; start_load(desired_load); // Start up a given load idle_thread_count = 0; cyg_semaphore_post(&idle_thread_sem); // Start idle thread cyg_thread_delay(1*100); // Pause for one second cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread load_idle = idle_thread_count; start_load(0); // Shut down background load percent_load = 100 - ((load_idle * 100) / no_load_idle); diag_printf("Load[%d] = %d => %d%%\n", load_thread_level, (int)idle_thread_count, percent_load); if (((high-low) <= 1) || (abs(desired_load-percent_load) <= 2)) break; if (percent_load < desired_load) { low = load_thread_level; } else { high = load_thread_level; } } // Now we are within a few percent of the target; scale the load // factor to get a better fit, and test it, print the answer. load_thread_level *= desired_load; load_thread_level /= percent_load; start_load(desired_load); // Start up a given load idle_thread_count = 0; cyg_semaphore_post(&idle_thread_sem); // Start idle thread cyg_thread_delay(1*100); // Pause for one second cyg_semaphore_wait(&idle_thread_sem); // Stop idle thread load_idle = idle_thread_count; start_load(0); // Shut down background load percent_load = 100 - ((load_idle * 100) / no_load_idle); diag_printf("Final load[%d] = %d => %d%%\n", load_thread_level, (int)idle_thread_count, percent_load);// no_load_idle_count_1_second = no_load_idle;}//// This function is called to set up a load level of 'load' percent (given// as a whole number, e.g. start_load(20) would mean initiate a background// load of 20%, leaving the cpu 80% idle).//static voidstart_load(int load){ static int prev_load = 0; int i; test_printf("Set background load = %d%%\n", load); if (load == 0) { if (prev_load == 0) return; // Nothing out there to stop for (i = 0; i < prev_load/10; i++) { cyg_semaphore_wait(&load_thread_sem[i]); } prev_load = 0; } else { for (i = 0; i < load/10; i++) { cyg_semaphore_post(&load_thread_sem[i]); } prev_load = load; }}//// These thread(s) do some amount of "background" computing. This is used// to simulate a given load level. They need to be run at a higher priority // than the network code itself.//// Like the "idle" thread, they run as long as their "switch" (aka semaphore)// is enabled.//voidnet_load(cyg_addrword_t who){ int i; while (true) { cyg_semaphore_wait(&load_thread_sem[who]); for (i = 0; i < load_thread_level; i++) { do_some_random_computation(i); } cyg_thread_delay(1); // Wait until the next 'tick' cyg_semaphore_post(&load_thread_sem[who]); }}//// Some arbitrary computation, designed to use up the CPU and cause associated// cache "thrash" behaviour - part of background load modelling.//static voiddo_some_random_computation(int p){ // Just something that might be "hard" volatile double x; x = ((p * 10) * 3.14159) / 180.0; // radians}//// This thread does nothing but count. It will be allowed to count// as long as the semaphore is "free". //voidnet_idle(cyg_addrword_t param){ while (true) { cyg_semaphore_wait(&idle_thread_sem); idle_thread_count++; cyg_semaphore_post(&idle_thread_sem); }}#if 0voidcyg_start(void *n){ int i; // Create processing threads for (i = 0; i < CYGHWR_NET_DRIVERS; i++) { cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority net_test, // entry i, // entry parameter "Network test", // Name &main_thread_stack[i][0], // Stack STACK_SIZE, // Size &main_thread_handle[i], // Handle &main_thread_data[i] // Thread data structure ); } cyg_thread_resume(main_thread_handle[0]); // Start first one // Create the idle thread environment cyg_semaphore_init(&idle_thread_sem, 0); cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority net_idle, // entry 0, // entry parameter "Network idle", // Name &idle_thread_stack[0], // Stack STACK_SIZE, // Size &idle_thread_handle, // Handle &idle_thread_data // Thread data structure ); cyg_thread_resume(idle_thread_handle); // Start it // Create the load threads and their environment(s) for (i = 0; i < NUM_LOAD_THREADS; i++) { cyg_semaphore_init(&load_thread_sem[i], 0); cyg_thread_create(LOAD_THREAD_PRIORITY, // Priority net_load, // entry i, // entry parameter "Background load", // Name &load_thread_stack[i][0], // Stack STACK_SIZE, // Size &load_thread_handle[i], // Handle &load_thread_data[i] // Thread data structure ); cyg_thread_resume(load_thread_handle[i]); // Start it } cyg_scheduler_start();}#endifvoidtmain(cyg_addrword_t p){ lwip_init(); sys_thread_new(net_test, 0, MAIN_THREAD_PRIORITY);}static char stack[STACK_SIZE];static cyg_thread thread_data;static cyg_handle_t thread_handle;voidcyg_user_start(void){ int i; // Create the idle thread environment cyg_semaphore_init(&idle_thread_sem, 0); cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority net_idle, // entry 0, // entry parameter "Network idle", // Name &idle_thread_stack[0], // Stack STACK_SIZE, // Size &idle_thread_handle, // Handle &idle_thread_data // Thread data structure ); cyg_thread_resume(idle_thread_handle); // Start it // Create the load threads and their environment(s) for (i = 0; i < NUM_LOAD_THREADS; i++) { cyg_semaphore_init(&load_thread_sem[i], 0); cyg_thread_create(LOAD_THREAD_PRIORITY, // Priority net_load, // entry i, // entry parameter "Background load", // Name &load_thread_stack[i][0], // Stack STACK_SIZE, // Size &load_thread_handle[i], // Handle &load_thread_data[i] // Thread data structure ); cyg_thread_resume(load_thread_handle[i]); // Start it } // Create a main thread, so we can run the scheduler and have time 'pass' cyg_thread_create(10, // Priority - just a number tmain, // entry 0, // entry parameter "socket echo test", // Name &stack[0], // Stack STACK_SIZE, // Size &thread_handle, // Handle &thread_data // Thread data structure ); cyg_thread_resume(thread_handle); // Start it}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?