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

📄 stress_threads.c

📁 eCos1.31版
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================////        stress_threads.cxx////        Basic thread stress test////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):     rosalia// Contributors:  rosalia, jskov// Date:          1999-04-13// Description:   Very simple thread stress test, with some memory//                allocation and alarm handling.//// Notes://  If client_makes_request is big, it means that there are made many more//  client requests than can be serviced. Consequently, clients are wasting//  CPU time and should be sleeping more.////  The list of handler invocations show how many threads are running//  at the same time. The more powerful the CPU, the more the numbers//  should spread out.//####DESCRIPTIONEND#####include <pkgconf/system.h>#include <cyg/infra/testcase.h>#include <cyg/hal/hal_arch.h>#if defined(CYGPKG_KERNEL) && defined(CYGPKG_IO) && defined(CYGPKG_LIBC)#include <pkgconf/kernel.h>#include <pkgconf/libc.h>#if defined(CYGFUN_KERNEL_API_C)#include <cyg/kernel/kapi.h>#ifdef CYGPKG_LIBC_STDIO#include <stdio.h>#include <stdlib.h>#if defined(CYGPKG_LIBM)#include <math.h>#include <assert.h>#include <cyg/kernel/test/stackmon.h>#if defined(CYGFUN_KERNEL_THREADS_TIMER)#if defined(CYGPKG_LIBC_MALLOC)/* if TIME_LIMIT is defined, it represents the number of seconds this   test should last; if it is undefined the test will go forever */#define DEATH_TIME_LIMIT 20/* #undef DEATH_TIME_LIMIT */// STACK_SIZE is typical +2kB for printf family calls which use big// auto variables. Add more for handler which calls perform_stressful_tasks()#define STACK_SIZE (2*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)#define STACK_SIZE_HANDLER (4*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)#define N_MAIN 1//-----------------------------------------------------------------------// Some targets need to define a smaller number of handlers due to// memory restrictions.#ifdef CYGPKG_HAL_ARM_AEB#define MAX_HANDLERS 4#define N_LISTENERS 1#define N_CLIENTS 1#undef STACK_SIZE#undef STACK_SIZE_HANDLER#define STACK_SIZE (1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)#define STACK_SIZE_HANDLER (1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)#endif//-----------------------------------------------------------------------// If no target specific definitions, use defaults#ifndef MAX_HANDLERS#define MAX_HANDLERS 19#define N_LISTENERS 4#define N_CLIENTS 4#endif/* Allocate priorities in this order. This ensures that handlers   (which are the ones using the CPU) get enough CPU time to actually   complete their tasks.    The empty space ensures that if libc main() thread should happen to   be in the priority range of the handlers, no handlers are   accidently reduced so much in priority to get below   listeners/clients. */#define P_MAIN_PROGRAM    1#define P_MAIN_PROGRAM_E  (P_MAIN_PROGRAM+N_MAIN)#define P_BASE_HANDLER    (P_MAIN_PROGRAM_E)#define P_BASE_HANDLER_E  (P_BASE_HANDLER+MAX_HANDLERS)#define P_BASE_EMPTY      (P_BASE_HANDLER_E)#define P_BASE_EMPTY_E    (P_BASE_EMPTY+2)#define P_BASE_LISTENER   (P_BASE_EMPTY_E)#define P_BASE_LISTENER_E (P_BASE_LISTENER+N_LISTENERS)#define P_BASE_CLIENT     (P_BASE_LISTENER_E)#define P_BASE_CLIENT_E   (P_BASE_CLIENT+N_CLIENTS)#define P_MAX             (P_BASE_CLIENT_E)/* Ensure there's room for what we request */#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= P_MAX)/* if we use the bitmap scheduler we must make sure we don't use the   same priority more than once, so we must store those already in use */static volatile char priority_in_use[P_MAX];/* We may not get the priority we ask for (scheduler may decide to ignore   schedule hint). So keep a table of priorities actually assigned to   the threads. This information may come in handy for debugging - it's   not actively used by the code. */static volatile int  priority_translation[P_MAX];/* now declare (and allocate space for) some kernel objects, like the   threads we will use */cyg_thread main_thread_s;cyg_thread handler_thread_s[MAX_HANDLERS];cyg_thread listener_thread_s[N_LISTENERS];cyg_thread client_thread_s[N_CLIENTS];/* space for stacks for all threads */char main_stack[STACK_SIZE];char handler_stack[MAX_HANDLERS][STACK_SIZE_HANDLER];char listener_stack[N_LISTENERS][STACK_SIZE];char client_stack[N_CLIENTS][STACK_SIZE];/* now the handles for the threads */cyg_handle_t mainH;cyg_handle_t handlerH[MAX_HANDLERS];cyg_handle_t listenerH[N_LISTENERS];cyg_handle_t clientH[N_CLIENTS];/* space for thread names */char thread_name[P_MAX][20];/* and now variables for the procedure which is the thread */cyg_thread_entry_t main_program, client_program, listener_program,     handler_program;/* a few mutexes used in the code */cyg_mutex_t client_request_lock, handler_slot_lock, statistics_print_lock,     free_handler_lock;/* global variables with which the handler IDs and thread priorities   to free are communicated from handlers to main_program. Access to   these are protected by free_handler_lock. An id of -1 means the   that the variables are empty. */volatile int free_handler_pri = 0;volatile int free_handler_id = -1;/* a global variable with which the client and server coordinate */volatile int client_makes_request = 0;/* if this is true, clients will not make requests */volatile int clients_paused = 0;/* indicates that it's time to print out a report */volatile int time_to_report = 0;/* print status after a delay of this many secs. */int time_report_delay;/*** now application-specific variables ***//* an array that stores whether the handler threads are in use */volatile int handler_thread_in_use[MAX_HANDLERS];/* total count of active handlers */volatile int handler_thread_in_use_count;/***** statistics-gathering variables *****/struct s_statistics {    /* store the number of times each handler has been invoked */    unsigned long handler_invocation_histogram[MAX_HANDLERS];    /* store how many times malloc has been attempted and how many times       it has failed */    unsigned long malloc_tries, malloc_failures;    /* how many threads have been created */    unsigned long thread_creations, thread_exits;};struct s_statistics statistics;/* some function prototypes; those with the sc_ prefix are   "statistics-collecting" versions of the cyg_ primitives */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           */    );void start_handler(void);void stop_handler(int handler_id, int handler_pri);void perform_stressful_tasks(void);void permute_array(char a[], int size, int seed);void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp,                       cyg_alarm *death_alarm_p, int *killed_p);void print_statistics(int print_full);/* we need to declare the alarm handling function (which is defined   below), so that we can pass it to cyg_alarm_initialize() */cyg_alarm_t report_alarm_func, death_alarm_func;/* handle and alarm for the report alarm */cyg_handle_t report_alarmH, counterH, system_clockH;cyg_alarm report_alarm;/* main launches all the threads of the test */intmain(void){    int i;    CYG_TEST_INIT();    CYG_TEST_INFO("Stress threads test compiled on " __DATE__);    cyg_mutex_init(&client_request_lock);    cyg_mutex_init(&statistics_print_lock);    cyg_mutex_init(&free_handler_lock);    /* initialize statistics */    memset(&statistics, 0, sizeof(statistics));    /* clear priority table */    for (i = 0; i < sizeof(priority_in_use); i++)        priority_in_use[i] = 0;    /* initialize main thread */    {        priority_translation[P_MAIN_PROGRAM] =            sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0,                             "main_program", (void *) main_stack, STACK_SIZE,                             &mainH, &main_thread_s);        priority_in_use[P_MAIN_PROGRAM]++;    }    /* initialize all handler threads to not be in use */    for (i = 0; i < MAX_HANDLERS; ++i) {        handler_thread_in_use[i] = 0;    }    handler_thread_in_use_count = 0;    for (i = 0; i < N_LISTENERS; ++i) {        int prio = P_BASE_LISTENER + i;        char* name = &thread_name[prio][0];        sprintf(name, "listener-%02d", i);        priority_translation[prio] =            sc_thread_create(prio, listener_program, (cyg_addrword_t) i,                             name, (void *) listener_stack[i], STACK_SIZE,                             &listenerH[i], &listener_thread_s[i]);        CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");        priority_in_use[prio]++;    }    for (i = 0; i < N_CLIENTS; ++i) {        int prio = P_BASE_CLIENT + i;        char* name = &thread_name[prio][0];        sprintf(name, "client-%02d", i);        priority_translation[prio] =            sc_thread_create(prio, client_program, (cyg_addrword_t) i,                             name, (void *) client_stack[i], STACK_SIZE,                             &(clientH[i]), &client_thread_s[i]);        CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!");        priority_in_use[prio]++;    }    cyg_thread_resume(mainH);    for (i = 0; i < N_CLIENTS; ++i) {        cyg_thread_resume(clientH[i]);    }    for (i = 0; i < N_LISTENERS; ++i) {        cyg_thread_resume(listenerH[i]);    }    /* set up the alarm which gives periodic wakeups to say "time to       print a report */    system_clockH = cyg_real_time_clock();    cyg_clock_to_counter(system_clockH, &counterH);    cyg_alarm_create(counterH, report_alarm_func,                     (cyg_addrword_t) 4000,                     &report_alarmH, &report_alarm);    if (cyg_test_is_simulator) {        time_report_delay = 2;    } else {        time_report_delay = 60;    }    cyg_alarm_initialize(report_alarmH, cyg_current_time()+200,                          time_report_delay*100);    return 0;}/* main_program() -- frees resources and prints status. */void main_program(cyg_addrword_t data){#ifdef DEATH_TIME_LIMIT    cyg_handle_t deathH;    cyg_alarm death_alarm;    int is_dead = 0;    setup_death_alarm(0, &deathH, &death_alarm, &is_dead);#endif /* DEATH_TIME_LIMIT */    for (;;) {        int handler_id = -1;        int handler_pri = 0;        cyg_mutex_lock(&free_handler_lock); {            // If any handler has left its ID, copy the ID and            // priority values to local variables, and free up the            // global communication variables again.            if (-1 != free_handler_id) {                handler_id = free_handler_id;                handler_pri = free_handler_pri;                free_handler_id = -1;            }        } cyg_mutex_unlock(&free_handler_lock);        if (-1 != handler_id) {            stop_handler(handler_id, handler_pri);        }        // If it's time to report status or quit, set pause flag and        // keep looping until all handlers have stopped.        if (time_to_report) {            // Pause clients            cyg_mutex_lock(&client_request_lock); {                clients_paused = 1;            } cyg_mutex_unlock(&client_request_lock);            // When all handlers have stopped, we can print statistics            // knowing that all (handler allocated) resources should have            // been freed. That is, we should be able to determine leaks.            if (0 == handler_thread_in_use_count) {                print_statistics(0);                // We've done the printing now. Resume the system.                time_to_report = 0;                cyg_mutex_lock(&client_request_lock); {                    clients_paused = 0;                } cyg_mutex_unlock(&client_request_lock);            }         }#ifdef DEATH_TIME_LIMIT        // Stop test if time. We don't care about resource state here        // since we've only run for a limited time anyway.        if (is_dead) {            print_statistics(1);            CYG_TEST_PASS_FINISH("Kernel thread stress test OK");        }#endif /* DEATH_TIME_LIMIT */        cyg_thread_delay(3);    }}/* client_program() -- an obnoxious client which makes a lot of requests */void client_program(cyg_addrword_t data){    int delay;    system_clockH = cyg_real_time_clock();    cyg_clock_to_counter(system_clockH, &counterH);    for (;;) {        delay = (rand() % 20);        /* now send a request to the server */        cyg_mutex_lock(&client_request_lock); {            if (0 == clients_paused)                client_makes_request++;

⌨️ 快捷键说明

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