/* * Task which adds task variables just to delete them */ rtems_task Task_variable_deleter(rtems_task_argument ignored) { rtems_status_code sc; puts( "Adding multiple task variables to delete implicitly" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar1, test_dtor); directive_failed( sc, "add multiple for delete #1" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar2, NULL); directive_failed( sc, "add multiple for delete #2" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar3, test_dtor); directive_failed( sc, "add multiple for delete #3" ); (void) rtems_task_delete( RTEMS_SELF ); }
int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *)) { rtems_status_code status; /* Ok, this can be a bit tricky. We are going to return a "key" as a * pointer to the buffer that will hold the value of the key itself. * We have to to this, because the others functions on this interface * deal with the value of the key, as used with the POSIX API. */ /* Do not pull your hair, trust me this works. :-) */ __gthread_key_t new_key = (__gthread_key_t) malloc( sizeof( *new_key ) ); *key = new_key; new_key->val = NULL; new_key->dtor = dtor; #ifdef DEBUG_GXX_WRAPPERS printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key ); #endif /* register with RTEMS the buffer that will hold the key values */ status = rtems_task_variable_add( RTEMS_SELF, (void **)new_key, dtor ); if ( status == RTEMS_SUCCESSFUL ) return 0; free( new_key ); return -1; }
void *rtems_gxx_getspecific(__gthread_key_t key) { rtems_status_code status; void *p= 0; /* register with RTEMS the buffer that will hold the key values */ status = rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ); if ( status == RTEMS_SUCCESSFUL ) { /* We do not have to do this, but what the heck ! */ p= key->val; } else { /* fisrt time, always set to zero, it is unknown the value that the others * threads are using at the moment of this call */ status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ); if ( status != RTEMS_SUCCESSFUL ) { _Internal_error_Occurred( INTERNAL_ERROR_CORE, true, INTERNAL_ERROR_GXX_KEY_ADD_FAILED ); } key->val = (void *)0; } #ifdef DEBUG_GXX_WRAPPERS printk( "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n", key, p, rtems_task_self() ); #endif return p; }
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<MAX_VARS ; i++ ) { sc = rtems_task_variable_add(RTEMS_SELF, &base[i], NULL); if ( sc == RTEMS_NO_MEMORY ) { puts( "task_variable_add - returns NO_MEMORY" ); max = i; ran_out = 1; break; } directive_failed( sc, "add loop until out of memory" ); } if ( !ran_out ) { puts( "ERROR!!! did not run out of memory adding task variables!" ); rtems_test_exit(0); } for (i=0 ; i<max ; i++ ) { sc = rtems_task_variable_delete(RTEMS_SELF, &base[i]); directive_failed( sc, "delete loop until out of memory" ); } }
void test_delete_from_other_task(void) { rtems_status_code sc; test_dtor_ran = 0; sc = rtems_task_ident( RTEMS_SELF, 0, &main_task ); directive_failed( sc, "task ident" ); sc = rtems_task_variable_add(RTEMS_SELF, (void **)&taskvar1, test_dtor); directive_failed( sc, "add for other task case" ); sc = rtems_task_create(rtems_build_name ('O', 'T', 'H', 'R'), 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, &other_task ); directive_failed( sc, "task create other" ); sc = rtems_task_start(other_task, Other_Task, 0); directive_failed( sc, "task start other" ); rtems_task_wake_after( 100 ); if ( test_dtor_ran != 1 ) { printf( "Test dtor ran %" PRIu32 " times not 1 times as expected\n", test_dtor_ran ); rtems_test_exit(0); } }
/* * Set up per-task RPC variables */ int rtems_rpc_task_init (void) { rtems_status_code sc; struct _rtems_rpc_task_variables *tvp; if (rtems_rpc_task_variables == &rpc_default) { tvp = malloc (sizeof *tvp); if (tvp == NULL) return RTEMS_NO_MEMORY; /* * FIXME: Should have destructor which cleans up * all RPC stuff: * - Close all files * - Go through and free linked list elements * - Free other allocated memory (e.g. clnt_perror_buf) */ sc = rtems_task_variable_add ( RTEMS_SELF, (void *)&rtems_rpc_task_variables, NULL); if (sc != RTEMS_SUCCESSFUL) { free (tvp); return sc; } *tvp = rpc_init; rtems_rpc_task_variables = tvp; } return RTEMS_SUCCESSFUL; }
BSP_ExceptionExtension BSP_exceptionHandlerInstall(BSP_ExceptionExtension e) { volatile BSP_ExceptionExtension test; if ( RTEMS_SUCCESSFUL != rtems_task_variable_get(RTEMS_SELF, (void*)&BSP_exceptionExtension, (void**)&test) ) { /* not yet added */ rtems_task_variable_add(RTEMS_SELF, (void*)&BSP_exceptionExtension, 0); } test = BSP_exceptionExtension; BSP_exceptionExtension = e; return test; }
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" ); }
rtems_status_code rtems_libio_set_private_env(void) { rtems_status_code sc; rtems_id task_id; rtems_filesystem_location_info_t loc; sc=rtems_task_ident(RTEMS_SELF,0,&task_id); if (sc != RTEMS_SUCCESSFUL) return sc; /* Only for the first time a malloc is necesary */ if (rtems_current_user_env==&rtems_global_user_env) { rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t)); if (!tmp) return RTEMS_NO_MEMORY; #ifdef HAVE_USERENV_REFCNT tmp->refcnt = 1; #endif sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,(void(*)(void *))free_user_env); if (sc != RTEMS_SUCCESSFUL) { /* don't use free_user_env because the pathlocs are * not initialized yet */ free(tmp); return sc; } rtems_current_user_env = tmp; }; *rtems_current_user_env = rtems_global_user_env; /* get the global values*/ rtems_current_user_env->task_id=task_id; /* mark the local values*/ /* Clone the pathlocs. In contrast to most other * code we must _not_ free the original locs because * what we are trying to do here is forking off * clones. The reason is a pathloc can be allocated by the * file system and needs to be freed when deleting the environment. */ rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0); rtems_filesystem_root = loc; rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0); rtems_filesystem_current = loc; return RTEMS_SUCCESSFUL; }
rtems_status_code rtems_libio_share_private_env(rtems_id task_id) { rtems_status_code sc; rtems_user_env_t * shared_user_env; rtems_id current_task_id; sc=rtems_task_ident(RTEMS_SELF,0,¤t_task_id); if (sc != RTEMS_SUCCESSFUL) return sc; if (rtems_current_user_env->task_id==current_task_id) { /* kill the current user env & task_var*/ rtems_user_env_t *tmp = rtems_current_user_env; sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env); if (sc != RTEMS_SUCCESSFUL) return sc; free_user_env(tmp); }; /* AT THIS POINT, rtems_current_user_env is DANGLING */ sc = rtems_task_variable_get(task_id,(void*)&rtems_current_user_env, (void*)&shared_user_env ); if (sc != RTEMS_SUCCESSFUL) goto bailout; sc = rtems_task_variable_add(RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env); if (sc != RTEMS_SUCCESSFUL) goto bailout; /* the current_user_env is the same pointer that remote env */ rtems_current_user_env = shared_user_env; /* increase the reference count */ #ifdef HAVE_USERENV_REFCNT rtems_current_user_env->refcnt++; #endif return RTEMS_SUCCESSFUL; bailout: /* fallback to the global env */ rtems_current_user_env = &rtems_global_user_env; return sc; }
int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr) { rtems_status_code status; #ifdef DEBUG_GXX_WRAPPERS printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, rtems_task_self() ); #endif /* register with RTEMS the buffer that will hold the key values */ status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ); if ( status == RTEMS_SUCCESSFUL ) { /* now let's set the proper value */ key->val = (void *)ptr; return 0; } return -1; }
bool rtems_shell_main_loop( rtems_shell_env_t *shell_env_arg ) { rtems_shell_env_t *shell_env; rtems_shell_cmd_t *shell_cmd; rtems_status_code sc; struct termios term; struct termios previous_term; char *prompt = NULL; int cmd; int cmd_count = 1; /* assume a script and so only 1 command line */ char *cmds[RTEMS_SHELL_CMD_COUNT]; char *cmd_argv; int argc; char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS]; bool result = true; bool input_file = false; int line = 0; FILE *stdinToClose = NULL; FILE *stdoutToClose = NULL; rtems_shell_initialize_command_set(); shell_env = rtems_current_shell_env = rtems_shell_init_env( shell_env_arg ); /* * @todo chrisj * Remove the use of task variables. Change to have a single * allocation per shell and then set into a notepad register * in the TCB. Provide a function to return the pointer. * Task variables are a virus to embedded systems software. */ sc = rtems_task_variable_add( RTEMS_SELF, (void*)&rtems_current_shell_env, rtems_shell_env_free ); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_task_variable_add(current_shell_env):"); return false; } setuid(0); setgid(0); rtems_current_user_env->euid = rtems_current_user_env->egid = 0; fileno(stdout); /* fprintf( stderr, "-%s-%s-\n", shell_env->input, shell_env->output ); */ if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) { if (strcmp(shell_env->output, "stderr") == 0) { stdout = stderr; } else if (strcmp(shell_env->output, "/dev/null") == 0) { fclose (stdout); } else { FILE *output = fopen(shell_env_arg->output, shell_env_arg->output_append ? "a" : "w"); if (!output) { fprintf(stderr, "shell: open output %s failed: %s\n", shell_env_arg->output, strerror(errno)); return false; } stdout = output; stdoutToClose = output; } } if (shell_env->input && strcmp(shell_env_arg->input, "stdin") != 0) { FILE *input = fopen(shell_env_arg->input, "r"); if (!input) { fprintf(stderr, "shell: open input %s failed: %s\n", shell_env_arg->input, strerror(errno)); return false; } stdin = input; stdinToClose = input; shell_env->forever = false; input_file =true; } else { /* make a raw terminal,Linux Manuals */ if (tcgetattr(fileno(stdin), &previous_term) >= 0) { term = previous_term; term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); term.c_oflag &= ~OPOST; term.c_oflag |= (OPOST|ONLCR); /* But with cr+nl on output */ term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); term.c_cflag |= CLOCAL | CREAD; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) { fprintf(stderr, "shell:cannot set terminal attributes(%s)\n",shell_env->devname); } } cmd_count = RTEMS_SHELL_CMD_COUNT; prompt = malloc(RTEMS_SHELL_PROMPT_SIZE); if (!prompt) fprintf(stderr, "shell:cannot allocate prompt memory\n"); } setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/ setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/ rtems_shell_initialize_command_set(); /* * Allocate the command line buffers. */ cmd_argv = malloc (RTEMS_SHELL_CMD_SIZE); if (!cmd_argv) { fprintf(stderr, "no memory for command line buffers\n" ); } cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE); if (!cmds[0]) { fprintf(stderr, "no memory for command line buffers\n" ); } if (cmd_argv && cmds[0]) { memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); for (cmd = 1; cmd < cmd_count; cmd++) { cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE; } do { /* Set again root user and root filesystem, side effect of set_priv..*/ sc = rtems_libio_set_private_env(); if (sc != RTEMS_SUCCESSFUL) { rtems_error(sc,"rtems_libio_set_private_env():"); result = false; break; } /* * By using result here, we can fall to the bottom of the * loop when the connection is dropped during login and * keep on trucking. */ if (shell_env->login_check != NULL) { result = rtems_shell_login(stdin,stdout); } else { result = true; } if (result) { const char *c; memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE); if (!input_file) { rtems_shell_cat_file(stdout,"/etc/motd"); fprintf(stdout, "\n" "RTEMS SHELL (Ver.1.0-FRC):%s. " \ __DATE__". 'help' to list commands.\n", shell_env->devname); } if (input_file) chdir(shell_env->cwd); else chdir("/"); /* XXX: chdir to getpwent homedir */ shell_env->exit_shell = false; for (;;) { int cmd; /* Prompt section */ if (prompt) { rtems_shell_get_prompt(shell_env, prompt, RTEMS_SHELL_PROMPT_SIZE); } /* getcmd section */ cmd = rtems_shell_line_editor(cmds, cmd_count, RTEMS_SHELL_CMD_SIZE, prompt, stdin, stdout); if (cmd == -1) continue; /* empty line */ if (cmd == -2) break; /*EOF*/ line++; if (shell_env->echo) fprintf(stdout, "%d: %s\n", line, cmds[cmd]); /* evaluate cmd section */ c = cmds[cmd]; while (*c) { if (!isblank((unsigned char)*c)) break; c++; } if (*c == '\0') /* empty line */ continue; if (*c == '#') { /* comment character */ cmds[cmd][0] = 0; continue; } if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) { fprintf(stdout, "Shell exiting\n" ); break; } else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */ fprintf(stdout, "System shutting down at user request\n" ); exit(0); } /* exec cmd section */ /* TODO: * To avoid user crash catch the signals. * Open a new stdio files with posibility of redirection * * Run in a new shell task background. (unix &) * Resuming. A little bash. */ memcpy (cmd_argv, cmds[cmd], RTEMS_SHELL_CMD_SIZE); if (!rtems_shell_make_args(cmd_argv, &argc, argv, RTEMS_SHELL_MAXIMUM_ARGUMENTS)) { shell_cmd = rtems_shell_lookup_cmd(argv[0]); if ( argv[0] == NULL ) { shell_env->errorlevel = -1; } else if ( shell_cmd == NULL ) { shell_env->errorlevel = rtems_shell_script_file(argc, argv); } else { shell_env->errorlevel = shell_cmd->command(argc, argv); } } /* end exec cmd section */ if (shell_env->exit_shell) break; } fflush( stdout ); fflush( stderr ); } } while (result && shell_env->forever); } if (cmds[0]) free (cmds[0]); if (cmd_argv) free (cmd_argv); if (prompt) free (prompt); if (stdinToClose) { fclose( stdinToClose ); } else { if (tcsetattr(fileno(stdin), TCSADRAIN, &previous_term) < 0) { fprintf( stderr, "shell: cannot reset terminal attributes (%s)\n", shell_env->devname ); } } if ( stdoutToClose ) fclose( stdoutToClose ); return result; }
rtems_status_code rtems_libio_set_private_env(void) { rtems_status_code sc = RTEMS_SUCCESSFUL; rtems_id task_id = rtems_task_self(); rtems_filesystem_location_info_t root_loc; rtems_filesystem_location_info_t current_loc; rtems_user_env_t *new_env = NULL; int rv = 0; rv = rtems_filesystem_evaluate_path("/", 1, 0, &root_loc, 0); if (rv != 0) goto error_0; rv = rtems_filesystem_evaluate_path("/", 1, 0, ¤t_loc, 0); if (rv != 0) goto error_1; /* * Malloc is necessary whenever the current task does not * have its own environment in place. This could be: * a) it never had one * OR * b) it shared another task's environment */ /* * Bharath: I'm not sure if the check can be reduced to * if( rtems_current_user_env->task_id != task_id ) { */ if ( rtems_current_user_env == &rtems_global_user_env || rtems_current_user_env->task_id != task_id ) { new_env = malloc(sizeof(rtems_user_env_t)); if (new_env == NULL) goto error_2; #ifdef HAVE_USERENV_REFCNT new_env->refcnt = 1; #endif sc = rtems_task_variable_add( RTEMS_SELF, (void*)&rtems_current_user_env, (void(*)(void *))free_user_env ); if (sc != RTEMS_SUCCESSFUL) goto error_3; rtems_current_user_env = new_env; } /* Inherit the global values */ *rtems_current_user_env = rtems_global_user_env; rtems_current_user_env->task_id = task_id; /* * Clone the pathlocs. In contrast to most other code we must _not_ free the * original locs because what we are trying to do here is forking off clones. * The reason is a pathloc can be allocated by the file system and needs to * be freed when deleting the environment. */ rtems_filesystem_root = root_loc; rtems_filesystem_current = current_loc; return RTEMS_SUCCESSFUL; error_3: free(new_env); error_2: rtems_filesystem_freenode(¤t_loc); error_1: rtems_filesystem_freenode(&root_loc); error_0: return RTEMS_NO_MEMORY; }
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 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); } }