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

📄 stress_threads.c

📁 eCos/RedBoot for勤研ARM AnywhereII(4510) 含全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
{
    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++;
        } 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 = 0;
    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 /= SIM_DELAY_DIVISOR;
#ifdef CYGPKG_HAL_SYNTH
        // 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)

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);

#if CYGINT_ISO_MALLINFO
    //--------------------------------
    // System information
    {
        struct mallinfo mem_info;
       
        mem_info = mallinfo();
        
        printf(" Memory system: Total=0x%08x Free=0x%08x Max=0x%08x\n", 
               mem_info.arena, mem_info.fordblks, mem_info.maxfree);
    }
#endif

    // 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 /* CYGINT_ISO_MALLOC */
# define N_A_MSG "this test needs malloc"
#endif /* CYGINT_ISO_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 /* CYGINT_ISO_STDIO_FORMATTED_IO */
# define N_A_MSG "this test needs stdio formatted I/O"
#endif /* CYGINT_ISO_STDIO_FORMATTED_IO */

#else // def CYGFUN_KERNEL_API_C
# define N_A_MSG "this test needs Kernel C API"
#endif

#else // def CYGPKG_KERNEL && CYGPKG_IO && CYGPKG_ISOINFRA
# define N_A_MSG "this tests needs Kernel, isoinfra and IO"
#endif

#ifdef N_A_MSG
externC void
cyg_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 + -