/* * COPYRIGHT (c) 1989-2012. * On-Line Applications Research Corporation (OAR). * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.com/license/LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include /* forward declarations to avoid warnings */ rtems_task Init(rtems_task_argument argument); rtems_task subtask(rtems_task_argument arg); rtems_task Task_variable_deleter(rtems_task_argument ignored); void starttask(int arg); void test_errors(void); void test_dtor(void *pointer); void test_multiple_taskvars(void); void test_out_of_memory(void); rtems_task Other_Task(rtems_task_argument ignored); void test_delete_from_other_task(void); void test_delete_as_side_effect(void); volatile void *taskvar; volatile int nRunning; volatile int nDeleted; rtems_task subtask (rtems_task_argument arg) { uintptr_t localvar = arg; int i; rtems_status_code sc; nRunning++; while (nRunning != 3) rtems_task_wake_after (0); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar, NULL); directive_failed( sc, "task variable add" ); taskvar = (void *)localvar; while (localvar < 1000) { localvar++; rtems_task_wake_after (0); taskvar = (void *)((uintptr_t)taskvar + 1); rtems_task_wake_after (0); if ((uintptr_t)taskvar != localvar) { printf( "Task:%" PRIdrtems_task_argument " taskvar:%" PRIuPTR " localvar:%" PRIuPTR "\n", arg, (uintptr_t)taskvar, localvar ); rtems_task_suspend (RTEMS_SELF); } } sc = rtems_task_variable_delete(RTEMS_SELF, (void **)&taskvar); nDeleted++; directive_failed( sc, "task variable delete" ); if ((uintptr_t)taskvar == localvar) { printf( "Task:%" PRIdrtems_task_argument " deleted taskvar:%" PRIuPTR " localvar:%" PRIuPTR "\n", arg, (uintptr_t)taskvar, localvar ); nRunning--; rtems_task_suspend (RTEMS_SELF); } while (nDeleted != 3) rtems_task_wake_after (0); for (i = 0 ; i < 1000 ; i++) { taskvar = (void *)(localvar = 100 * arg); rtems_task_wake_after(0); if (nRunning <= 1) break; if ((uintptr_t)taskvar == localvar) { printf( "Task:%" PRIdrtems_task_argument " taskvar:%" PRIuPTR " localvar:%" PRIuPTR "\n", arg, (uintptr_t)taskvar, localvar ); nRunning--; rtems_task_suspend(RTEMS_SELF); } } nRunning--; while (nRunning) rtems_task_wake_after(0); puts("*** END OF TEST 28 ***" ); rtems_test_exit(0); } void starttask (int arg) { rtems_id tid; rtems_status_code sc; sc = rtems_task_create(rtems_build_name ('S', 'R', 'V', arg + 'A'), RTEMS_MAXIMUM_PRIORITY - 1u, RTEMS_MINIMUM_STACK_SIZE, RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0), RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL, &tid ); directive_failed( sc, "task create" ); sc = rtems_task_start(tid, subtask, arg); directive_failed( sc, "task start" ); } volatile void *taskvar1; volatile void *taskvar2; volatile void *taskvar3; void test_errors(void) { rtems_status_code sc; void *value; /* * task variable add error status codes */ puts( "task variable add - NULL pointer - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_add(RTEMS_SELF, NULL, NULL ); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "add NULL pointer" ); /* * task variable get error status codes */ puts( "task variable get - bad Id - RTEMS_INVALID_ID" ); sc = rtems_task_variable_get( rtems_task_self() + 10, (void **)&taskvar1, &value ); fatal_directive_status( sc, RTEMS_INVALID_ID, "bad Id" ); puts( "task variable get - NULL pointer - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_get(RTEMS_SELF, NULL, &value ); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "get NULL pointer" ); puts( "task variable get - bad result - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_get(RTEMS_SELF, (void **)&taskvar1, NULL); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "get bad result" ); puts( "task variable get - bad pointer - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_get(RTEMS_SELF, (void **)&taskvar1, &value); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "get bad pointer" ); /* * task variable delete error status codes */ puts( "task variable delete - bad Id - RTEMS_INVALID_ID" ); sc = rtems_task_variable_delete( rtems_task_self() + 10, (void **)&taskvar1 ); fatal_directive_status( sc, RTEMS_INVALID_ID, "bad Id" ); puts( "task variable delete - NULL pointer - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_delete(RTEMS_SELF, NULL); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "delete NULL pointer" ); puts( "task variable delete - bad pointer - RTEMS_INVALID_ADDRESS" ); sc = rtems_task_variable_delete(RTEMS_SELF, (void **)&taskvar1); fatal_directive_status( sc, RTEMS_INVALID_ADDRESS, "delete bad pointer" ); } volatile uint32_t test_dtor_ran; void test_dtor(void *pointer) { test_dtor_ran++; } void test_multiple_taskvars(void) { rtems_status_code sc; void *value; test_dtor_ran = 0; /* * Add multiple task variables and add each twice to * verify that behavior is OK */ puts( "task variable add - bad Id - RTEMS_INVALID_ID" ); sc = rtems_task_variable_add( rtems_task_self() + 10, (void **)&taskvar1, NULL ); fatal_directive_status( sc, RTEMS_INVALID_ID, "bad Id" ); puts( "Adding multiple task variables" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar1, NULL); directive_failed( sc, "add multiple #1" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar1, test_dtor); directive_failed( sc, "add multiple #2" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar2, test_dtor); directive_failed( sc, "add multiple #3" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar2, NULL); directive_failed( sc, "add multiple #4" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar3, NULL); directive_failed( sc, "add multiple #5" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar3, test_dtor); directive_failed( sc, "add multiple #6" ); /* * Obtain task variables in various spots on the chain */ puts( "Obtaining multiple task variables" ); sc = rtems_task_variable_get( RTEMS_SELF, (void **)&taskvar3, &value ); directive_failed( sc, "get multiple #1" ); sc = rtems_task_variable_get( RTEMS_SELF, (void **)&taskvar2, &value ); directive_failed( sc, "get multiple #2" ); sc = rtems_task_variable_get( RTEMS_SELF, (void **)&taskvar1, &value ); directive_failed( sc, "get multiple #2" ); /* * Delete task variables in various spots on the chain */ /* to trip the destructors */ taskvar1 = (void *)1; taskvar2 = (void *)2; taskvar3 = (void *)3; puts( "Deleting multiple task variables" ); sc = rtems_task_variable_delete(RTEMS_SELF, (void **)&taskvar2); directive_failed( sc, "delete multiple #1" ); sc = rtems_task_variable_delete(RTEMS_SELF, (void **)&taskvar3); directive_failed( sc, "delete multiple #2" ); sc = rtems_task_variable_delete(RTEMS_SELF, (void **)&taskvar1); directive_failed( sc, "delete multiple #3" ); if ( test_dtor_ran != 2 ) { printf( "Test dtor ran %" PRIu32 " times not 2 times as expected\n", test_dtor_ran ); rtems_test_exit(0); } } #define MAX_VARS 4096 void *Pointers[MAX_VARS]; void test_out_of_memory(void) { int i; int max; rtems_status_code sc; int ran_out = 0; void **base; base = Pointers; for (i=0 ; i