📄 stress_threads.c
字号:
//==========================================================================//// stress_threads.cxx//// Basic thread stress test////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // 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 Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): rosalia// Contributors: rosalia// Date: 1999-04-13// Description: Very simple thread stress test, with some memory// allocation and alarm handling.//####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>#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 15/* #undef DEATH_TIME_LIMIT */#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL)#define STACK_SIZE2 (8*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL)#define N_CLIENTS 4#define N_LISTENERS 4#define MAX_HANDLERS 19#if (CYGNUM_KERNEL_SCHED_PRIORITIES < (N_CLIENTS+N_LISTENERS+MAX_HANDLERS))# error "not enough priorities available"#endif/* 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 char priority_in_use[N_CLIENTS+N_LISTENERS+MAX_HANDLERS];/* now declare (and allocate space for) some kernel objects, like the threads we will use */cyg_thread client_thread_s[N_CLIENTS];cyg_thread listener_thread_s[N_LISTENERS];cyg_thread handler_thread_s[MAX_HANDLERS];/* space for stacks for all threads */char client_stack[N_CLIENTS][STACK_SIZE];char listener_stack[N_LISTENERS][STACK_SIZE];char handler_stack[MAX_HANDLERS][STACK_SIZE2];/* now the handles for the threads */cyg_handle_t clientH[N_CLIENTS];cyg_handle_t listenerH[N_LISTENERS];cyg_handle_t handlerH[MAX_HANDLERS];#ifdef DEATH_TIME_LIMIT/* how many client threads have been killed by the death handler */int n_clients_killed = 0;#endif /* DEATH_TIME_LIMIT *//* and now variables for the procedure which is the thread */cyg_thread_entry_t 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;/* a global variable with which the client and server coordinate */int client_makes_request = 0;/* indicates that it's time to print out a report */int time_to_report = 0;/*** now application-specific variables ***//* an array that stores whether the handler threads are in use */int handler_thread_in_use[MAX_HANDLERS];/***** 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 */void 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 sc_thread_exit(void);int get_handler_slot(cyg_handle_t current_threadH);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 handle_death(cyg_handle_t deathH, cyg_handle_t alarmH);void print_statistics(void);/* 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;/* we install our own startup routine which sets up threads */void cyg_user_start(void){ int i; CYG_TEST_INIT(); CYG_TEST_INFO("# Entering stress's cyg_user_start() function"); cyg_mutex_init(&client_request_lock); cyg_mutex_init(&statistics_print_lock); /* initialize statistics */ memset(&statistics, 0, sizeof(statistics)); /* initialize all handler threads to not be in use */ for (i = 0; i < MAX_HANDLERS; ++i) { handler_thread_in_use[i] = 0; } for (i = 0; i < N_CLIENTS; ++i) { int prio; char thread_name[20]; sprintf(thread_name, "client-%02d", i); prio = i; sc_thread_create(prio, client_program, (cyg_addrword_t) i, thread_name, (void *) client_stack[i], STACK_SIZE, &(clientH[i]), &client_thread_s[i]); priority_in_use[prio] = 1; } for (i = 0; i < N_LISTENERS; ++i) { int prio; char thread_name[20]; sprintf(thread_name, "listener-%02d", i); prio = N_CLIENTS + i; sc_thread_create(prio, listener_program, (cyg_addrword_t) i, thread_name, (void *) listener_stack[i], STACK_SIZE, &listenerH[i], &listener_thread_s[i]); priority_in_use[prio] = 1; } 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) { cyg_alarm_initialize(report_alarmH, cyg_current_time()+300, 400); } else { cyg_alarm_initialize(report_alarmH, cyg_current_time()+300, 4000); }}/* client_program() -- an obnoxious client which makes a lot of requests */void client_program(cyg_addrword_t data){ int delay; cyg_handle_t counterH, deathH, system_clockH; cyg_alarm death_alarm; int is_dead = 0; setup_death_alarm(data, &deathH, &death_alarm, &is_dead); printf("# Starting client-%d\n", (int) data); system_clockH = cyg_real_time_clock(); cyg_clock_to_counter(system_clockH, &counterH); for (;;) { delay = (rand() % 3); /* now send a request to the server */ cyg_mutex_lock(&client_request_lock); { ++client_makes_request;/* printf("client_makes_request %d\n", client_makes_request); */ } cyg_mutex_unlock(&client_request_lock); cyg_thread_delay(10+delay);/* cyg_thread_delay(0); */#ifdef DEATH_TIME_LIMIT if (is_dead) { handle_death(deathH, report_alarmH); }#endif /* DEATH_TIME_LIMIT */ }}/* listener_program() -- listens for a request and spawns a handler to take care of the request */void listener_program(cyg_addrword_t data){/* int message = (int) data; */ int handler_slot; printf("# Beginning execution; thread data is %d\n", (int) data); for (;;) {#ifdef DEATH_TIME_LIMIT /* as an extra task, the listener sees if all clients have been killed off, so it can report that the test is over */ if (n_clients_killed == N_CLIENTS) { n_clients_killed = -1; /* so we don't call this again */ CYG_TEST_PASS_FINISH("Kernel thread stress test OK");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -