⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stress_threads.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 2 页
字号:
        } cyg_mutex_unlock(&client_request_lock);        cyg_thread_delay(10+delay);    }}/* listener_program() -- listens for a request and spawns a handler to   take care of the request */void listener_program(cyg_addrword_t data){    for (;;) {        int make_request = 0;        cyg_mutex_lock(&client_request_lock); {            if (client_makes_request > 0) {                --client_makes_request;                make_request = 1;            }        } cyg_mutex_unlock(&client_request_lock);                if (make_request)            start_handler();                cyg_thread_delay(2 + (rand() % 10));    }}/* handler_program() -- is spawned to handle each incoming request */void handler_program(cyg_addrword_t data){    /* here is where we perform specific stressful tasks */    perform_stressful_tasks();    cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000)))));    {        // Loop until the handler id and priority can be communicated to        // the main_program.        int freed = 0;        do {            cyg_mutex_lock(&free_handler_lock); {                if (-1 == free_handler_id) {                    free_handler_id = data;                    free_handler_pri = P_BASE_HANDLER+(int) data;                    freed = 1;                }            } cyg_mutex_unlock(&free_handler_lock);            if (!freed)                cyg_thread_delay(2);        } while (!freed);    }    // Then exit.    cyg_thread_exit();}/* start a new handler */void start_handler(void){    int prio;    char* name;    int handler_slot;    int found = 0;    while (!found) {        cyg_mutex_lock(&handler_slot_lock); {            for (handler_slot = 0; handler_slot < MAX_HANDLERS;++handler_slot){                if (!handler_thread_in_use[handler_slot]) {                    found = 1;                    handler_thread_in_use[handler_slot]++;                    handler_thread_in_use_count++;                    break;                }            }        } cyg_mutex_unlock(&handler_slot_lock);        if (!found)            cyg_thread_delay(1);    }    CYG_ASSERT(1 == handler_thread_in_use[handler_slot],                "Handler usage count wrong!");    prio = P_BASE_HANDLER+handler_slot;    CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");    priority_in_use[prio]++;    name = &thread_name[prio][0];    sprintf(name, "handler-%02d/%02d", handler_slot, prio);    priority_translation[prio] =        sc_thread_create(prio, handler_program,                         (cyg_addrword_t) handler_slot,                         name, (void *) handler_stack[handler_slot],                         STACK_SIZE_HANDLER, &handlerH[handler_slot],                         &handler_thread_s[handler_slot]);    cyg_thread_resume(handlerH[handler_slot]);    ++statistics.handler_invocation_histogram[handler_slot];}/* free a locked handler thread */void stop_handler(int handler_id, int handler_pri){    // Finally delete the handler thread. This must be done in a    // loop, waiting for the call to return true. If it returns    // false, go to sleep for a bit, so the killed thread gets a    // chance to run and complete its business.    while (!cyg_thread_delete(handlerH[handler_id])) {        cyg_thread_delay(1);    }    ++statistics.thread_exits;        // Free the handler resources.    cyg_mutex_lock(&handler_slot_lock); {        handler_thread_in_use[handler_id]--;        handler_thread_in_use_count--;        priority_in_use[handler_pri]--;        CYG_ASSERT(0 == priority_in_use[handler_pri],                    "Priority not in use!");        CYG_ASSERT(0 == handler_thread_in_use[handler_id],                    "Handler not in use!");        CYG_ASSERT(0 <= handler_thread_in_use_count,                    "Stopped more handlers than was started!");    } cyg_mutex_unlock(&handler_slot_lock);        }/* do things which will stress the system */void perform_stressful_tasks(){#define MAX_MALLOCED_SPACES 100  /* do this many mallocs at most */#define MALLOCED_BASE_SIZE 1    /* basic size in bytes */    char *spaces[MAX_MALLOCED_SPACES];    int  sizes[MAX_MALLOCED_SPACES];    unsigned int i, j, size;    cyg_uint8 pool_space[10][100];    cyg_handle_t mempool_handles[10];    cyg_mempool_fix mempool_objects[10];    /* here I use malloc, which uses the kernel's variable memory pools.       note that malloc/free is a bit simple-minded here: it does not       try to really fragment things, and it does not try to make the       allocation/deallocation concurrent with other thread execution       (although I'm about to throw in a yield()) */    for (i = 0; i < MAX_MALLOCED_SPACES; ++i) {        ++statistics.malloc_tries;        size = (i*2+1)*MALLOCED_BASE_SIZE;        spaces[i] = (char *) malloc(size);        sizes[i] = size;        if (spaces[i] != NULL) {            // Fill with a known value (differs between chunk).            for (j = 0; j < size; ++j) {                spaces[i][j] = 0x50 | ((j+i) & 0x0f);            }        }        if (i % (MAX_MALLOCED_SPACES/10) == 0) {            cyg_thread_yield();        }        if (i % (MAX_MALLOCED_SPACES/15) == 0) {            cyg_thread_delay(i % 5);        }    }    cyg_thread_delay(5);    /* now free it all up */    for (i = 0; i < MAX_MALLOCED_SPACES; ++i) {        if (spaces[i] != NULL) {            size = sizes[i];            for (j = 0; j < size; ++j) {                // Validate chunk data.                if ((0x50 | ((j+i) & 0x0f)) != spaces[i][j]) {                    printf("Bad byte in chunk\n");                }                spaces[i][j] = 0xAA;    /* write a bit pattern */            }            free(spaces[i]);        } else {            ++statistics.malloc_failures;        }    }    /* now allocate and then free some fixed-size memory pools; for       now this is simple-minded because it does not have many threads       sharing the memory pools and racing for memory. */    for (i = 0; i < 10; ++i) {        cyg_mempool_fix_create(pool_space[i], 100, (i+1)*3,                               &mempool_handles[i], &mempool_objects[i]);    }    for (i = 0; i < 10; ++i) {        spaces[i] = cyg_mempool_fix_try_alloc(mempool_handles[i]);    }    for (i = 0; i < 10; ++i) {        if (spaces[i]) {            cyg_mempool_fix_delete(mempool_handles[i]);        }    }}/* report_alarm_func() is invoked as an alarm handler, so it should be   quick and simple.  in this case it sets a global flag which is   checked by main_program. */void report_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data){    time_to_report = 1;}#ifdef DEATH_TIME_LIMIT/* this sets up death alarms. it gets the handle and alarm from the   caller, since they must persist for the life of the alarm */void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp,                       cyg_alarm *death_alarm_p, int *killed_p){    cyg_handle_t system_clockH, counterH;    cyg_resolution_t rtc_res;    system_clockH = cyg_real_time_clock();    cyg_clock_to_counter(system_clockH, &counterH);    cyg_alarm_create(counterH, death_alarm_func,                     (cyg_addrword_t) killed_p,                     deathHp, death_alarm_p);    rtc_res = cyg_clock_get_resolution(system_clockH);    {        cyg_tick_count_t tick_delay;        tick_delay = (long long)            ((1000000000.0*rtc_res.divisor)             *((double)DEATH_TIME_LIMIT)/((double)rtc_res.dividend));        if ( cyg_test_is_simulator )            tick_delay /= 10;#ifdef CYGPKG_HAL_I386_LINUX         // 20 seconds is a long time compared to the run time of other tests.        // Reduce to 10 seconds, allowing more tests to get run.        tick_delay /= 2;#endif        cyg_alarm_initialize(*deathHp, cyg_current_time() + tick_delay, 0);    }}#endif/* death_alarm_func() is the alarm handler that kills the current   thread after a specified timeout. It does so by setting a flag the   thread is constantly checking. */void death_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data){    int *killed_p;    killed_p = (int *) data;    *killed_p = 1;}/* now I write the sc_ versions of the cyg_functions */cyg_addrword_t sc_thread_create(    cyg_addrword_t      sched_info,            /* scheduling info (eg pri)  */    cyg_thread_entry_t  *entry,                /* entry point function      */    cyg_addrword_t      entry_data,            /* entry data                */    char                *name,                 /* optional thread name      */    void                *stack_base,           /* stack base, NULL = alloc  */    cyg_ucount32        stack_size,            /* stack size, 0 = default   */    cyg_handle_t        *handle,               /* returned thread handle    */    cyg_thread          *thread                /* put thread here           */    ){    ++statistics.thread_creations;    cyg_thread_create(sched_info, entry, entry_data, name,                      stack_base, stack_size, handle, thread);    return cyg_thread_get_priority(*handle);}#define MINS_HOUR (60)#define MINS_DAY  (60*24)externC void *cyg_libc_get_malloc_pool( void );void print_statistics(int print_full){    int i;    static int stat_dumps = 0;    static int print_count = 0;    static int shift_count = 0;    int minutes;    stat_dumps++;    // Find number of minutes.    minutes = time_report_delay*stat_dumps / 60;    if (!print_full) {        // Return if time/minutes not integer.        if ((time_report_delay*stat_dumps % 60) != 0)            return;        // After the first day, only dump stat once per day. Do print        // a . on the hour though.        if ((minutes > MINS_DAY) && ((minutes % MINS_DAY) != 0)) {            if ((minutes % MINS_HOUR) == 0) {                printf(".");                fflush(stdout);            }            return;        }        // After the first hour of the first day, only dump stat once        // per hour. Do print . each minute though.        if ((minutes < MINS_DAY) && (minutes > MINS_HOUR)            && ((minutes % MINS_HOUR) != 0)) {            printf(".");            fflush(stdout);            return;        }    }    printf("\nState dump %d (%d hours, %d minutes) [numbers >>%d]\n",           ++print_count, minutes / MINS_HOUR, minutes % MINS_HOUR,            shift_count);    cyg_mutex_lock(&statistics_print_lock); {        //--------------------------------        // Information private to this test:        printf(" Handler-invocations: ");        for (i = 0; i < MAX_HANDLERS; ++i) {            printf("%4lu ", statistics.handler_invocation_histogram[i]);        }        printf("\n");        printf(" malloc()-tries/failures: -- %7lu %7lu\n",               statistics.malloc_tries, statistics.malloc_failures);        printf(" client_makes_request:       %d\n", client_makes_request);        // Check for big numbers and reduce if getting close to overflow        if (statistics.malloc_tries > 0x40000000) {            shift_count++;            for (i = 0; i < MAX_HANDLERS; ++i) {                statistics.handler_invocation_histogram[i] >>= 1;            }            statistics.malloc_tries >>= 1;            statistics.malloc_failures >>= 1;        }    } cyg_mutex_unlock(&statistics_print_lock);    //--------------------------------    // System information    {        cyg_mempool_info mem_info;        cyg_mempool_var_get_info((cyg_handle_t) cyg_libc_get_malloc_pool(),                                  &mem_info);        printf(" Memory system: Total=0x%08x Free=0x%08x Max=0x%08x\n",                mem_info.totalmem, mem_info.freemem, mem_info.maxfree);    }    // Dump stack status    printf(" Stack usage:\n");    cyg_test_dump_interrupt_stack_stats( "  Interrupt" );    cyg_test_dump_idlethread_stack_stats( "  Idle" );    cyg_test_dump_stack_stats("  Main", main_stack,                               main_stack + sizeof(main_stack));    for (i = 0; i < MAX_HANDLERS; i++) {        cyg_test_dump_stack_stats("  Handler", handler_stack[i],                                   handler_stack[i] + sizeof(handler_stack[i]));    }    for (i = 0; i < N_LISTENERS; i++) {        cyg_test_dump_stack_stats("  Listener", listener_stack[i],                                   listener_stack[i] + sizeof(listener_stack[i]));    }    for (i = 0; i < N_CLIENTS; i++) {        cyg_test_dump_stack_stats("  Client", client_stack[i],                                   client_stack[i] + sizeof(client_stack[i]));    }}#else /* (CYGNUM_KERNEL_SCHED_PRIORITIES >=    *//* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */#define N_A_MSG "not enough priorities available"#endif /* (CYGNUM_KERNEL_SCHED_PRIORITIES >=    *//* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */#else /* CYGSEM_LIBC_MALLOC */# define N_A_MSG "this test needs malloc"#endif /* CYGSEM_LIBC_MALLOC */#else /* CYGFUN_KERNEL_THREADS_TIMER */# define N_A_MSG "this test needs kernel threads timer"#endif /* CYGFUN_KERNEL_THREADS_TIMER */#else /* CYGPKG_LIBM */# define N_A_MSG "this test needs libm"#endif /* CYGPKG_LIBM */#else /* CYGSEM_LIBC_STDIO */# define N_A_MSG "this test needs stdio"#endif /* CYGSEM_LIBC_STDIO */#else // def CYGFUN_KERNEL_API_C# define N_A_MSG "this test needs Kernel C API"#endif#else // def CYGPKG_KERNEL && CYGPKG_IO && CYGPKG_LIBC# define N_A_MSG "this tests needs Kernel, libc and IO"#endif#ifdef N_A_MSGexternC voidcyg_start( void ){    CYG_TEST_INIT();    CYG_TEST_NA( N_A_MSG);}#endif // N_A_MSG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -