void init_blocks(uint8_t * map, uint32_t size) { int i; memset(zero, 0, sizeof zero); list_init(&block_head); list_init(&used_block); // printk("%d\n", size / 512); for(i = 0; i < size / 512; ++ i) { block[i].index = i; if(map[i / 8] & (1 << (i & 0x7))) list_add_before(&used_block, &block[i].list); else list_add_before(&block_head, &block[i].list); } }
static void comm_init_pool( uint8_t *mem, uint32_t mem_size, struct list_head *free_list_head ) { uint8_t *com_mem; uint32_t avail_mem_size, data_mem_size; // set com_mem = mem; avail_mem_size = mem_size; data_mem_size = ALIGN(sizeof(com_pool_data_t)); com_pool_size = 0; INIT_LIST_HEAD(free_list_head); // dispose while (avail_mem_size >= data_mem_size){ com_pool_data_t *data = (com_pool_data_t *)com_mem; // add to list list_add_before(&data->list_node, free_list_head); com_mem += data_mem_size; avail_mem_size -= data_mem_size; com_pool_size++; } }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); while (le != &free_list) { p = le2page(le, page_link); le = list_next(le); if (base + base->property == p) { base->property += p->property; ClearPageProperty(p); list_del(&(p->page_link)); } else if (p + p->property == base) { p->property += base->property; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } } nr_free += n; le = &free_list; while ((le = list_next(le)) != &free_list) { if (le2page(le, page_link) > base) { break; } } list_add_before(le, &(base->page_link)); }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *page = le2page(le, page_link); // Finds a free block. if (page->property >= n) { // Malloc the first n pages. ClearPageProperty(page); SetPageReserved(page); list_del(le); if (page->property > n) { // Updates the remained space size. struct Page* new_page = page + n; new_page->property = page->property - n; list_add_before(list_next(le), &(new_page->page_link)); } page->property = 0; nr_free -= n; return page; } } return NULL; }
/* * stride_enqueue inserts the process ``proc'' into the run-queue * ``rq''. The procedure should verify/initialize the relevant members * of ``proc'', and then put the ``lab6_run_pool'' node into the * queue(since we use priority queue here). The procedure should also * update the meta date in ``rq'' structure. * * proc->time_slice denotes the time slices allocation for the * process, which should set to rq->max_time_slice. * * hint: see libs/skew_heap.h for routines of the priority * queue structures. */ static void stride_enqueue(struct run_queue *rq, struct proc_struct *proc) { /* LAB6: YOUR CODE * (1) insert the proc into rq correctly * NOTICE: you can use skew_heap or list. Important functions * skew_heap_insert: insert a entry into skew_heap * list_add_before: insert a entry into the last of list * (2) recalculate proc->time_slice * (3) set proc->rq pointer to rq * (4) increase rq->proc_num */ #if USE_SKEW_HEAP rq->lab6_run_pool = skew_heap_insert(rq->lab6_run_pool, &(proc->lab6_run_pool), proc_stride_comp_f); #else assert(list_empty(&(proc->run_link))); list_add_before(&(rq->run_list), &(proc->run_link)); #endif if (proc->time_slice == 0 || proc->time_slice > rq->max_time_slice) { proc->time_slice = rq->max_time_slice; } proc->rq = rq; rq->proc_num++; }
/** * Change a timer_entry. * * @param timer_entry to be changed. * @param new relative time expressed in units of milliseconds. * @param new jitter expressed in percent. * @return nada */ void olsr_change_timer(struct timer_entry *timer, unsigned int rel_time, uint8_t jitter_pct, bool periodical) { /* Sanity check. */ if (!timer) { return; } assert(timer->timer_cookie); /* we want timer cookies everywhere */ /* Singleshot or periodical timer ? */ timer->timer_period = periodical ? rel_time : 0; timer->timer_clock = calc_jitter(rel_time, jitter_pct, timer->timer_random); timer->timer_jitter_pct = jitter_pct; /* * Changes are easy: Remove timer from the exisiting timer_wheel slot * and reinsert into the new slot. */ list_remove(&timer->timer_list); list_add_before(&timer_wheel[timer->timer_clock & TIMER_WHEEL_MASK], &timer->timer_list); OLSR_PRINTF(7, "TIMER: change %s timer %p, firing to %s, ctx %p\n", timer->timer_cookie->ci_name, timer, olsr_clock_string(timer->timer_clock), timer->timer_cb_context); }
static int range_alloc(struct ashmem_area *asma, struct ashmem_range *prev_range, unsigned int purged, size_t start, size_t end) { struct ashmem_range *range; range = kmalloc(sizeof(struct ashmem_range)); memset(range, 0, sizeof(struct ashmem_range)); if(!range) { return -ENOMEM; } range->asma = asma; range->pgstart = start; range->pgend = end; range->purged = purged; list_add_before(&prev_range->unpinned, &range->unpinned); if(range_on_lru(range)) { lru_add(range); } return 0; }
static struct Page * default_alloc_pages(size_t n) { assert(n > 0); if (n > nr_free) { return NULL; } struct Page *page = NULL; list_entry_t *le = &free_list; while ((le = list_next(le)) != &free_list) { struct Page *p = le2page(le, page_link); if (p->property >= n) { page = p; break; } } if (page != NULL) { list_entry_t *next_le = list_next(&(page->page_link)); list_del(&(page->page_link)); if (page->property > n) { struct Page *p = page + n; p->property = page->property - n; SetPageProperty(p); if(list_empty(&free_list)) list_add(&free_list, &(p->page_link)); else list_add_before(next_le, &(p->page_link)); } nr_free -= n; ClearPageProperty(page); } return page; }
int kswapd_main(void *arg) { int guard = 0; while (1) { if (pressure > 0) { int needs = (pressure << 5), rounds = 16; list_entry_t *list = &proc_mm_list; assert(!list_empty(list)); while (needs > 0 && rounds -- > 0) { list_entry_t *le = list_next(list); list_del(le); list_add_before(list, le); struct mm_struct *mm = le2mm(le, proc_mm_link); needs -= swap_out_mm(mm, (needs < 32) ? needs : 32); } } pressure -= page_launder(); refill_inactive_scan(); if (pressure > 0) { if ((++ guard) >= 1000) { guard = 0; warn("kswapd: may out of memory"); } continue ; } pressure = 0, guard = 0; kswapd_wakeup_all(); do_sleep(1000); } }
static void dir_handler (const char *path, List *dirs) { DIR *dir; struct dirent *ent; char ent_path[PATH_MAX]; dir = opendir (path); if (! dir) { perror ("opendir"); return; } while ((ent = readdir (dir))) { if (*ent->d_name == '.') continue; snprintf ((char *)&ent_path, PATH_MAX, "%s/%s", path, ent->d_name); if (ent->d_type == DT_DIR) list_add_before (dirs, strdup (ent_path)); else if (strcmp (ent->d_name, "modalias") == 0) read_modalias (ent_path); } closedir (dir); }
uint32_t get_new_block() { assert(!list_empty(&block_head)); block_t *newb = list_entry(block_head.next, block_t, list); list_del(&newb->list); list_add_before(&used_block, &newb->list); // printk("%d\n", newb->index); return newb->index; }
// swap_inactive_list_add - add the page to inactive_list static inline void swap_inactive_list_add(struct Page *page) { assert(PageSwap(page)); ClearPageActive(page); swap_list_t *list = &inactive_list; list->nr_pages ++; list_add_before(&(list->swap_list), &(page->swap_link)); }
/* assume intr has been disabled in the following API */ void wait_queue_add(wait_queue_t * queue, wait_t * wait) { spinlock_acquire(&queue->lock); assert(list_empty(&(wait->wait_link)) && wait->proc != NULL); wait->wait_queue = queue; list_add_before(&(queue->wait_head), &(wait->wait_link)); spinlock_release(&queue->lock); }
// try to insert this free chunk into the free list, consuming the chunk by merging it with // nearby ones if possible. Returns base of whatever chunk it became in the list. static struct free_heap_chunk *heap_insert_free_chunk(struct free_heap_chunk *chunk) { #if DEBUGLEVEL > INFO //vaddr_t chunk_end = (vaddr_t)chunk + chunk->len; //dprintf(DEBUGLEVEL, "%s: chunk ptr %p, size 0x%lx, chunk_end 0x%x\n", __FUNCTION__, chunk, (long unsigned int)chunk->len, (unsigned int)chunk_end); #endif struct free_heap_chunk *next_chunk; struct free_heap_chunk *last_chunk; mutex_acquire(&theheap.lock); // walk through the list, finding the node to insert before list_for_every_entry(&theheap.free_list, next_chunk, struct free_heap_chunk, node) { if (chunk < next_chunk) { DEBUG_ASSERT(chunk_end <= (vaddr_t)next_chunk); list_add_before(&next_chunk->node, &chunk->node); goto try_merge; } } // walked off the end of the list, add it at the tail list_add_tail(&theheap.free_list, &chunk->node); // try to merge with the previous chunk try_merge: last_chunk = list_prev_type(&theheap.free_list, &chunk->node, struct free_heap_chunk, node); if (last_chunk) { if ((vaddr_t)last_chunk + last_chunk->len == (vaddr_t)chunk) { // easy, just extend the previous chunk last_chunk->len += chunk->len; // remove ourself from the list list_delete(&chunk->node); // set the chunk pointer to the newly extended chunk, in case // it needs to merge with the next chunk below chunk = last_chunk; } } // try to merge with the next chunk if (next_chunk) { if ((vaddr_t)chunk + chunk->len == (vaddr_t)next_chunk) { // extend our chunk chunk->len += next_chunk->len; // remove them from the list list_delete(&next_chunk->node); } } mutex_release(&theheap.lock); return chunk; }
static void RR_enqueue(struct run_queue *rq, struct proc_struct *proc) { assert(list_empty(&(proc->run_link))); list_add_before(&(rq->run_list), &(proc->run_link)); if (proc->time_slice == 0 || proc->time_slice > rq->max_time_slice) { proc->time_slice = rq->max_time_slice; } proc->rq = rq; rq->proc_num++; }
static com_pool_data_t * comm_alloc_data( struct list_head *free_list_head ) { com_pool_data_t *data; // 1 get next storage data nd add before head data = list_entry(free_list_head->next,com_pool_data_t,list_node); list_del(free_list_head->next); list_add_before(&data->list_node,free_list_head); return data; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = list_next(&free_list); // Given Code // while (le != &free_list) { // p = le2page(le, page_link); // le = list_next(le); // if (base + base->property == p) { // base->property += p->property; // ClearPageProperty(p); // list_del(&(p->page_link)); // } // else if (p + p->property == base) { // p->property += base->property; // ClearPageProperty(base); // base = p; // list_del(&(p->page_link)); // } // } // nr_free += n; // list_add(&free_list, &(base->page_link)); while (le != &free_list) { p = le2page(le, page_link); if (base + base->property < p) //已经遍历到第一个地址大于base且无法合并的块,跳出循环 break; le = list_next(le); if (p + p->property == base) { //检查是否是base之前的能合并的块 p->property += base->property; base->flags = base->property = 0; ClearPageProperty(base); base = p; list_del(&(p->page_link)); } else if (base + base->property == p) { //检查是否是base之后能合并的块 base->property += p->property; p->flags = p->property = 0; ClearPageProperty(p); list_del(&(p->page_link)); } } nr_free += n; //空闲空间增加 SetPageProperty(base); //property = 1 list_add_before(le, &(base->page_link)); //插入在第一个第一个地址大于base且无法合并的块之前 }
/* do_fork - parent process for a new child process * @clone_flags: used to guide how to clone the child process * @stack: the parent's user stack pointer. if stack==0, It means to fork a kernel thread. * @tf: the trapframe info, which will be copied to child process's proc->tf */ int do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf) { int ret = -E_NO_FREE_PROC; struct proc_struct *proc; if (nr_process >= MAX_PROCESS) { goto fork_out; } ret = -E_NO_MEM; //LAB4:EXERCISE2 2012011346 /* * Some Useful MACROs, Functions and DEFINEs, you can use them in below implementation. * MACROs or Functions: * alloc_proc: create a proc struct and init fields (lab4:exercise1) * setup_kstack: alloc pages with size KSTACKPAGE as process kernel stack * copy_thread: setup the trapframe on the process's kernel stack top and * setup the kernel entry point and stack of process * hash_proc: add proc into proc hash_list * get_pid: alloc a unique pid for process * wakeup_proc: set proc->state = PROC_RUNNABLE * VARIABLES: * proc_list: the process set's list * nr_process: the number of process set */ // 1. call alloc_proc to allocate a proc_struct proc = alloc_proc(); proc->pid = get_pid(); cprintf("fork pid = %d\n", proc->pid); // 2. call setup_kstack to allocate a kernel stack for child process setup_kstack(proc); // 3. call copy_thread to setup tf & context in proc_struct copy_thread(proc, stack, tf); // 4. insert proc_struct into proc_list list_add_before(&proc_list, &proc->list_link); // 5. call wakeup_proc to make the new child process RUNNABLE wakeup_proc(proc); // 7. set ret vaule using child proc's pid nr_process++; ret = proc->pid; // 8. set parent proc->parent = current; fork_out: return ret; bad_fork_cleanup_kstack: put_kstack(proc); bad_fork_cleanup_proc: kfree(proc); goto fork_out; }
static void RR_enqueue(struct run_queue *rq, struct proc_struct *proc) { //cprintf("[RR Schedule]enqueue pid %d name %s\n", proc->pid, proc->name); assert(list_empty(&(proc->run_link))); list_add_before(&(rq->run_list), &(proc->run_link)); if (proc->time_slice == 0 || proc->time_slice > rq->max_time_slice) { proc->time_slice = rq->max_time_slice; } proc->rq = rq; rq->proc_num ++; }
/* * (3)_fifo_map_swappable: According FIFO PRA, we should link the most recent arrival page at the back of pra_list_head qeueue */ static int _fifo_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in) { list_entry_t *head=(list_entry_t*) mm->sm_priv; list_entry_t *entry=&(page->pra_page_link); assert(entry != NULL && head != NULL); //record the page access situlation /*LAB3 EXERCISE 2: 2013011720*/ list_add_before(head, entry);//(1)link the most recent arrival page at the back of the pra_list_head qeueue. return 0; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); list_entry_t *le = &free_list; struct Page * p; while (p <= base && (le = list_next(le)) != &free_list) p = le2page(le, page_link); for(p=base;p<base+n;p++) { list_add_before(le, &(p->page_link)); p->flags = 0; set_page_ref(p, 0); } base->flags = 0; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); base->property = n; while (1) { p = le2page(le, page_link); if (base->page_link.next != &free_list && base+base->property==p) { base->property += p->property; p->property = 0; } else break; } le = list_prev(&(base->page_link)); p = le2page(le, page_link); if(le != &free_list && p == base-1) { while (1) { if (p->property) { p->property += base->property; base->property = 0; break; } if (le != &free_list) { le = list_prev(le); p = le2page(le,page_link); } else break; } } nr_free += n; }
static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(!PageReserved(p) && !PageProperty(p)); p->flags = 0; set_page_ref(p, 0); } base->property = n; SetPageProperty(base); list_entry_t *le = &free_list; while (1) { //TODO: set reserve bits and could be faster le = list_next(le); p = le2page(le, page_link); if (le == &free_list || p > base) { list_add_before(&(p->page_link), &(base->page_link)); break; } } int flag = 1; //cprintf("Now check merge\n"); while (flag == 1) { flag = 0; p = le2page((base->page_link.next), page_link); //cprintf("base = %08x p = %08x size = %d\n", base, p, base->property); //cprintf(" plus = %08x\n", base + base->property); if (base->page_link.next != &free_list && base+base->property==p) { base->property += p->property; //cprintf("merge on the back: %d\n", p->property); ClearPageProperty(p); list_del(&(p->page_link)); //cprintf("flag = %d %d\n", base->flags, p->flags); flag = 1; } p = le2page((base->page_link.prev), page_link); //cprintf("base = %08x p = %08x size = %d\n", base, p, base->property); if (base->page_link.prev != &free_list && p+p->property==base) { p->property += base->property; //cprintf("merge on the front: %d\n", p->property); ClearPageProperty(base); list_del(&(base->page_link)); //cprintf("flag = %d %d\n", base->flags, p->flags); base = p; flag = 1; } } nr_free += n; //list_add(&free_list, &(base->page_link)); }
bool ScopeInsertSymbol(Scope scope, struct Symbol_* s) { ListHead *ptr,*head; head = &scope->scopelist; for(ptr = head->next; ptr != head; ptr = ptr->next) { Symbol csymbol = SSLEntry(ptr); if(strcmp(s->name, csymbol->name) == 0) return false; } list_add_before(head, &s->scopelist); return true; }
/* * Free a memory block owned by a given cookie. * Run some corruption checks. */ void olsr_cookie_free(struct olsr_cookie_info *ci, void *ptr) { struct olsr_cookie_mem_brand *branding; struct list_node *free_list_node; #ifdef OLSR_COOKIE_DEBUG bool reuse = false; #endif branding = (struct olsr_cookie_mem_brand *)ARM_NOWARN_ALIGN(((unsigned char *)ptr + ci->ci_size)); /* * Verify if there has been a memory overrun, or * the wrong owner is trying to free this. */ assert(!memcmp(&branding->cmb_sig, "cookie", 6) && branding->cmb_id == ci->ci_id); /* Kill the brand */ memset(branding, 0, sizeof(*branding)); /* * Rather than freeing the memory right away, try to reuse at a later * point. Keep at least ten percent of the active used blocks or at least * ten blocks on the free list. */ if ((ci->ci_free_list_usage < COOKIE_FREE_LIST_THRESHOLD) || (ci->ci_free_list_usage < ci->ci_usage / COOKIE_FREE_LIST_THRESHOLD)) { free_list_node = (struct list_node *)ptr; list_node_init(free_list_node); list_add_before(&ci->ci_free_list, free_list_node); ci->ci_free_list_usage++; #ifdef OLSR_COOKIE_DEBUG reuse = true; #endif } else { /* * No interest in reusing memory. */ free(ptr); } /* Stats keeping */ olsr_cookie_usage_decr(ci->ci_id); #ifdef OLSR_COOKIE_DEBUG OLSR_PRINTF(1, "MEMORY: free %s, %p, %u bytes%s\n", ci->ci_name, ptr, ci->ci_size, reuse ? ", reuse" : ""); #endif }
//static void default_free_pages(struct Page *base, size_t n) { assert(n > 0); assert(PageReserved(base)); //遍历空闲块链表,找到合适的位置插入回收的地址块 list_entry_t *le = &free_list; struct Page *page = NULL; //寻找第一个空闲块 while ((le = list_next(le)) != &free_list) { page = le2page(le, page_link); if (page > base) { break; } } //插入回收的空闲块:按页插入 for (page=base; page<(base+n); page++) { list_add_before(le, &(page->page_link)); } //重置该块的字段 base->flags = 0; base->property = n; set_page_ref(base, 0); ClearPageProperty(base); SetPageProperty(base); //尝试合并地址相连的空闲地址块 //先查看后一个空闲块 page = le2page(le, page_link); //得到后一个空闲块起始地址 if ((base+n) == page) { base->property += page->property; page->property = 0; } //后查看前一个空闲块 le = list_prev(&(base->page_link)); page = le2page(le, page_link); //此时并不是前一个空闲块,而是前一个page if ((le!= &free_list) && page == (base-1)) { while (le!= &free_list) { if (page->property > 0) { page->property += base->property; base->property =0; break; } le = list_prev(le); page = le2page(le, page_link); } } nr_free += n; return; }
/* * (3)_fifo_map_swappable: According FIFO PRA, we should link the most recent arrival page at the back of pra_list_head qeueue */ static int _extclock_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in) { list_entry_t *head=(list_entry_t*) mm->sm_priv; list_entry_t *entry=&(page->pra_page_link); assert(entry != NULL && head != NULL); //record the page access situlation /*LAB3 EXERCISE 2: 13307130148*/ //(1)link the most recent arrival page at the back of the pra_list_head qeueue. page->flags |= PTE_A; list_add_before(current_list_point, entry); page_count ++; return 0; }
static void insert_waiting_thread(struct semaphore *sem, struct thread *t) { struct thread *thread; #if defined(CONFIG_SCHEDULE_ROUND_ROBIN) || defined(CONFIG_SCHEDULE_RR_PRIO) list_add_tail(&sem->waiting_threads, &t->event_node); #elif defined(CONFIG_SCHEDULE_PRIORITY) list_for_every_entry(&sem->waiting_threads, thread, struct thread, event_node) if (t->priority > thread->priority) list_add_before(&thread->event_node, &t->event_node); #endif }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = p->property = 0; SetPageProperty(p); set_page_ref(p, 0); list_add_before(&free_list, &(p->page_link)); } nr_free += n; base->property = n; }
struct rt_info * sched_grma(struct list_head *head, struct global_sched_domain *g) { int count = 1, cpus = count_global_cpus(g); struct rt_info *it, *lowest = get_global_task(head->next); it = lowest; INIT_LIST_HEAD(&lowest->task_list[SCHED_LIST1]); list_for_each_entry_continue(it, head, task_list[GLOBAL_LIST]) { count++; list_add_before(lowest, it, SCHED_LIST1); if(count == cpus) break; }
static void default_init_memmap(struct Page *base, size_t n) { assert(n > 0); struct Page *p = base; for (; p != base + n; p ++) { assert(PageReserved(p)); p->flags = 0; // init p->flags as 0 SetPageProperty(p); // p->flags should be set bit PG_property p->property = 0; // p->property should be set to 0 set_page_ref(p, 0); // p->ref should be 0, because now p is free and no reference list_add_before(&free_list, &(p->page_link)); // link this page to free_list } base->property = n; // for the first page of free block, its property should be set to total num of block nr_free += n; // sum the number of free mem block }