void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { /* Is there a stack allocated? */ if (dtcb->stack_alloc_ptr) { #if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP) /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { sched_kfree(dtcb->stack_alloc_ptr); } else #endif { /* Use the user-space allocator if this is a task or pthread */ sched_ufree(dtcb->stack_alloc_ptr); } /* Mark the stack freed */ dtcb->stack_alloc_ptr = NULL; } /* The size of the allocated stack is now zero */ dtcb->adj_stack_size = 0; }
void lib_stream_release(FAR struct task_group_s *group) { FAR struct streamlist *list; #if CONFIG_STDIO_BUFFER_SIZE > 0 int i; #endif #if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ defined(CONFIG_MM_KERNEL_HEAP) DEBUGASSERT(group && group->tg_streamlist); list = group->tg_streamlist; #else DEBUGASSERT(group); list = &group->tg_streamlist; #endif /* Destroy the semaphore and release the filelist */ (void)sem_destroy(&list->sl_sem); /* Release each stream in the list */ #if CONFIG_STDIO_BUFFER_SIZE > 0 for (i = 0; i < CONFIG_NFILE_STREAMS; i++) { /* Destroy the semaphore that protects the IO buffer */ (void)sem_destroy(&list->sl_streams[i].fs_sem); /* Release the IO buffer */ if (list->sl_streams[i].fs_bufstart) { #ifndef CONFIG_BUILD_KERNEL /* Release memory from the user heap */ sched_ufree(list->sl_streams[i].fs_bufstart); #else /* If the exiting group is unprivileged, then it has an address * environment. Don't bother to release the memory in this case... * There is no point since the memory lies in the user heap which * will be destroyed anyway. But if this is a privileged group, * when we still have to release the memory using the kernel * allocator. */ if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0) { sched_kfree(list->sl_streams[i].fs_bufstart); } #endif } } #endif }
void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { /* Is there a stack allocated? */ if (dtcb->stack_alloc_ptr) { sched_ufree(dtcb->stack_alloc_ptr); } /* Mark the stack freed */ dtcb->stack_alloc_ptr = NULL; dtcb->adj_stack_size = 0; dtcb->adj_stack_ptr = NULL; }
void env_release(FAR struct task_group_s *group) { DEBUGASSERT(group); /* Free any allocate environment strings */ if (group->tg_envp) { /* Free the environment */ sched_ufree(group->tg_envp); } /* In any event, make sure that all environment-related varialbles in the * task group structure are reset to initial values. */ group->tg_envsize = 0; group->tg_envp = NULL; }
void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { /* Is there a stack allocated? */ if (dtcb->stack_alloc_ptr) { if (umm_heapmember(dtcb->stack_alloc_ptr)) { sched_ufree(dtcb->stack_alloc_ptr); } /* Mark the stack freed */ dtcb->stack_alloc_ptr = NULL; } /* The size of the allocated stack is now zero */ dtcb->adj_stack_size = 0; }
static inline void group_release(FAR struct task_group_s *group) { /* Free all un-reaped child exit status */ #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) group_removechildren(group); #endif #ifndef CONFIG_DISABLE_SIGNALS /* Release pending signals */ sig_release(group); #endif #ifndef CONFIG_DISABLE_PTHREAD /* Release pthread resources */ pthread_release(group); #endif #if CONFIG_NFILE_DESCRIPTORS > 0 /* Free all file-related resources now. We really need to close files as * soon as possible while we still have a functioning task. */ /* Free resources held by the file descriptor list */ files_releaselist(&group->tg_filelist); #if CONFIG_NFILE_STREAMS > 0 /* Free resource held by the stream list */ lib_stream_release(group); #endif /* CONFIG_NFILE_STREAMS */ #endif /* CONFIG_NFILE_DESCRIPTORS */ #if CONFIG_NSOCKET_DESCRIPTORS > 0 /* Free resource held by the socket list */ net_releaselist(&group->tg_socketlist); #endif /* CONFIG_NSOCKET_DESCRIPTORS */ #ifndef CONFIG_DISABLE_ENVIRON /* Release all shared environment variables */ env_release(group); #endif #ifndef CONFIG_DISABLE_MQUEUE /* Close message queues opened by members of the group */ mq_release(group); #endif #if defined(CONFIG_BUILD_KERNEL) && defined(CONFIG_MM_SHM) /* Release any resource held by shared memory virtual page allocator */ (void)shm_group_release(group); #endif #ifdef CONFIG_ARCH_ADDRENV /* Destroy the group address environment */ (void)up_addrenv_destroy(&group->tg_addrenv); /* Mark no address environment */ g_gid_current = 0; #endif #if defined(HAVE_GROUP_MEMBERS) || defined(CONFIG_ARCH_ADDRENV) /* Remove the group from the list of groups */ group_remove(group); #endif #ifdef HAVE_GROUP_MEMBERS /* Release the members array */ if (group->tg_members) { sched_kfree(group->tg_members); group->tg_members = NULL; } #endif #if CONFIG_NFILE_STREAMS > 0 && defined(CONFIG_MM_KERNEL_HEAP) /* In a flat, single-heap build. The stream list is part of the * group structure and, hence will be freed when the group structure * is freed. Otherwise, it is separately allocated an must be * freed here. */ # if defined(CONFIG_BUILD_PROTECTED) /* In the protected build, the task's stream list is always allocated * and freed from the single, global user allocator. */ sched_ufree(group->tg_streamlist); # elif defined(CONFIG_BUILD_KERNEL) /* In the kernel build, the unprivileged process' stream list will be * allocated from with its per-process, private user heap. But in that * case, there is no reason to do anything here: That allocation resides * in the user heap which which be completely freed when we destroy the * process' address environment. */ if ((group->tg_flags & GROUP_FLAG_PRIVILEGED) != 0) { /* But kernel threads are different in this build configuration: Their * stream lists were allocated from the common, global kernel heap and * must explicitly freed here. */ sched_kfree(group->tg_streamlist); } # endif #endif #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT) /* If there are threads waiting for this group to be freed, then we cannot * yet free the memory resources. Instead just mark the group deleted * and wait for those threads complete their waits. */ if (group->tg_nwaiters > 0) { group->tg_flags |= GROUP_FLAG_DELETED; } else #endif { /* Release the group container itself */ sched_kfree(group); } }