void sched_ufree(FAR void *address) { #ifdef CONFIG_BUILD_KERNEL /* REVISIT: It is not safe to defer user allocation in the kernel mode * build. Why? Because the correct user context is in place now but * will not be in place when the deferred de-allocation is performed. In * order to make this work, we would need to do something like: (1) move * g_delayed_kufree into the group structure, then traverse the groups to * collect garbage on a group-by-group basis. */ ASSERT(!up_interrupt_context()); kumm_free(address); #else /* Check if this is an attempt to deallocate memory from an exception * handler. If this function is called from the IDLE task, then we * must have exclusive access to the memory manager to do this. */ if (up_interrupt_context() || kumm_trysemaphore() != 0) { irqstate_t flags; /* Yes.. Make sure that this is not a attempt to free kernel memory * using the user deallocator. */ flags = irqsave(); #if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ defined(CONFIG_MM_KERNEL_HEAP) DEBUGASSERT(!kmm_heapmember(address)); #endif /* Delay the deallocation until a more appropriate time. */ sq_addlast((FAR sq_entry_t *)address, (FAR sq_queue_t *)&g_delayed_kufree); /* Signal the worker thread that is has some clean up to do */ #ifdef CONFIG_SCHED_WORKQUEUE work_signal(LPWORK); #endif irqrestore(flags); } else { /* No.. just deallocate the memory now. */ kumm_free(address); kumm_givesemaphore(); } #endif }
void sched_ufree(FAR void *address) { irqstate_t flags; /* Check if this is an attempt to deallocate memory from an exception * handler. If this function is called from the IDLE task, then we * must have exclusive access to the memory manager to do this. */ if (up_interrupt_context() || kumm_trysemaphore() != 0) { /* Yes.. Make sure that this is not a attempt to free kernel memory * using the user deallocator. */ flags = irqsave(); #if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \ defined(CONFIG_MM_KERNEL_HEAP) DEBUGASSERT(!kmm_heapmember(address)); #endif /* Delay the deallocation until a more appropriate time. */ sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayed_kufree); /* Signal the worker thread that is has some clean up to do */ #ifdef CONFIG_SCHED_WORKQUEUE work_signal(LPWORK); #endif irqrestore(flags); } else { /* No.. just deallocate the memory now. */ kumm_free(address); kumm_givesemaphore(); } }
void up_release_stack(FAR struct tcb_s *dtcb, uint8_t ttype) { /* Is there a stack allocated? */ if (dtcb->stack_alloc_ptr) { #ifdef HAVE_KERNEL_HEAP /* Use the kernel allocator if this is a kernel thread */ if (ttype == TCB_FLAG_TTYPE_KERNEL) { if (kmm_heapmember(dtcb->stack_alloc_ptr)) { sched_kfree(dtcb->stack_alloc_ptr); } } else #endif { /* Use the user-space allocator if this is a task or pthread */ 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; }