/* * ======== cmm_get_info ======== * Purpose: * Return the current memory utilization information. */ int cmm_get_info(struct cmm_object *hcmm_mgr, OUT struct cmm_info *cmm_info_obj) { struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr; u32 ul_seg; int status = 0; struct cmm_allocator *altr; struct cmm_mnode *mnode_obj = NULL; DBC_REQUIRE(cmm_info_obj != NULL); if (!hcmm_mgr) { status = -EFAULT; return status; } mutex_lock(&cmm_mgr_obj->cmm_lock); cmm_info_obj->ul_num_gppsm_segs = 0; /* # of SM segments */ /* Total # of outstanding alloc */ cmm_info_obj->ul_total_in_use_cnt = 0; /* min block size */ cmm_info_obj->ul_min_block_size = cmm_mgr_obj->ul_min_block_size; /* check SM memory segments */ for (ul_seg = 1; ul_seg <= CMM_MAXGPPSEGS; ul_seg++) { /* get the allocator object for this segment id */ altr = get_allocator(cmm_mgr_obj, ul_seg); if (altr != NULL) { cmm_info_obj->ul_num_gppsm_segs++; cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_pa = altr->shm_base - altr->ul_dsp_size; cmm_info_obj->seg_info[ul_seg - 1].ul_total_seg_size = altr->ul_dsp_size + altr->ul_sm_size; cmm_info_obj->seg_info[ul_seg - 1].dw_gpp_base_pa = altr->shm_base; cmm_info_obj->seg_info[ul_seg - 1].ul_gpp_size = altr->ul_sm_size; cmm_info_obj->seg_info[ul_seg - 1].dw_dsp_base_va = altr->dw_dsp_base; cmm_info_obj->seg_info[ul_seg - 1].ul_dsp_size = altr->ul_dsp_size; cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_va = altr->dw_vm_base - altr->ul_dsp_size; cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt = 0; mnode_obj = (struct cmm_mnode *) lst_first(altr->in_use_list_head); /* Count inUse blocks */ while (mnode_obj) { cmm_info_obj->ul_total_in_use_cnt++; cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt++; /* next node. */ mnode_obj = (struct cmm_mnode *) lst_next(altr->in_use_list_head, (struct list_head *)mnode_obj); } } } /* end for */ mutex_unlock(&cmm_mgr_obj->cmm_lock); return status; }
/* * ======== un_register_gppsm_seg ======== * Purpose: * UnRegister the SM allocator by freeing all its resources and * nulling cmm mgr table entry. * Note: * This routine is always called within cmm lock crit sect. */ static void un_register_gppsm_seg(struct cmm_allocator *psma) { struct cmm_mnode *mnode_obj = NULL; struct cmm_mnode *next_node = NULL; DBC_REQUIRE(psma != NULL); if (psma->free_list_head != NULL) { /* free nodes on free list */ mnode_obj = (struct cmm_mnode *)lst_first(psma->free_list_head); while (mnode_obj) { next_node = (struct cmm_mnode *)lst_next(psma->free_list_head, (struct list_head *) mnode_obj); lst_remove_elem(psma->free_list_head, (struct list_head *)mnode_obj); kfree((void *)mnode_obj); /* next node. */ mnode_obj = next_node; } kfree(psma->free_list_head); /* delete freelist */ /* free nodes on InUse list */ mnode_obj = (struct cmm_mnode *)lst_first(psma->in_use_list_head); while (mnode_obj) { next_node = (struct cmm_mnode *)lst_next(psma->in_use_list_head, (struct list_head *) mnode_obj); lst_remove_elem(psma->in_use_list_head, (struct list_head *)mnode_obj); kfree((void *)mnode_obj); /* next node. */ mnode_obj = next_node; } kfree(psma->in_use_list_head); /* delete InUse list */ } if ((void *)psma->dw_vm_base != NULL) MEM_UNMAP_LINEAR_ADDRESS((void *)psma->dw_vm_base); /* Free allocator itself */ kfree(psma); }
void main (void) { LIST *list; int done = 0; REC *rec; char line[80]; list = lst_init (); printf ("Type a list of names and ages. Empty line quits\n\n"); while (!done) { rec = lst_newnode (sizeof (REC)); gets (line); if ((done = (line[0] == '\0')) != 1) { strcpy (rec->name, line); gets (line); rec->age = atoi (line); lst_insertafter (list, rec, LST_HEAD (list)); } }; printf ("\nThe list you typed in was:\n\n"); for (rec = lst_first (list); rec; rec = lst_next (rec)) printf ("Name: %s, Age: %d\n", rec->name, rec->age); printf ("\nSorting the list...\n\n"); lst_mergesort (list, my_cmp); for (rec = lst_first (list); rec; rec = lst_next (rec)) printf ("Name: %s, Age: %d\n", rec->name, rec->age); lst_kill (list, lst_freenode); }
/* * ======== dev_notify_clients ======== * Purpose: * Notify all clients of this device of a change in device status. */ int dev_notify_clients(struct dev_object *hdev_obj, u32 ret) { int status = 0; struct dev_object *dev_obj = hdev_obj; void *proc_obj; for (proc_obj = (void *)lst_first(dev_obj->proc_list); proc_obj != NULL; proc_obj = (void *)lst_next(dev_obj->proc_list, (struct list_head *)proc_obj)) proc_notify_clients(proc_obj, (u32) ret); return status; }
/* * ======== rmm_free ======== */ bool rmm_free(struct rmm_target_obj *target, u32 segid, u32 dsp_addr, u32 size, bool reserved) { struct rmm_ovly_sect *sect; bool ret = true; DBC_REQUIRE(target); DBC_REQUIRE(reserved || segid < target->num_segs); DBC_REQUIRE(reserved || (dsp_addr >= target->seg_tab[segid].base && (dsp_addr + size) <= (target->seg_tab[segid]. base + target->seg_tab[segid]. length))); /* * Free or unreserve memory. */ if (!reserved) { ret = free_block(target, segid, dsp_addr, size); if (ret) target->seg_tab[segid].number--; } else { /* Unreserve memory */ sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list); while (sect != NULL) { if (dsp_addr == sect->addr) { DBC_ASSERT(size == sect->size); /* Remove from list */ lst_remove_elem(target->ovly_list, (struct list_head *)sect); kfree(sect); break; } sect = (struct rmm_ovly_sect *)lst_next(target->ovly_list, (struct list_head *)sect); } if (sect == NULL) ret = false; } return ret; }
/* * ======== cmm_free_buf ======== * Purpose: * Free the given buffer. */ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa, u32 ul_seg_id) { struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr; int status = -EFAULT; struct cmm_mnode *mnode_obj = NULL; struct cmm_allocator *allocator = NULL; struct cmm_attrs *pattrs; DBC_REQUIRE(refs > 0); DBC_REQUIRE(buf_pa != NULL); if (ul_seg_id == 0) { pattrs = &cmm_dfltalctattrs; ul_seg_id = pattrs->ul_seg_id; } if (!hcmm_mgr || !(ul_seg_id > 0)) { status = -EFAULT; return status; } /* get the allocator for this segment id */ allocator = get_allocator(cmm_mgr_obj, ul_seg_id); if (allocator != NULL) { mutex_lock(&cmm_mgr_obj->cmm_lock); mnode_obj = (struct cmm_mnode *)lst_first(allocator->in_use_list_head); while (mnode_obj) { if ((u32) buf_pa == mnode_obj->dw_pa) { /* Found it */ lst_remove_elem(allocator->in_use_list_head, (struct list_head *)mnode_obj); /* back to freelist */ add_to_free_list(allocator, mnode_obj); status = 0; /* all right! */ break; } /* next node. */ mnode_obj = (struct cmm_mnode *) lst_next(allocator->in_use_list_head, (struct list_head *)mnode_obj); } mutex_unlock(&cmm_mgr_obj->cmm_lock); } return status; }
/* * ====== get_free_block ======== * Purpose: * Scan the free block list and return the first block that satisfies * the size. */ static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator, u32 usize) { if (allocator) { struct cmm_mnode *mnode_obj = (struct cmm_mnode *) lst_first(allocator->free_list_head); while (mnode_obj) { if (usize <= (u32) mnode_obj->ul_size) { lst_remove_elem(allocator->free_list_head, (struct list_head *)mnode_obj); return mnode_obj; } /* next node. */ mnode_obj = (struct cmm_mnode *) lst_next(allocator->free_list_head, (struct list_head *)mnode_obj); } } return NULL; }
static _linkage_block_ * _add_line_to_linkage_block_ (Line *line_to_add, Line *linkage_block_line, List *linkage_block_lst) { _linkage_block_ *linkage_block; assert (line_to_add); assert (linkage_block_line); assert (linkage_block_lst); assert (!lst_is_empty (linkage_block_lst)); assert (line_to_add -> scale < linkage_block_line -> scale); for (linkage_block = lst_first (linkage_block_lst); linkage_block && linkage_block -> line != linkage_block_line; linkage_block = lst_next (linkage_block_lst)); if (linkage_block && linkage_block -> line == linkage_block_line) { lst_add (line_to_add, linkage_block -> candidate_line_lst); linkage_block -> nb_of_candidates ++; } return linkage_block; }
/* * ======== dev_remove_proc_object ======== * Purpose: * Search for and remove a Proc object from the given list maintained * by the DEV * Parameters: * p_proc_object: Ptr to ProcObject to insert. * dev_obj Ptr to Dev Object where the list is. * Returns: * 0: If successful. * Requires: * List exists and is not empty * proc_obj != 0 * hdev_obj is a valid Dev handle. * Ensures: * Details: * List will be deleted when the DEV is destroyed. */ int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj) { int status = -EPERM; struct list_head *cur_elem; struct dev_object *dev_obj = (struct dev_object *)hdev_obj; DBC_REQUIRE(dev_obj); DBC_REQUIRE(proc_obj != 0); DBC_REQUIRE(dev_obj->proc_list != NULL); DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list)); /* Search list for dev_obj: */ for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL; cur_elem = lst_next(dev_obj->proc_list, cur_elem)) { /* If found, remove it. */ if ((u32) cur_elem == proc_obj) { lst_remove_elem(dev_obj->proc_list, cur_elem); status = 0; break; } } return status; }
/* * ======== rmm_alloc ======== */ int rmm_alloc(struct rmm_target_obj *target, u32 segid, u32 size, u32 align, u32 *dsp_address, bool reserve) { struct rmm_ovly_sect *sect; struct rmm_ovly_sect *prev_sect = NULL; struct rmm_ovly_sect *new_sect; u32 addr; int status = 0; DBC_REQUIRE(target); DBC_REQUIRE(dsp_address != NULL); DBC_REQUIRE(size > 0); DBC_REQUIRE(reserve || (target->num_segs > 0)); DBC_REQUIRE(refs > 0); if (!reserve) { if (!alloc_block(target, segid, size, align, dsp_address)) { status = -ENOMEM; } else { /* Increment the number of allocated blocks in this * segment */ target->seg_tab[segid].number++; } goto func_end; } /* An overlay section - See if block is already in use. If not, * insert into the list in ascending address size. */ addr = *dsp_address; sect = (struct rmm_ovly_sect *)lst_first(target->ovly_list); /* Find place to insert new list element. List is sorted from * smallest to largest address. */ while (sect != NULL) { if (addr <= sect->addr) { /* Check for overlap with sect */ if ((addr + size > sect->addr) || (prev_sect && (prev_sect->addr + prev_sect->size > addr))) { status = -ENXIO; } break; } prev_sect = sect; sect = (struct rmm_ovly_sect *)lst_next(target->ovly_list, (struct list_head *) sect); } if (!status) { /* No overlap - allocate list element for new section. */ new_sect = kzalloc(sizeof(struct rmm_ovly_sect), GFP_KERNEL); if (new_sect == NULL) { status = -ENOMEM; } else { lst_init_elem((struct list_head *)new_sect); new_sect->addr = addr; new_sect->size = size; new_sect->page = segid; if (sect == NULL) { /* Put new section at the end of the list */ lst_put_tail(target->ovly_list, (struct list_head *)new_sect); } else { /* Put new section just before sect */ lst_insert_before(target->ovly_list, (struct list_head *)new_sect, (struct list_head *)sect); } } } func_end: return status; }
/* * ======== add_to_free_list ======== * Purpose: * Coelesce node into the freelist in ascending size order. */ static void add_to_free_list(struct cmm_allocator *allocator, struct cmm_mnode *pnode) { struct cmm_mnode *node_prev = NULL; struct cmm_mnode *node_next = NULL; struct cmm_mnode *mnode_obj; u32 dw_this_pa; u32 dw_next_pa; DBC_REQUIRE(pnode != NULL); DBC_REQUIRE(allocator != NULL); dw_this_pa = pnode->dw_pa; dw_next_pa = NEXT_PA(pnode); mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head); while (mnode_obj) { if (dw_this_pa == NEXT_PA(mnode_obj)) { /* found the block ahead of this one */ node_prev = mnode_obj; } else if (dw_next_pa == mnode_obj->dw_pa) { node_next = mnode_obj; } if ((node_prev == NULL) || (node_next == NULL)) { /* next node. */ mnode_obj = (struct cmm_mnode *) lst_next(allocator->free_list_head, (struct list_head *)mnode_obj); } else { /* got 'em */ break; } } /* while */ if (node_prev != NULL) { /* combine with previous block */ lst_remove_elem(allocator->free_list_head, (struct list_head *)node_prev); /* grow node to hold both */ pnode->ul_size += node_prev->ul_size; pnode->dw_pa = node_prev->dw_pa; pnode->dw_va = node_prev->dw_va; /* place node on mgr nodeFreeList */ delete_node((struct cmm_object *)allocator->hcmm_mgr, node_prev); } if (node_next != NULL) { /* combine with next block */ lst_remove_elem(allocator->free_list_head, (struct list_head *)node_next); /* grow da node */ pnode->ul_size += node_next->ul_size; /* place node on mgr nodeFreeList */ delete_node((struct cmm_object *)allocator->hcmm_mgr, node_next); } /* Now, let's add to freelist in increasing size order */ mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head); while (mnode_obj) { if (pnode->ul_size <= mnode_obj->ul_size) break; /* next node. */ mnode_obj = (struct cmm_mnode *)lst_next(allocator->free_list_head, (struct list_head *)mnode_obj); } /* if mnode_obj is NULL then add our pnode to the end of the freelist */ if (mnode_obj == NULL) { lst_put_tail(allocator->free_list_head, (struct list_head *)pnode); } else { /* insert our node before the current traversed node */ lst_insert_before(allocator->free_list_head, (struct list_head *)pnode, (struct list_head *)mnode_obj); } }