/******************************************************************************* ** ** gckVIDMEM_Free ** ** Free an allocated video memory node. ** ** INPUT: ** ** gcuVIDMEM_NODE_PTR Node ** Pointer to a gcuVIDMEM_NODE object. ** ** OUTPUT: ** ** Nothing. */ gceSTATUS gckVIDMEM_Free( IN gcuVIDMEM_NODE_PTR Node ) { gckVIDMEM memory = gcvNULL; gcuVIDMEM_NODE_PTR node; gceSTATUS status; gctBOOL acquired = gcvFALSE; gcmkHEADER_ARG("Node=0x%x", Node); /* Verify the arguments. */ if ((Node == gcvNULL) || (Node->VidMem.memory == gcvNULL) ) { /* Invalid object. */ gcmkONERROR(gcvSTATUS_INVALID_OBJECT); } /**************************** Video Memory ********************************/ if (Node->VidMem.memory->object.type == gcvOBJ_VIDMEM) { if (Node->VidMem.locked > 0) { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM, "Node 0x%x is locked (%d)", Node, Node->VidMem.locked); /* Force unlock. */ Node->VidMem.locked = 0; } /* Extract pointer to gckVIDMEM object owning the node. */ memory = Node->VidMem.memory; /* Acquire the mutex. */ gcmkONERROR( gckOS_AcquireMutex(memory->os, memory->mutex, gcvINFINITE)); acquired = gcvTRUE; #ifdef __QNXNTO__ /* Reset handle to 0. */ Node->VidMem.logical = gcvNULL; Node->VidMem.handle = 0; /* Don't try to a re-free an already freed node. */ if ((Node->VidMem.nextFree == gcvNULL) && (Node->VidMem.prevFree == gcvNULL) ) #endif { /* Update the number of free bytes. */ memory->freeBytes += Node->VidMem.bytes; /* Find the next free node. */ for (node = Node->VidMem.next; node->VidMem.nextFree == gcvNULL; node = node->VidMem.next) ; /* Insert this node in the free list. */ Node->VidMem.nextFree = node; Node->VidMem.prevFree = node->VidMem.prevFree; Node->VidMem.prevFree->VidMem.nextFree = node->VidMem.prevFree = Node; /* Is the next node a free node and not the sentinel? */ if ((Node->VidMem.next == Node->VidMem.nextFree) && (Node->VidMem.next->VidMem.bytes != 0) ) { /* Merge this node with the next node. */ gcmkONERROR(_Merge(memory->os, node = Node)); gcmkASSERT(node->VidMem.nextFree != node); gcmkASSERT(node->VidMem.prevFree != node); } /* Is the previous node a free node and not the sentinel? */ if ((Node->VidMem.prev == Node->VidMem.prevFree) && (Node->VidMem.prev->VidMem.bytes != 0) ) { /* Merge this node with the previous node. */ gcmkONERROR(_Merge(memory->os, node = Node->VidMem.prev)); gcmkASSERT(node->VidMem.nextFree != node); gcmkASSERT(node->VidMem.prevFree != node); } } /* Release the mutex. */ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex)); /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; } /*************************** Virtual Memory *******************************/ /* Verify the gckKERNEL object pointer. */ gcmkVERIFY_OBJECT(Node->Virtual.kernel, gcvOBJ_KERNEL); #ifdef __QNXNTO__ if (!Node->Virtual.unlockPending && (Node->Virtual.locked > 0)) #else if (!Node->Virtual.pending && (Node->Virtual.locked > 0)) #endif { gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_VIDMEM, "gckVIDMEM_Free: Virtual node 0x%x is locked (%d)", Node, Node->Virtual.locked); /* Force unlock. */ Node->Virtual.locked = 0; } #ifdef __QNXNTO__ if (!Node->Virtual.freePending) { if (Node->Virtual.unlockPending) #else if (Node->Virtual.pending) #endif { gcmkASSERT(Node->Virtual.locked == 1); /* Schedule the node to be freed. */ gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_VIDMEM, "gckVIDMEM_Free: Scheduling node 0x%x to be freed later", Node); /* Schedule the video memory to be freed again. */ gcmkONERROR(gckEVENT_FreeVideoMemory(Node->Virtual.kernel->event, Node, gcvKERNEL_PIXEL)); #ifdef __QNXNTO__ Node->Virtual.freePending = gcvTRUE; } #endif /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_SKIP; } else { /* Free the virtual memory. */ gcmkVERIFY_OK(gckOS_FreePagedMemory(Node->Virtual.kernel->os, Node->Virtual.physical, Node->Virtual.bytes)); /* Destroy the gcuVIDMEM_NODE union. */ gcmkVERIFY_OK(gckVIDMEM_DestroyVirtual(Node)); } /* Success. */ gcmkFOOTER_NO(); return gcvSTATUS_OK; OnError: if (acquired) { /* Release the mutex. */ gcmkVERIFY_OK(gckOS_ReleaseMutex(memory->os, memory->mutex)); } /* Return the status. */ gcmkFOOTER(); return status; }
int memory_engine_free(memory_engine_t *engine, int alignaddr) { int res = 0; #ifdef SHM_GUARD_BYTES_ENABLE int flag = 0; #endif memory_node_t *new_node, *node; shm_debug("memory_engine_free start. (0x%08X)\n", alignaddr); if ((engine == NULL) || (alignaddr == 0)) return -EINVAL; down(&(engine->m_mutex)); /* find alignaddr */ node = memory_engine_lookup_shm_node(&(engine->m_shm_root), alignaddr); if (node == NULL) { printk("memory_engine_lookup_shm_node Error alignaddr[%x]\n", alignaddr); res = -EFAULT; goto err_exit; } memory_engine_delete_shm_node(&(engine->m_shm_root), node); /* if the node to be freed is a free one, there could be invalid operations*/ if (node->m_next_free != NULL) { res = -EFAULT; goto err_exit; } #ifdef SHM_GUARD_BYTES_ENABLE //check stuff bytes if (engine->m_cache_or_noncache == SHM_CACHE) { if (_Check_guard_data(engine, node) != 0) { _Check_guard_data_all_node(engine); flag = -1; } } #endif /* clean node */ node->m_offset = 0; node->m_alignment = 0; /* Update the number of free bytes. */ engine->m_size_free += node->m_size; engine->m_size_used -= node->m_size; /* Find the next free node(go through node list, find the first node which is free). */ for (new_node = node->m_next; new_node->m_next_free == NULL; new_node = new_node->m_next) ; /* Insert this node in the free list. */ node->m_next_free = new_node; node->m_prev_free = new_node->m_prev_free; node->m_prev_free->m_next_free = new_node->m_prev_free = node; engine->m_num_usedblock--; engine->m_num_freeblock++; /* Is the next node a free node and not the root? */ if ((node->m_next == node->m_next_free) && (node->m_next->m_size != 0)) { /* Merge this node with the next node. */ new_node = node; res = _Merge(engine, new_node); if((new_node->m_next_free == new_node) || (new_node->m_prev_free == new_node) || (res != 0)) { /* Error. */ shm_error("_Merge next node failed.\n"); goto err_exit; } engine->m_num_freeblock--; shm_debug("_Merge next node OK.\n"); } /* Is the previous node a free node and not the root? */ if ((node->m_prev == node->m_prev_free) && (node->m_prev->m_size != 0)) { /* Merge this node with the previous node. */ new_node = node->m_prev; res = _Merge(engine, new_node); if((new_node->m_next_free == new_node) || (new_node->m_prev_free == new_node) || (res != 0)) { /* Error. */ shm_error("_Merge previous node failed.\n"); goto err_exit; } engine->m_num_freeblock--; shm_debug("_Merge previous node OK.\n"); } up(&(engine->m_mutex)); shm_debug("memory_engine_free OK.\n"); #ifdef SHM_GUARD_BYTES_ENABLE if (flag != 0) return flag; #endif return 0; err_exit: up(&(engine->m_mutex)); if (shm_lowmem_debug_level > 2) { shm_error("memory_engine_free failed !!! (0x%08X)\n", alignaddr); dump_stack(); } return res; }