tcp_echo.c
来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 596 行 · 第 1/2 页
C
596 行
//==========================================================================//// tests/tcp_echo.c//// Simple TCP throughput test - echo component////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2000-01-10// Purpose: // Description: This is the middle part of a three part test. The idea is// to test the throughput of box in a configuration like this://// +------+ port +----+ port +----+// |SOURCE|=========>|ECHO|============>|SINK|// +------+ 9990 +----+ 9991 +----+// ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/system.h>#include <pkgconf/net.h>#ifdef CYGBLD_DEVS_ETH_DEVICE_H // Get the device config if it exists#include CYGBLD_DEVS_ETH_DEVICE_H // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME#endif#ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test?# ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists# include CYGTST_DEVS_ETH_TEST_NET_REALTIME# endif#endif// Fill in the blanks if necessary#ifndef TNR_OFF# define TNR_OFF()#endif#ifndef TNR_ON# define TNR_ON()#endif#ifndef TNR_INIT# define TNR_INIT()#endif#ifndef TNR_PRINT_ACTIVITY# define TNR_PRINT_ACTIVITY()#endif// Network throughput test code#include <network.h>static __inline__ unsigned intmax(unsigned int m, unsigned int n){ return m > n ? m : n;}#define SOURCE_PORT 9990#define SINK_PORT 9991#define MAX_BUF 8192static unsigned char data_buf[MAX_BUF];struct test_params { long nbufs; long bufsize; long load;};struct test_status { long ok;};#ifndef CYGPKG_LIBC_STDIO#define perror(s) diag_printf(#s ": %s\n", strerror(errno))#endif#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000)static char stack[STACK_SIZE];static cyg_thread thread_data;static cyg_handle_t thread_handle;// Background load stuff#define NUM_LOAD_THREADS 20 // Get 5% granularity#define IDLE_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY+3#define LOAD_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-3#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-4#define DESIRED_BACKGROUND_LOAD 50 // should be accurate enough over range// starting points for load calculation#define MAX_LOAD_THREAD_LEVEL 100#define MIN_LOAD_THREAD_LEVEL 0static char idle_thread_stack[STACK_SIZE];static cyg_thread idle_thread_data;static cyg_handle_t idle_thread_handle;static cyg_sem_t idle_thread_sem;volatile static long long idle_thread_count;static char load_thread_stack[NUM_LOAD_THREADS][STACK_SIZE];static cyg_thread load_thread_data[NUM_LOAD_THREADS];static cyg_handle_t load_thread_handle[NUM_LOAD_THREADS];static cyg_sem_t load_thread_sem[NUM_LOAD_THREADS];static long load_thread_level;static void calibrate_load(int load);static void start_load(int load);static void do_some_random_computation(int p,int id);#define abs(n) ((n) < 0 ? -(n) : (n))static long long no_load_idle_count_1_second;extern voidcyg_test_exit(void);voidpexit(char *s){ TNR_OFF(); perror(s); cyg_test_exit();}intdo_read(int s, void *_buf, int len){ int total, slen, rlen; unsigned char *buf = (unsigned char *)_buf; total = 0; rlen = len; while (total < len) { slen = read(s, buf, rlen); if (slen != rlen) { if (slen < 0) { diag_printf("Error after reading %d bytes\n", total); return -1; } rlen -= slen; buf += slen; } total += slen; } return total;}intdo_write(int s, void *_buf, int len){ int total, slen, rlen; unsigned char *buf = (unsigned char *)_buf; total = 0; rlen = len; while (total < len) { slen = write(s, buf, rlen); if (slen != rlen) { if (slen < 0) { diag_printf("Error after writing %d bytes\n", total); return -1; } rlen -= slen; buf += slen; } total += slen; } return total;}//// 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; // Compute the "no load" idle value 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 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; if (load == 0) { diag_printf("Set no background load\n"); if (prev_load == 0) return; // Nothing out there to stop for (i = 0; i < prev_load * NUM_LOAD_THREADS/100; i++) { cyg_semaphore_wait(&load_thread_sem[i]); } prev_load = 0; } else { diag_printf("Set background load = %d%% starting %d threads\n", load, load * NUM_LOAD_THREADS/100 ); for (i = 0; i < load * NUM_LOAD_THREADS/100; 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.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?