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 + -
显示快捷键?