Mercurial > ecos
diff packages/kernel/current/tests/stress_threads.c @ 24:306eee292492 ecos-sw-1999-07-16
Merge from eCos master repository on 1999-07-16-05:47:06-BST
| author | jlarmour |
|---|---|
| date | Fri, 16 Jul 1999 21:54:32 +0000 |
| parents | 53104bbd5f99 |
| children | 18ee5a9c102e |
line wrap: on
line diff
--- a/packages/kernel/current/tests/stress_threads.c +++ b/packages/kernel/current/tests/stress_threads.c @@ -84,19 +84,29 @@ #define STACK_SIZE (2*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) #define STACK_SIZE2 (8*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) -/* 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 number of instances in each thread class #define N_MAIN 1 #define MAX_HANDLERS 19 #define N_LISTENERS 4 #define N_CLIENTS 4 +#define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS) -#if (CYGNUM_KERNEL_SCHED_PRIORITIES >= (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS)) +/* 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. */ +//#define P_MAIN 0 // This is defined by libc +#define P_MAIN_PROGRAM 1 +#define P_BASE_HANDLER 2 +#define P_BASE_LISTENER (P_BASE_HANDLER+MAX_HANDLERS) +#define P_BASE_CLIENT (P_BASE_LISTENER+N_LISTENERS) +#define P_MAX (P_BASE_CLIENT+N_CLIENTS) + + +#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[N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS]; +static volatile char priority_in_use[P_MAX]; /* now declare (and allocate space for) some kernel objects, like the threads we will use */ @@ -117,6 +127,9 @@ 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; @@ -137,7 +150,7 @@ int client_makes_request = 0; /* indicates that it's time to print out a report */ int time_to_report = 0; - /* print status after a delay of this many secs. */ +/* print status after a delay of this many secs. */ int time_report_delay; /*** now application-specific variables ***/ @@ -170,7 +183,7 @@ void sc_thread_create( cyg_ucount32 stack_size, /* stack size, 0 = default */ cyg_handle_t *handle, /* returned thread handle */ cyg_thread *thread /* put thread here */ -); + ); int get_handler_slot(cyg_handle_t current_threadH); void perform_stressful_tasks(void); @@ -191,83 +204,81 @@ cyg_alarm report_alarm; int main(void) { - int i; + int i; - CYG_TEST_INIT(); - CYG_TEST_INFO("# Entering stress's cyg_user_start() function"); + 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); - cyg_mutex_init(&free_handler_lock); + 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)); + /* initialize statistics */ + memset(&statistics, 0, sizeof(statistics)); - /* clear priority table */ - for (i = 0; i < sizeof(priority_in_use); i++) - priority_in_use[i] = 0; + /* clear priority table */ + for (i = 0; i < sizeof(priority_in_use); i++) + priority_in_use[i] = 0; - /* initialize main thread */ - { - char thread_name[] = "main"; - - sc_thread_create(0, main_program, (cyg_addrword_t) 0, - thread_name, (void *) main_stack, STACK_SIZE, - &mainH, &main_thread_s); - priority_in_use[0]++; - } + /* initialize main thread */ + { + 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; - } - for (i = 0; i < N_LISTENERS; ++i) { - int prio; - char thread_name[20]; - sprintf(thread_name, "listener-%02d", i); - prio = N_MAIN + MAX_HANDLERS + 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]); - CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); - priority_in_use[prio]++; - } - for (i = 0; i < N_CLIENTS; ++i) { - int prio; - char thread_name[20]; - sprintf(thread_name, "client-%02d", i); - prio = N_MAIN + MAX_HANDLERS + N_LISTENERS + 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]); - CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); - priority_in_use[prio]++; - } + /* 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_LISTENERS; ++i) { + int prio = P_BASE_LISTENER + i; + char* name = &thread_name[prio][0]; + sprintf(name, "listener-%02d/%02d", i, 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/%02d", i, 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]); - } + 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); - /* 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 = 30; + } - 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 = 30; - } + cyg_alarm_initialize(report_alarmH, cyg_current_time()+200, + time_report_delay*100); - cyg_alarm_initialize(report_alarmH, cyg_current_time()+200, - time_report_delay*100); + return 0; } /* main_program() -- frees resources and prints status. */ @@ -340,25 +351,25 @@ void main_program(cyg_addrword_t data) /* client_program() -- an obnoxious client which makes a lot of requests */ void client_program(cyg_addrword_t data) { - int delay; + int delay; - printf("# Starting client-%d\n", (int) data); + printf("# Starting client-%d\n", (int) data); - system_clockH = cyg_real_time_clock(); - cyg_clock_to_counter(system_clockH, &counterH); + system_clockH = cyg_real_time_clock(); + cyg_clock_to_counter(system_clockH, &counterH); - for (;;) { - delay = (rand() % 20); + for (;;) { + delay = (rand() % 20); - /* now send a request to the server */ - cyg_mutex_lock(&client_request_lock); { - ++client_makes_request; + /* 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_mutex_unlock(&client_request_lock); - cyg_thread_delay(10+delay); + cyg_thread_delay(10+delay); /* cyg_thread_delay(0); */ - } + } } /* listener_program() -- listens for a request and spawns a handler to @@ -381,17 +392,21 @@ void listener_program(cyg_addrword_t dat if (make_request) { int prio; + char* name; /* printf("just got a request from a client (count = %d)\n", */ /* client_makes_request); */ handler_slot = get_handler_slot(listenerH[(int) data]); - prio = N_MAIN+handler_slot; + prio = P_BASE_HANDLER+handler_slot; + + name = &thread_name[prio][0]; + sprintf(name, "handler-%02d/%02d", handler_slot, prio); CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); priority_in_use[prio]++; sc_thread_create(prio, handler_program, (cyg_addrword_t) handler_slot, - "handler", (void *) handler_stack[handler_slot], + name, (void *) handler_stack[handler_slot], STACK_SIZE2, &handlerH[handler_slot], &handler_thread_s[handler_slot]); cyg_thread_resume(handlerH[handler_slot]); @@ -405,32 +420,32 @@ void listener_program(cyg_addrword_t dat /* 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(); + /* here is where we perform specific stressful tasks */ + perform_stressful_tasks(); - cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000))))); + cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000))))); /* cyg_thread_delay(0); */ - ++statistics.thread_exits; - { - // 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 = N_MAIN+(int) data; - freed = 1; - } - } cyg_mutex_unlock(&free_handler_lock); - if (!freed) - cyg_thread_delay(2); - } while (!freed); - } + ++statistics.thread_exits; + { + // 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(); + // Then exit. + cyg_thread_exit(); } /* look for an available handler thread */ @@ -463,65 +478,65 @@ 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]; - unsigned int i; + char *spaces[MAX_MALLOCED_SPACES]; + unsigned int i; - cyg_mutex_t tmp_lock; + cyg_mutex_t tmp_lock; - cyg_uint8 pool_space[10][100]; - cyg_handle_t mempool_handles[10]; - cyg_mempool_fix mempool_objects[10]; + cyg_uint8 pool_space[10][100]; + cyg_handle_t mempool_handles[10]; + cyg_mempool_fix mempool_objects[10]; - cyg_mutex_init(&tmp_lock); + cyg_mutex_init(&tmp_lock); - /* 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; + /* 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; /* spaces[i] = (char *) malloc(((int)(sqrt(i*2.0))+1)*MALLOCED_BASE_SIZE); */ - spaces[i] = (char *) malloc(((int)i*2.0+1)*MALLOCED_BASE_SIZE); - if (i % (MAX_MALLOCED_SPACES/10) == 0) { - cyg_thread_yield(); + spaces[i] = (char *) malloc(((int)i*2.0+1)*MALLOCED_BASE_SIZE); + if (i % (MAX_MALLOCED_SPACES/10) == 0) { + cyg_thread_yield(); + } + if (i % (MAX_MALLOCED_SPACES/15) == 0) { + cyg_thread_delay(i % 5); + } } - if (i % (MAX_MALLOCED_SPACES/15) == 0) { - cyg_thread_delay(i % 5); - } - } - /* now free it all up */ - for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { - if (spaces[i] != NULL) { - unsigned int j; - for (j = 0; j < (i*2+1)*MALLOCED_BASE_SIZE; ++j) { - spaces[i][j] = 0xAA; /* write a bit pattern */ - } - free(spaces[i]); - } else { - ++statistics.malloc_failures; + /* now free it all up */ + for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { + if (spaces[i] != NULL) { + unsigned int j; + for (j = 0; j < (i*2+1)*MALLOCED_BASE_SIZE; ++j) { + 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]); - } + /* 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) { + 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]); + for (i = 0; i < 10; ++i) { + if (spaces[i]) { + cyg_mempool_fix_delete(mempool_handles[i]); + } } - } - cyg_mutex_destroy(&tmp_lock); + cyg_mutex_destroy(&tmp_lock); } /* report_alarm_func() is invoked as an alarm handler, so it should be @@ -538,31 +553,31 @@ void report_alarm_func(cyg_handle_t alar 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; + cyg_handle_t system_clockH, counterH; + cyg_resolution_t rtc_res; - system_clockH = cyg_real_time_clock(); - cyg_clock_to_counter(system_clockH, &counterH); + 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; + 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; + // 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); - } + cyg_alarm_initialize(*deathHp, cyg_current_time() + tick_delay, 0); + } } #endif @@ -571,9 +586,9 @@ void setup_death_alarm(cyg_addrword_t da 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; + int *killed_p; + killed_p = (int *) data; + *killed_p = 1; } /* now I write the sc_ versions of the cyg_functions */ @@ -586,51 +601,54 @@ void sc_thread_create( cyg_ucount32 stack_size, /* stack size, 0 = default */ cyg_handle_t *handle, /* returned thread handle */ cyg_thread *thread /* put thread here */ -) + ) { /*printf("Creating a thread -- priority is %lu\n", (unsigned long) sched_info);*/ /* fflush(stdout); */ - ++statistics.thread_creations; - cyg_thread_create(sched_info, entry, entry_data, name, - stack_base, stack_size, handle, thread); + ++statistics.thread_creations; + cyg_thread_create(sched_info, entry, entry_data, name, + stack_base, stack_size, handle, thread); + + CYG_ASSERT(cyg_thread_get_priority(*handle) == (cyg_priority_t) sched_info, + "Didn't get requested priority!"); } void print_statistics(int print_full) { - int i; - static int print_count = 0; + int i; + static int print_count = 0; - printf("State dump %d (time %02d.%02d.%02d)\n", - print_count, - print_count*time_report_delay / (60*60), // hours - (print_count*time_report_delay / 60) % 60, // minutes - (print_count*time_report_delay ) % 60); // seconds - print_count++; + printf("State dump %d (time %02d.%02d.%02d)\n", + print_count, + print_count*time_report_delay / (60*60), // hours + (print_count*time_report_delay / 60) % 60, // minutes + (print_count*time_report_delay ) % 60); // seconds + print_count++; - cyg_mutex_lock(&statistics_print_lock); { - printf(" Handler-invocations: "); - for (i = 0; i < MAX_HANDLERS; ++i) { - printf("%4lu ", statistics.handler_invocation_histogram[i]); + cyg_mutex_lock(&statistics_print_lock); { + 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); + } cyg_mutex_unlock(&statistics_print_lock); + + // Add: Also occasionally dump individual threads' stack status. + if (0 == print_count % 5 || print_full) { + cyg_test_dump_interrupt_stack_stats( " Status" ); + cyg_test_dump_idlethread_stack_stats( " Status" ); } - printf("\n"); - printf(" malloc()-tries/failures: -- %7lu %7lu\n", - statistics.malloc_tries, statistics.malloc_failures); - printf(" client_makes_request: %d\n", client_makes_request); - } cyg_mutex_unlock(&statistics_print_lock); - - // Add: Also occasionally dump individual threads' stack status. - if (0 == print_count % 5 || print_full) { - cyg_test_dump_interrupt_stack_stats( " Status" ); - cyg_test_dump_idlethread_stack_stats( " Status" ); - } } #else /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */ - /* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ +/* (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)) */ +/* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ #else /* CYGSEM_LIBC_MALLOC */ # define N_A_MSG "this test needs malloc"
