summaryrefslogtreecommitdiff
path: root/nuttx/sched/sched_free.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/sched/sched_free.c')
-rw-r--r--nuttx/sched/sched_free.c69
1 files changed, 59 insertions, 10 deletions
diff --git a/nuttx/sched/sched_free.c b/nuttx/sched/sched_free.c
index e5e0bdacf..7442a4d09 100644
--- a/nuttx/sched/sched_free.c
+++ b/nuttx/sched/sched_free.c
@@ -1,7 +1,7 @@
/************************************************************************
* sched/sched_free.c
*
- * Copyright (C) 2007, 2009, 2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2012-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -72,18 +72,61 @@
************************************************************************/
/************************************************************************
- * Name: sched_free
+ * Name: sched_ufree and sched_kfree
*
* Description:
- * This function performs deallocations that the operating system may
- * need to make. This special interface to free is used to handling
+ * These function performs deallocations that the operating system may
+ * need to make. This special interface to free is used in handling
* corner cases where the operating system may have to perform
* deallocations from within an interrupt handler.
*
************************************************************************/
-void sched_free(FAR void *address)
+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_NUTTX_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. */
+
+ kufree(address);
+ kumm_givesemaphore();
+ }
+}
+
+#if defined(CONFIG_NUTTX_KERNEL) && defined(CONFIG_MM_KERNEL_HEAP)
+void sched_kfree(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.
@@ -91,17 +134,23 @@ void sched_free(FAR void *address)
if (up_interrupt_context() || kmm_trysemaphore() != 0)
{
- /* Yes.. Delay the deallocation until a more appropriate time. */
+ /* Yes.. Make sure that this is not a attempt to free user memory
+ * using the kernel deallocator.
+ */
+
+ flags = irqsave();
+ DEBUGASSERT(kmm_heapmember(address));
- irqstate_t saved_state = irqsave();
- sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayeddeallocations);
+ /* Delay the deallocation until a more appropriate time. */
+
+ sq_addlast((FAR sq_entry_t*)address, (sq_queue_t*)&g_delayed_kfree);
/* Signal the worker thread that is has some clean up to do */
#ifdef CONFIG_SCHED_WORKQUEUE
work_signal(LPWORK);
#endif
- irqrestore(saved_state);
+ irqrestore(flags);
}
else
{
@@ -111,4 +160,4 @@ void sched_free(FAR void *address)
kmm_givesemaphore();
}
}
-
+#endif