Mercurial > ecos-v2_0-branch
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 23:8883a9947b66 | 24:306eee292492 |
|---|---|
| 82 // STACK_SIZE is typical +2kB for printf family calls which use big | 82 // STACK_SIZE is typical +2kB for printf family calls which use big |
| 83 // auto variables. | 83 // auto variables. |
| 84 #define STACK_SIZE (2*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) | 84 #define STACK_SIZE (2*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) |
| 85 #define STACK_SIZE2 (8*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) | 85 #define STACK_SIZE2 (8*1024 + CYGNUM_HAL_STACK_SIZE_TYPICAL) |
| 86 | 86 |
| 87 /* Allocate priorities in this order. This ensures that handlers | 87 // The number of instances in each thread class |
| 88 (which are the ones using the CPU) get enough CPU time to actually | |
| 89 complete their tasks. */ | |
| 90 #define N_MAIN 1 | 88 #define N_MAIN 1 |
| 91 #define MAX_HANDLERS 19 | 89 #define MAX_HANDLERS 19 |
| 92 #define N_LISTENERS 4 | 90 #define N_LISTENERS 4 |
| 93 #define N_CLIENTS 4 | 91 #define N_CLIENTS 4 |
| 94 | 92 #define N_THREADS (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS) |
| 95 #if (CYGNUM_KERNEL_SCHED_PRIORITIES >= (N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS)) | 93 |
| 94 /* Allocate priorities in this order. This ensures that handlers | |
| 95 (which are the ones using the CPU) get enough CPU time to actually | |
| 96 complete their tasks. */ | |
| 97 //#define P_MAIN 0 // This is defined by libc | |
| 98 #define P_MAIN_PROGRAM 1 | |
| 99 #define P_BASE_HANDLER 2 | |
| 100 #define P_BASE_LISTENER (P_BASE_HANDLER+MAX_HANDLERS) | |
| 101 #define P_BASE_CLIENT (P_BASE_LISTENER+N_LISTENERS) | |
| 102 #define P_MAX (P_BASE_CLIENT+N_CLIENTS) | |
| 103 | |
| 104 | |
| 105 #if (CYGNUM_KERNEL_SCHED_PRIORITIES >= (P_MAX)) | |
| 96 | 106 |
| 97 /* if we use the bitmap scheduler we must make sure we don't use the | 107 /* if we use the bitmap scheduler we must make sure we don't use the |
| 98 same priority more than once, so we must store those already in use */ | 108 same priority more than once, so we must store those already in use */ |
| 99 static volatile char priority_in_use[N_MAIN+MAX_HANDLERS+N_LISTENERS+N_CLIENTS]; | 109 static volatile char priority_in_use[P_MAX]; |
| 100 | 110 |
| 101 /* now declare (and allocate space for) some kernel objects, like the | 111 /* now declare (and allocate space for) some kernel objects, like the |
| 102 threads we will use */ | 112 threads we will use */ |
| 103 cyg_thread main_thread_s; | 113 cyg_thread main_thread_s; |
| 104 cyg_thread handler_thread_s[MAX_HANDLERS]; | 114 cyg_thread handler_thread_s[MAX_HANDLERS]; |
| 115 cyg_handle_t mainH; | 125 cyg_handle_t mainH; |
| 116 cyg_handle_t handlerH[MAX_HANDLERS]; | 126 cyg_handle_t handlerH[MAX_HANDLERS]; |
| 117 cyg_handle_t listenerH[N_LISTENERS]; | 127 cyg_handle_t listenerH[N_LISTENERS]; |
| 118 cyg_handle_t clientH[N_CLIENTS]; | 128 cyg_handle_t clientH[N_CLIENTS]; |
| 119 | 129 |
| 130 /* space for thread names */ | |
| 131 char thread_name[P_MAX][20]; | |
| 132 | |
| 120 /* and now variables for the procedure which is the thread */ | 133 /* and now variables for the procedure which is the thread */ |
| 121 cyg_thread_entry_t main_program, client_program, listener_program, | 134 cyg_thread_entry_t main_program, client_program, listener_program, |
| 122 handler_program; | 135 handler_program; |
| 123 | 136 |
| 124 /* a few mutexes used in the code */ | 137 /* a few mutexes used in the code */ |
| 135 /* a global variable with which the client and server coordinate */ | 148 /* a global variable with which the client and server coordinate */ |
| 136 int client_makes_request = 0; | 149 int client_makes_request = 0; |
| 137 | 150 |
| 138 /* indicates that it's time to print out a report */ | 151 /* indicates that it's time to print out a report */ |
| 139 int time_to_report = 0; | 152 int time_to_report = 0; |
| 140 /* print status after a delay of this many secs. */ | 153 /* print status after a delay of this many secs. */ |
| 141 int time_report_delay; | 154 int time_report_delay; |
| 142 | 155 |
| 143 /*** now application-specific variables ***/ | 156 /*** now application-specific variables ***/ |
| 144 /* an array that stores whether the handler threads are in use */ | 157 /* an array that stores whether the handler threads are in use */ |
| 145 int handler_thread_in_use[MAX_HANDLERS]; | 158 int handler_thread_in_use[MAX_HANDLERS]; |
| 168 char *name, /* optional thread name */ | 181 char *name, /* optional thread name */ |
| 169 void *stack_base, /* stack base, NULL = alloc */ | 182 void *stack_base, /* stack base, NULL = alloc */ |
| 170 cyg_ucount32 stack_size, /* stack size, 0 = default */ | 183 cyg_ucount32 stack_size, /* stack size, 0 = default */ |
| 171 cyg_handle_t *handle, /* returned thread handle */ | 184 cyg_handle_t *handle, /* returned thread handle */ |
| 172 cyg_thread *thread /* put thread here */ | 185 cyg_thread *thread /* put thread here */ |
| 173 ); | 186 ); |
| 174 | 187 |
| 175 int get_handler_slot(cyg_handle_t current_threadH); | 188 int get_handler_slot(cyg_handle_t current_threadH); |
| 176 void perform_stressful_tasks(void); | 189 void perform_stressful_tasks(void); |
| 177 void permute_array(char a[], int size, int seed); | 190 void permute_array(char a[], int size, int seed); |
| 178 void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp, | 191 void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp, |
| 189 | 202 |
| 190 /* main launches all the threads of the test */ | 203 /* main launches all the threads of the test */ |
| 191 int | 204 int |
| 192 main(void) | 205 main(void) |
| 193 { | 206 { |
| 194 int i; | 207 int i; |
| 195 | 208 |
| 196 CYG_TEST_INIT(); | 209 CYG_TEST_INIT(); |
| 197 CYG_TEST_INFO("# Entering stress's cyg_user_start() function"); | 210 CYG_TEST_INFO("# Entering stress's cyg_user_start() function"); |
| 198 | 211 |
| 199 cyg_mutex_init(&client_request_lock); | 212 cyg_mutex_init(&client_request_lock); |
| 200 cyg_mutex_init(&statistics_print_lock); | 213 cyg_mutex_init(&statistics_print_lock); |
| 201 cyg_mutex_init(&free_handler_lock); | 214 cyg_mutex_init(&free_handler_lock); |
| 202 | 215 |
| 203 /* initialize statistics */ | 216 /* initialize statistics */ |
| 204 memset(&statistics, 0, sizeof(statistics)); | 217 memset(&statistics, 0, sizeof(statistics)); |
| 205 | 218 |
| 206 /* clear priority table */ | 219 /* clear priority table */ |
| 207 for (i = 0; i < sizeof(priority_in_use); i++) | 220 for (i = 0; i < sizeof(priority_in_use); i++) |
| 208 priority_in_use[i] = 0; | 221 priority_in_use[i] = 0; |
| 209 | 222 |
| 210 /* initialize main thread */ | 223 /* initialize main thread */ |
| 211 { | 224 { |
| 212 char thread_name[] = "main"; | 225 sc_thread_create(P_MAIN_PROGRAM, main_program, (cyg_addrword_t) 0, |
| 213 | 226 "main_program", (void *) main_stack, STACK_SIZE, |
| 214 sc_thread_create(0, main_program, (cyg_addrword_t) 0, | 227 &mainH, &main_thread_s); |
| 215 thread_name, (void *) main_stack, STACK_SIZE, | 228 priority_in_use[P_MAIN_PROGRAM]++; |
| 216 &mainH, &main_thread_s); | 229 } |
| 217 priority_in_use[0]++; | 230 |
| 218 } | 231 /* initialize all handler threads to not be in use */ |
| 219 | 232 for (i = 0; i < MAX_HANDLERS; ++i) { |
| 220 /* initialize all handler threads to not be in use */ | 233 handler_thread_in_use[i] = 0; |
| 221 for (i = 0; i < MAX_HANDLERS; ++i) { | 234 } |
| 222 handler_thread_in_use[i] = 0; | 235 for (i = 0; i < N_LISTENERS; ++i) { |
| 223 } | 236 int prio = P_BASE_LISTENER + i; |
| 224 for (i = 0; i < N_LISTENERS; ++i) { | 237 char* name = &thread_name[prio][0]; |
| 225 int prio; | 238 sprintf(name, "listener-%02d/%02d", i, prio); |
| 226 char thread_name[20]; | 239 sc_thread_create(prio, listener_program, (cyg_addrword_t) i, |
| 227 sprintf(thread_name, "listener-%02d", i); | 240 name, (void *) listener_stack[i], STACK_SIZE, |
| 228 prio = N_MAIN + MAX_HANDLERS + i; | 241 &listenerH[i], &listener_thread_s[i]); |
| 229 sc_thread_create(prio, listener_program, (cyg_addrword_t) i, | 242 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); |
| 230 thread_name, (void *) listener_stack[i], STACK_SIZE, | 243 priority_in_use[prio]++; |
| 231 &listenerH[i], &listener_thread_s[i]); | 244 } |
| 232 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); | 245 for (i = 0; i < N_CLIENTS; ++i) { |
| 233 priority_in_use[prio]++; | 246 int prio = P_BASE_CLIENT + i; |
| 234 } | 247 char* name = &thread_name[prio][0]; |
| 235 for (i = 0; i < N_CLIENTS; ++i) { | 248 sprintf(name, "client-%02d/%02d", i, prio); |
| 236 int prio; | 249 sc_thread_create(prio, client_program, (cyg_addrword_t) i, |
| 237 char thread_name[20]; | 250 name, (void *) client_stack[i], STACK_SIZE, |
| 238 sprintf(thread_name, "client-%02d", i); | 251 &(clientH[i]), &client_thread_s[i]); |
| 239 prio = N_MAIN + MAX_HANDLERS + N_LISTENERS + i; | 252 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); |
| 240 sc_thread_create(prio, client_program, (cyg_addrword_t) i, | 253 priority_in_use[prio]++; |
| 241 thread_name, (void *) client_stack[i], STACK_SIZE, | 254 } |
| 242 &(clientH[i]), &client_thread_s[i]); | 255 |
| 243 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); | 256 cyg_thread_resume(mainH); |
| 244 priority_in_use[prio]++; | 257 for (i = 0; i < N_CLIENTS; ++i) { |
| 245 } | 258 cyg_thread_resume(clientH[i]); |
| 246 | 259 } |
| 247 cyg_thread_resume(mainH); | 260 for (i = 0; i < N_LISTENERS; ++i) { |
| 248 for (i = 0; i < N_CLIENTS; ++i) { | 261 cyg_thread_resume(listenerH[i]); |
| 249 cyg_thread_resume(clientH[i]); | 262 } |
| 250 } | 263 |
| 251 for (i = 0; i < N_LISTENERS; ++i) { | 264 /* set up the alarm which gives periodic wakeups to say "time to |
| 252 cyg_thread_resume(listenerH[i]); | 265 print a report */ |
| 253 } | 266 system_clockH = cyg_real_time_clock(); |
| 254 | 267 cyg_clock_to_counter(system_clockH, &counterH); |
| 255 /* set up the alarm which gives periodic wakeups to say "time to | 268 |
| 256 print a report */ | 269 cyg_alarm_create(counterH, report_alarm_func, |
| 257 system_clockH = cyg_real_time_clock(); | 270 (cyg_addrword_t) 4000, |
| 258 cyg_clock_to_counter(system_clockH, &counterH); | 271 &report_alarmH, &report_alarm); |
| 259 | 272 if (cyg_test_is_simulator) { |
| 260 cyg_alarm_create(counterH, report_alarm_func, | 273 time_report_delay = 2; |
| 261 (cyg_addrword_t) 4000, | 274 } else { |
| 262 &report_alarmH, &report_alarm); | 275 time_report_delay = 30; |
| 263 if (cyg_test_is_simulator) { | 276 } |
| 264 time_report_delay = 2; | 277 |
| 265 } else { | 278 cyg_alarm_initialize(report_alarmH, cyg_current_time()+200, |
| 266 time_report_delay = 30; | 279 time_report_delay*100); |
| 267 } | 280 |
| 268 | 281 return 0; |
| 269 cyg_alarm_initialize(report_alarmH, cyg_current_time()+200, | |
| 270 time_report_delay*100); | |
| 271 } | 282 } |
| 272 | 283 |
| 273 /* main_program() -- frees resources and prints status. */ | 284 /* main_program() -- frees resources and prints status. */ |
| 274 void main_program(cyg_addrword_t data) | 285 void main_program(cyg_addrword_t data) |
| 275 { | 286 { |
| 338 } | 349 } |
| 339 | 350 |
| 340 /* client_program() -- an obnoxious client which makes a lot of requests */ | 351 /* client_program() -- an obnoxious client which makes a lot of requests */ |
| 341 void client_program(cyg_addrword_t data) | 352 void client_program(cyg_addrword_t data) |
| 342 { | 353 { |
| 343 int delay; | 354 int delay; |
| 344 | 355 |
| 345 printf("# Starting client-%d\n", (int) data); | 356 printf("# Starting client-%d\n", (int) data); |
| 346 | 357 |
| 347 system_clockH = cyg_real_time_clock(); | 358 system_clockH = cyg_real_time_clock(); |
| 348 cyg_clock_to_counter(system_clockH, &counterH); | 359 cyg_clock_to_counter(system_clockH, &counterH); |
| 349 | 360 |
| 350 for (;;) { | 361 for (;;) { |
| 351 delay = (rand() % 20); | 362 delay = (rand() % 20); |
| 352 | 363 |
| 353 /* now send a request to the server */ | 364 /* now send a request to the server */ |
| 354 cyg_mutex_lock(&client_request_lock); { | 365 cyg_mutex_lock(&client_request_lock); { |
| 355 ++client_makes_request; | 366 ++client_makes_request; |
| 356 /* printf("client_makes_request %d\n", client_makes_request); */ | 367 /* printf("client_makes_request %d\n", client_makes_request); */ |
| 357 } cyg_mutex_unlock(&client_request_lock); | 368 } cyg_mutex_unlock(&client_request_lock); |
| 358 | 369 |
| 359 cyg_thread_delay(10+delay); | 370 cyg_thread_delay(10+delay); |
| 360 /* cyg_thread_delay(0); */ | 371 /* cyg_thread_delay(0); */ |
| 361 } | 372 } |
| 362 } | 373 } |
| 363 | 374 |
| 364 /* listener_program() -- listens for a request and spawns a handler to | 375 /* listener_program() -- listens for a request and spawns a handler to |
| 365 take care of the request */ | 376 take care of the request */ |
| 366 void listener_program(cyg_addrword_t data) | 377 void listener_program(cyg_addrword_t data) |
| 379 } | 390 } |
| 380 } cyg_mutex_unlock(&client_request_lock); | 391 } cyg_mutex_unlock(&client_request_lock); |
| 381 | 392 |
| 382 if (make_request) { | 393 if (make_request) { |
| 383 int prio; | 394 int prio; |
| 395 char* name; | |
| 384 /* printf("just got a request from a client (count = %d)\n", */ | 396 /* printf("just got a request from a client (count = %d)\n", */ |
| 385 /* client_makes_request); */ | 397 /* client_makes_request); */ |
| 386 | 398 |
| 387 handler_slot = get_handler_slot(listenerH[(int) data]); | 399 handler_slot = get_handler_slot(listenerH[(int) data]); |
| 388 prio = N_MAIN+handler_slot; | 400 prio = P_BASE_HANDLER+handler_slot; |
| 401 | |
| 402 name = &thread_name[prio][0]; | |
| 403 sprintf(name, "handler-%02d/%02d", handler_slot, prio); | |
| 389 | 404 |
| 390 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); | 405 CYG_ASSERT(0 == priority_in_use[prio], "Priority already in use!"); |
| 391 priority_in_use[prio]++; | 406 priority_in_use[prio]++; |
| 392 sc_thread_create(prio, handler_program, | 407 sc_thread_create(prio, handler_program, |
| 393 (cyg_addrword_t) handler_slot, | 408 (cyg_addrword_t) handler_slot, |
| 394 "handler", (void *) handler_stack[handler_slot], | 409 name, (void *) handler_stack[handler_slot], |
| 395 STACK_SIZE2, &handlerH[handler_slot], | 410 STACK_SIZE2, &handlerH[handler_slot], |
| 396 &handler_thread_s[handler_slot]); | 411 &handler_thread_s[handler_slot]); |
| 397 cyg_thread_resume(handlerH[handler_slot]); | 412 cyg_thread_resume(handlerH[handler_slot]); |
| 398 ++statistics.handler_invocation_histogram[handler_slot]; | 413 ++statistics.handler_invocation_histogram[handler_slot]; |
| 399 } | 414 } |
| 403 } | 418 } |
| 404 | 419 |
| 405 /* handler_program() -- is spawned to handle each incoming request */ | 420 /* handler_program() -- is spawned to handle each incoming request */ |
| 406 void handler_program(cyg_addrword_t data) | 421 void handler_program(cyg_addrword_t data) |
| 407 { | 422 { |
| 408 /* here is where we perform specific stressful tasks */ | 423 /* here is where we perform specific stressful tasks */ |
| 409 perform_stressful_tasks(); | 424 perform_stressful_tasks(); |
| 410 | 425 |
| 411 cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000))))); | 426 cyg_thread_delay(4 + (int) (0.5*log(1.0 + fabs((rand() % 1000000))))); |
| 412 /* cyg_thread_delay(0); */ | 427 /* cyg_thread_delay(0); */ |
| 413 | 428 |
| 414 ++statistics.thread_exits; | 429 ++statistics.thread_exits; |
| 415 { | 430 { |
| 416 // Loop until the handler id and priority can be communicated to | 431 // Loop until the handler id and priority can be communicated to |
| 417 // the main_program. | 432 // the main_program. |
| 418 int freed = 0; | 433 int freed = 0; |
| 419 do { | 434 do { |
| 420 cyg_mutex_lock(&free_handler_lock); { | 435 cyg_mutex_lock(&free_handler_lock); { |
| 421 if (-1 == free_handler_id) { | 436 if (-1 == free_handler_id) { |
| 422 free_handler_id = data; | 437 free_handler_id = data; |
| 423 free_handler_pri = N_MAIN+(int) data; | 438 free_handler_pri = P_BASE_HANDLER+(int) data; |
| 424 freed = 1; | 439 freed = 1; |
| 425 } | 440 } |
| 426 } cyg_mutex_unlock(&free_handler_lock); | 441 } cyg_mutex_unlock(&free_handler_lock); |
| 427 if (!freed) | 442 if (!freed) |
| 428 cyg_thread_delay(2); | 443 cyg_thread_delay(2); |
| 429 } while (!freed); | 444 } while (!freed); |
| 430 } | 445 } |
| 431 | 446 |
| 432 // Then exit. | 447 // Then exit. |
| 433 cyg_thread_exit(); | 448 cyg_thread_exit(); |
| 434 } | 449 } |
| 435 | 450 |
| 436 /* look for an available handler thread */ | 451 /* look for an available handler thread */ |
| 437 int get_handler_slot(cyg_handle_t current_threadH) | 452 int get_handler_slot(cyg_handle_t current_threadH) |
| 438 { | 453 { |
| 461 /* do things which will stress the system */ | 476 /* do things which will stress the system */ |
| 462 void perform_stressful_tasks() | 477 void perform_stressful_tasks() |
| 463 { | 478 { |
| 464 #define MAX_MALLOCED_SPACES 100 /* do this many mallocs at most */ | 479 #define MAX_MALLOCED_SPACES 100 /* do this many mallocs at most */ |
| 465 #define MALLOCED_BASE_SIZE 1 /* basic size in bytes */ | 480 #define MALLOCED_BASE_SIZE 1 /* basic size in bytes */ |
| 466 char *spaces[MAX_MALLOCED_SPACES]; | 481 char *spaces[MAX_MALLOCED_SPACES]; |
| 467 unsigned int i; | 482 unsigned int i; |
| 468 | 483 |
| 469 cyg_mutex_t tmp_lock; | 484 cyg_mutex_t tmp_lock; |
| 470 | 485 |
| 471 cyg_uint8 pool_space[10][100]; | 486 cyg_uint8 pool_space[10][100]; |
| 472 cyg_handle_t mempool_handles[10]; | 487 cyg_handle_t mempool_handles[10]; |
| 473 cyg_mempool_fix mempool_objects[10]; | 488 cyg_mempool_fix mempool_objects[10]; |
| 474 | 489 |
| 475 cyg_mutex_init(&tmp_lock); | 490 cyg_mutex_init(&tmp_lock); |
| 476 | 491 |
| 477 /* here I use malloc, which uses the kernel's variable memory pools. | 492 /* here I use malloc, which uses the kernel's variable memory pools. |
| 478 note that malloc/free is a bit simple-minded here: it does not | 493 note that malloc/free is a bit simple-minded here: it does not |
| 479 try to really fragment things, and it does not try to make the | 494 try to really fragment things, and it does not try to make the |
| 480 allocation/deallocation concurrent with other thread execution | 495 allocation/deallocation concurrent with other thread execution |
| 481 (although I'm about to throw in a yield()) */ | 496 (although I'm about to throw in a yield()) */ |
| 482 for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { | 497 for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { |
| 483 ++statistics.malloc_tries; | 498 ++statistics.malloc_tries; |
| 484 /* spaces[i] = (char *) malloc(((int)(sqrt(i*2.0))+1)*MALLOCED_BASE_SIZE); */ | 499 /* spaces[i] = (char *) malloc(((int)(sqrt(i*2.0))+1)*MALLOCED_BASE_SIZE); */ |
| 485 spaces[i] = (char *) malloc(((int)i*2.0+1)*MALLOCED_BASE_SIZE); | 500 spaces[i] = (char *) malloc(((int)i*2.0+1)*MALLOCED_BASE_SIZE); |
| 486 if (i % (MAX_MALLOCED_SPACES/10) == 0) { | 501 if (i % (MAX_MALLOCED_SPACES/10) == 0) { |
| 487 cyg_thread_yield(); | 502 cyg_thread_yield(); |
| 488 } | 503 } |
| 489 if (i % (MAX_MALLOCED_SPACES/15) == 0) { | 504 if (i % (MAX_MALLOCED_SPACES/15) == 0) { |
| 490 cyg_thread_delay(i % 5); | 505 cyg_thread_delay(i % 5); |
| 491 } | 506 } |
| 492 } | 507 } |
| 493 | 508 |
| 494 /* now free it all up */ | 509 /* now free it all up */ |
| 495 for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { | 510 for (i = 0; i < MAX_MALLOCED_SPACES; ++i) { |
| 496 if (spaces[i] != NULL) { | 511 if (spaces[i] != NULL) { |
| 497 unsigned int j; | 512 unsigned int j; |
| 498 for (j = 0; j < (i*2+1)*MALLOCED_BASE_SIZE; ++j) { | 513 for (j = 0; j < (i*2+1)*MALLOCED_BASE_SIZE; ++j) { |
| 499 spaces[i][j] = 0xAA; /* write a bit pattern */ | 514 spaces[i][j] = 0xAA; /* write a bit pattern */ |
| 500 } | 515 } |
| 501 free(spaces[i]); | 516 free(spaces[i]); |
| 502 } else { | 517 } else { |
| 503 ++statistics.malloc_failures; | 518 ++statistics.malloc_failures; |
| 504 } | 519 } |
| 505 } | 520 } |
| 506 /* now allocate and then free some fixed-size memory pools; for | 521 /* now allocate and then free some fixed-size memory pools; for |
| 507 now this is simple-minded because it does not have many threads | 522 now this is simple-minded because it does not have many threads |
| 508 sharing the memory pools and racing for memory. */ | 523 sharing the memory pools and racing for memory. */ |
| 509 for (i = 0; i < 10; ++i) { | 524 for (i = 0; i < 10; ++i) { |
| 510 cyg_mempool_fix_create(pool_space[i], 100, (i+1)*3, | 525 cyg_mempool_fix_create(pool_space[i], 100, (i+1)*3, |
| 511 &mempool_handles[i], &mempool_objects[i]); | 526 &mempool_handles[i], &mempool_objects[i]); |
| 512 } | 527 } |
| 513 | 528 |
| 514 for (i = 0; i < 10; ++i) { | 529 for (i = 0; i < 10; ++i) { |
| 515 spaces[i] = cyg_mempool_fix_try_alloc(mempool_handles[i]); | 530 spaces[i] = cyg_mempool_fix_try_alloc(mempool_handles[i]); |
| 516 } | 531 } |
| 517 | 532 |
| 518 for (i = 0; i < 10; ++i) { | 533 for (i = 0; i < 10; ++i) { |
| 519 if (spaces[i]) { | 534 if (spaces[i]) { |
| 520 cyg_mempool_fix_delete(mempool_handles[i]); | 535 cyg_mempool_fix_delete(mempool_handles[i]); |
| 521 } | 536 } |
| 522 } | 537 } |
| 523 | 538 |
| 524 cyg_mutex_destroy(&tmp_lock); | 539 cyg_mutex_destroy(&tmp_lock); |
| 525 } | 540 } |
| 526 | 541 |
| 527 /* report_alarm_func() is invoked as an alarm handler, so it should be | 542 /* report_alarm_func() is invoked as an alarm handler, so it should be |
| 528 quick and simple. in this case it sets a global flag which is | 543 quick and simple. in this case it sets a global flag which is |
| 529 checked by main_program. */ | 544 checked by main_program. */ |
| 536 /* this sets up death alarms. it gets the handle and alarm from the | 551 /* this sets up death alarms. it gets the handle and alarm from the |
| 537 caller, since they must persist for the life of the alarm */ | 552 caller, since they must persist for the life of the alarm */ |
| 538 void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp, | 553 void setup_death_alarm(cyg_addrword_t data, cyg_handle_t *deathHp, |
| 539 cyg_alarm *death_alarm_p, int *killed_p) | 554 cyg_alarm *death_alarm_p, int *killed_p) |
| 540 { | 555 { |
| 541 cyg_handle_t system_clockH, counterH; | 556 cyg_handle_t system_clockH, counterH; |
| 542 cyg_resolution_t rtc_res; | 557 cyg_resolution_t rtc_res; |
| 543 | 558 |
| 544 system_clockH = cyg_real_time_clock(); | 559 system_clockH = cyg_real_time_clock(); |
| 545 cyg_clock_to_counter(system_clockH, &counterH); | 560 cyg_clock_to_counter(system_clockH, &counterH); |
| 546 | 561 |
| 547 cyg_alarm_create(counterH, death_alarm_func, | 562 cyg_alarm_create(counterH, death_alarm_func, |
| 548 (cyg_addrword_t) killed_p, | 563 (cyg_addrword_t) killed_p, |
| 549 deathHp, death_alarm_p); | 564 deathHp, death_alarm_p); |
| 550 rtc_res = cyg_clock_get_resolution(system_clockH); | 565 rtc_res = cyg_clock_get_resolution(system_clockH); |
| 551 { | 566 { |
| 552 cyg_tick_count_t tick_delay; | 567 cyg_tick_count_t tick_delay; |
| 553 tick_delay = (long long) | 568 tick_delay = (long long) |
| 554 ((1000000000.0*rtc_res.divisor) | 569 ((1000000000.0*rtc_res.divisor) |
| 555 *((double)DEATH_TIME_LIMIT)/((double)rtc_res.dividend)); | 570 *((double)DEATH_TIME_LIMIT)/((double)rtc_res.dividend)); |
| 556 if ( cyg_test_is_simulator ) | 571 if ( cyg_test_is_simulator ) |
| 557 tick_delay /= 10; | 572 tick_delay /= 10; |
| 558 #ifdef CYGPKG_HAL_I386_LINUX | 573 #ifdef CYGPKG_HAL_I386_LINUX |
| 559 // 20 seconds is a long time compared to the run time of other tests. | 574 // 20 seconds is a long time compared to the run time of other tests. |
| 560 // Reduce to 10 seconds, allowing more tests to get run. | 575 // Reduce to 10 seconds, allowing more tests to get run. |
| 561 tick_delay /= 2; | 576 tick_delay /= 2; |
| 562 #endif | 577 #endif |
| 563 | 578 |
| 564 cyg_alarm_initialize(*deathHp, cyg_current_time() + tick_delay, 0); | 579 cyg_alarm_initialize(*deathHp, cyg_current_time() + tick_delay, 0); |
| 565 } | 580 } |
| 566 } | 581 } |
| 567 #endif | 582 #endif |
| 568 | 583 |
| 569 /* death_alarm_func() is the alarm handler that kills the current | 584 /* death_alarm_func() is the alarm handler that kills the current |
| 570 thread after a specified timeout. It does so by setting a flag the | 585 thread after a specified timeout. It does so by setting a flag the |
| 571 thread is constantly checking. */ | 586 thread is constantly checking. */ |
| 572 void death_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data) | 587 void death_alarm_func(cyg_handle_t alarmH, cyg_addrword_t data) |
| 573 { | 588 { |
| 574 int *killed_p; | 589 int *killed_p; |
| 575 killed_p = (int *) data; | 590 killed_p = (int *) data; |
| 576 *killed_p = 1; | 591 *killed_p = 1; |
| 577 } | 592 } |
| 578 | 593 |
| 579 /* now I write the sc_ versions of the cyg_functions */ | 594 /* now I write the sc_ versions of the cyg_functions */ |
| 580 void sc_thread_create( | 595 void sc_thread_create( |
| 581 cyg_addrword_t sched_info, /* scheduling info (eg pri) */ | 596 cyg_addrword_t sched_info, /* scheduling info (eg pri) */ |
| 584 char *name, /* optional thread name */ | 599 char *name, /* optional thread name */ |
| 585 void *stack_base, /* stack base, NULL = alloc */ | 600 void *stack_base, /* stack base, NULL = alloc */ |
| 586 cyg_ucount32 stack_size, /* stack size, 0 = default */ | 601 cyg_ucount32 stack_size, /* stack size, 0 = default */ |
| 587 cyg_handle_t *handle, /* returned thread handle */ | 602 cyg_handle_t *handle, /* returned thread handle */ |
| 588 cyg_thread *thread /* put thread here */ | 603 cyg_thread *thread /* put thread here */ |
| 589 ) | 604 ) |
| 590 { | 605 { |
| 591 /*printf("Creating a thread -- priority is %lu\n", (unsigned long) sched_info);*/ | 606 /*printf("Creating a thread -- priority is %lu\n", (unsigned long) sched_info);*/ |
| 592 /* fflush(stdout); */ | 607 /* fflush(stdout); */ |
| 593 ++statistics.thread_creations; | 608 ++statistics.thread_creations; |
| 594 cyg_thread_create(sched_info, entry, entry_data, name, | 609 cyg_thread_create(sched_info, entry, entry_data, name, |
| 595 stack_base, stack_size, handle, thread); | 610 stack_base, stack_size, handle, thread); |
| 611 | |
| 612 CYG_ASSERT(cyg_thread_get_priority(*handle) == (cyg_priority_t) sched_info, | |
| 613 "Didn't get requested priority!"); | |
| 596 } | 614 } |
| 597 | 615 |
| 598 | 616 |
| 599 void print_statistics(int print_full) | 617 void print_statistics(int print_full) |
| 600 { | 618 { |
| 601 int i; | 619 int i; |
| 602 static int print_count = 0; | 620 static int print_count = 0; |
| 603 | 621 |
| 604 printf("State dump %d (time %02d.%02d.%02d)\n", | 622 printf("State dump %d (time %02d.%02d.%02d)\n", |
| 605 print_count, | 623 print_count, |
| 606 print_count*time_report_delay / (60*60), // hours | 624 print_count*time_report_delay / (60*60), // hours |
| 607 (print_count*time_report_delay / 60) % 60, // minutes | 625 (print_count*time_report_delay / 60) % 60, // minutes |
| 608 (print_count*time_report_delay ) % 60); // seconds | 626 (print_count*time_report_delay ) % 60); // seconds |
| 609 print_count++; | 627 print_count++; |
| 610 | 628 |
| 611 cyg_mutex_lock(&statistics_print_lock); { | 629 cyg_mutex_lock(&statistics_print_lock); { |
| 612 printf(" Handler-invocations: "); | 630 printf(" Handler-invocations: "); |
| 613 for (i = 0; i < MAX_HANDLERS; ++i) { | 631 for (i = 0; i < MAX_HANDLERS; ++i) { |
| 614 printf("%4lu ", statistics.handler_invocation_histogram[i]); | 632 printf("%4lu ", statistics.handler_invocation_histogram[i]); |
| 615 } | 633 } |
| 616 printf("\n"); | 634 printf("\n"); |
| 617 printf(" malloc()-tries/failures: -- %7lu %7lu\n", | 635 printf(" malloc()-tries/failures: -- %7lu %7lu\n", |
| 618 statistics.malloc_tries, statistics.malloc_failures); | 636 statistics.malloc_tries, statistics.malloc_failures); |
| 619 printf(" client_makes_request: %d\n", client_makes_request); | 637 printf(" client_makes_request: %d\n", client_makes_request); |
| 620 } cyg_mutex_unlock(&statistics_print_lock); | 638 } cyg_mutex_unlock(&statistics_print_lock); |
| 621 | 639 |
| 622 // Add: Also occasionally dump individual threads' stack status. | 640 // Add: Also occasionally dump individual threads' stack status. |
| 623 if (0 == print_count % 5 || print_full) { | 641 if (0 == print_count % 5 || print_full) { |
| 624 cyg_test_dump_interrupt_stack_stats( " Status" ); | 642 cyg_test_dump_interrupt_stack_stats( " Status" ); |
| 625 cyg_test_dump_idlethread_stack_stats( " Status" ); | 643 cyg_test_dump_idlethread_stack_stats( " Status" ); |
| 626 } | 644 } |
| 627 } | 645 } |
| 628 | 646 |
| 629 #else /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */ | 647 #else /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */ |
| 630 /* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ | 648 /* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ |
| 631 #define N_A_MSG "not enough priorities available" | 649 #define N_A_MSG "not enough priorities available" |
| 632 #endif /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */ | 650 #endif /* (CYGNUM_KERNEL_SCHED_PRIORITIES >= */ |
| 633 /* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ | 651 /* (N_MAIN+N_CLIENTS+N_LISTENERS+MAX_HANDLERS)) */ |
| 634 | 652 |
| 635 #else /* CYGSEM_LIBC_MALLOC */ | 653 #else /* CYGSEM_LIBC_MALLOC */ |
| 636 # define N_A_MSG "this test needs malloc" | 654 # define N_A_MSG "this test needs malloc" |
| 637 #endif /* CYGSEM_LIBC_MALLOC */ | 655 #endif /* CYGSEM_LIBC_MALLOC */ |
| 638 | 656 |
