int sched_tick() { pid pd; if (actual == NULL) { if (running_tasks <= 0) { pd = 0; } else { actual = first; pd = actual->pd; } } else { kassert(actual->quantum >= 0); if (actual->quantum > 0) { actual->quantum--; pd = actual->pd; } else { actual->quantum = SCHED_QUANTUM_DEFAULT; kassert(actual->next != NULL); actual = actual->next; pd = actual->pd; } } //print_queue(4); //breakpoint(); return pd; }
// make sure all the headers in freeMemList are sane and consitent int freeMemListOK(){ struct memHeader* lasthdr=NULL; struct memHeader* hdr = freeMemList; //are we at the head? kassert(freeMemList->prev == 0x0); // walk down freeMemList and check each memory block while (hdr->next){ memHeaderOK(hdr); hdr=hdr->next; //put the tail of freememlist into lasthdr if ((hdr)&&(hdr->next==NULL)&&(lasthdr==NULL)) lasthdr=hdr; } // walk back up the freeMemList while (lasthdr->prev!=NULL){ //memHeaderOK(lasthdr); lasthdr=lasthdr->prev; } // down and back the freeMemList, we should be back at start kassert(lasthdr==freeMemList); return 1; }
// TODO: This function shouldn't need to exist. Find another way vaddr_t vmm_km_heap_extend(size_t size) { vregion_t *region = &vmap_kernel()->regions[2]; kassert((UINT32_MAX - region->vend) > ROUND_PAGE(size)); vaddr_t prev_vend = region->vend; region->vend += ROUND_PAGE(size); for(vaddr_t va = prev_vend; va < region->vend; va += PAGESIZE) { // Allocate a free page if one should be available else panic paddr_t pa = pmm_alloc(); kassert(pa != UINTPTR_MAX); // TODO: Use pmap_enter here instead pmap_kenter_pa(va, pa, region->vm_prot, PMAP_WIRED | PMAP_WRITE_COMBINE); // Enter the information into the amap region->aref.amap->aslots[(uint32_t)((double)(va-region->vstart)/(double)PAGESIZE)]->page->vaddr = va; } memset((vaddr_t*)prev_vend, 0, PAGESIZE); vmap_kernel()->heap_end = region->vend; uint32_t new_size = region->vend - region->vstart; region->aref.amap->maxslots = region->aref.amap->nslots = (uint32_t)((double)new_size/(double)PAGESIZE); return prev_vend; }
static T& HandleFault(EbbId id) { kassert(id == T::static_id); { // acquire read only to find rep LocalIdMap::const_accessor accessor; auto found = local_id_map->find(accessor, id); kassert(found); auto rep_map = boost::any_cast<rep_map_t>(accessor->second); auto it = rep_map.find(my_cpu()); if (it != rep_map.end()) { cache_ref(id, *it->second); return *it->second; } } // we failed to find a rep, we must construct one auto rep = new T; //TODO: make the rep_map thread safe so we can acquire r/o access LocalIdMap::accessor accessor; auto found = local_id_map->find(accessor, id); kassert(found); auto rep_map = boost::any_cast<rep_map_t>(accessor->second); rep_map[my_cpu()] = rep; cache_ref(id, *rep); return *rep; }
/** スレッドキューが空であることを確認する @param[in] q 確認対象キュー @note キュー q のロックを呼出元で獲得して呼び出すこと */ bool tq_is_empty(thread_queue *q) { kassert( q != NULL); kassert( spinlock_locked_by_self(&q->lock) ); return queue_is_empty( &q->que ); /* キューが空である場合は真を返す */ }
inline size_t ref_count (frame_t frame) { kassert (frame >= begin_ && frame < end_); frame_entry_t idx = frame - begin_; /* Frame is allocated. */ kassert (entry_[idx] < 0); return -entry_[idx]; }
void pmap_destroy(pmap_t *pmap) { kassert(pmap != NULL); atomic_dec(&pmap->refcount); // The kernel's pmap should never be 0!! Something is f*****g up kassert(pmap->refcount == 0 && pmap == pmap_kernel()); // TODO: Deallocate resources for pmap if refcount is 0 }
void np_b_nc_input3 (bid_t b) { char* c = static_cast<char*> (syscall::buffer_map (b)); kassert (c != 0); kassert (strcmp (c, "ap_b_nc_output") == 0); kout << "\t" << __func__; no_schedule (); no_finish (); }
void ap_nb_c_input3 (aid_t p, aid_t v) { kassert (p == ap_nb_c_input3_parameter); kassert (v == ap_nb_c_output_value); kout << "\t" << __func__; no_schedule (); no_finish (); }
/** 仮想アドレス空間上のアドレスへカーネル空間の内容をコピーする @param[in] as コピー先の仮想アドレス空間 @param[in] dest コピー先のアドレス @param[in] src コピー元のアドレス @param[in] count コピーするバイト数 @return コピーしたバイト数 @return -EFAULT ページが存在しない */ int vm_copy_out(vm *as, void *dest, const void *src, size_t count) { int rc; kassert( as != NULL ); kassert( as->p != NULL ); if ( current->p != hal_refer_kernel_proc() ) { /* ユーザからのコピー */ if ( (uintptr_t)src < KERN_VMA_BASE ) { /* * ユーザプロセス間コピー */ rc = inter_user_copy(as, ¤t->p->vm, dest, src, count); if ( rc < 0 ) return rc; count = rc; goto copy_end; } } mutex_lock( &as->asmtx ); /* * カーネルからのコピー */ if ( as->p == hal_refer_kernel_proc() ) goto copy_ok; /* カーネルへのコピーなのでアクセス可能 */ /* * コピー先ユーザアドレスの妥当性確認 */ if ( ( (uintptr_t)dest ) >= KERN_VMA_BASE ) { rc = -EFAULT; goto error_out; } if ( !user_area_can_access_nolock(as, (void *)dest, count, VMA_PROT_W ) ) { rc = -EFAULT; goto error_out; } copy_ok: memcpy(dest, src, count); mutex_unlock( &as->asmtx ); copy_end: return count; error_out: mutex_unlock( &as->asmtx ); return rc; }
inline size_t incref (frame_t frame, size_t count) { kassert (frame >= begin_ && frame < end_); frame_entry_t idx = frame - begin_; /* Frame is allocated. */ kassert (entry_[idx] < 0); /* "Increment" the reference count. */ return -(entry_[idx] -= count); }
static inline void remove_automaton (const shared_ptr<automaton>& a) { context_map_type::iterator pos = context_map_.find (a); kassert (pos != context_map_.end ()); automaton_context* c = pos->second; kassert (c != 0); context_map_.erase (pos); ready_queue_.erase (c); delete c; }
/** スレッドキューにスレッドを追加する @param[in] q 追加先のスレッドキュー @param[in] thr 追加するスレッド @retval 追加後のスレッド格納数 @note キュー q のロックを呼出元で獲得して呼び出すこと */ int tq_add(thread_queue *q, struct _thread *thr) { kassert( q != NULL); kassert( thr != NULL); kassert( spinlock_locked_by_self( &q->lock ) ); queue_add( &q->que, &thr->link ); /* キューにスレッドを追加する */ ++q->cnt; /* キュー中のスレッド数をインクリメントする */ return q->cnt; /* 追加後のスレッド数を返却する */ }
/** スレッドキューからスレッドを取り外す @param[in] q 操作対象のスレッドキュー @param[in] thr 取り除くするスレッド @note キュー q のロックを呼出元で獲得して呼び出すこと */ int tq_del(thread_queue *q, struct _thread *thr) { kassert( q != NULL); kassert( thr != NULL); kassert( spinlock_locked_by_self( &q->lock ) ); list_del( &thr->link ); /* スレッドをキューから取り除く */ --q->cnt; /* 取り出し後のキュー内のスレッド数を減算する */ return q->cnt; /* 取り外した後のスレッド数を返却する */ }
void ap_b_nc_input3 (aid_t p, bid_t b) { kassert (p == ap_b_nc_input3_parameter); kout << "\t" << __func__; char* c = static_cast<char*> (syscall::buffer_map (b)); kassert (c != 0); kassert (strcmp (c, "ap_b_nc_output") == 0); no_schedule (); no_finish (); }
void np_b_c_input2 (bid_t b, aid_t v) { kassert (v == p_b_c_output_value); char* c = static_cast<char*> (syscall::buffer_map (b)); kassert (c != 0); kassert (strcmp (c, "p_b_c_output") == 0); kout << "\t" << __func__; no_schedule (); no_finish (); }
/** バディページから所定のオーダのページを取り出しページフレーム番号を返す @param[in] buddy バディページ @param[in] order 取得するページのオーダ @param[out] pfnp 取得したページのページフレーム番号を返却する領域 @retval 0 正常にページを獲得した @retval -EINVAL ページフレーム情報返却域が不正か要求したページオーダが不正 @retval -ENOMEM 空きページがない */ int page_buddy_dequeue(page_buddy *buddy, page_order order, obj_cnt_type *pfnp){ page_order cur_order; page_frame *cur_page; kassert( spinlock_locked_by_self(&buddy->lock) ); if ( (pfnp == NULL) || (order >= PAGE_POOL_MAX_ORDER) ) return -EINVAL; /* ページフレーム情報返却域 or 要求したページオーダが不正 */ cur_order = order; while (cur_order < PAGE_POOL_MAX_ORDER) { /* 空きページがあるキューを順番に調べる */ if ( !queue_is_empty(&buddy->page_list[cur_order]) ) { cur_page = CONTAINER_OF( queue_get_top(&buddy->page_list[cur_order]), page_frame, link); /* 空きページを取り出す */ --buddy->free_nr[cur_order]; /* 空きページから要求オーダのページを切り出す */ cur_page = remove_page_from_page_queue(buddy, cur_page, order, cur_order); cur_page->state |= PAGE_CSTATE_USED; /* ページを使用中にする */ *pfnp = cur_page->pfn; /* ページフレーム番号を返却する */ if ( cur_page->order != order ) { /* ページオーダが一致しない場合は内部整合性異常 */ kprintf(KERN_CRI, "Invalid order page is allocated:%p " "pfn:%u flags=%x order:%d reqest-order:%d find:%d\n", cur_page, cur_page->pfn, cur_page->state, cur_page->order, order, cur_order); kassert(0); } kassert( ( buddy->start_pfn <= cur_page->pfn ) && ( cur_page->pfn < ( buddy->start_pfn + buddy->nr_pages ) ) ); return 0; } ++cur_order; /* より上のオーダからページを切り出す */ } return -ENOMEM; }
/** スレッドキューの先頭のスレッドを取り出す @param[in] q 操作対象キュー @param[in] thrp キューの先頭スレッドを設定するポインタ変数のアドレス @retval 取り出し後のスレッド格納数 @note キュー q のロックを呼出元で獲得しておき, キューが 空でないことを呼出元責任で保証すること */ int tq_get_top(thread_queue *q, struct _thread **thrp) { kassert( q != NULL); kassert( spinlock_locked_by_self( &q->lock ) ); kassert( !queue_is_empty( &q->que ) ); *thrp = CONTAINER_OF( queue_get_top( &q->que ), thread, link); /* キューからスレッドを取り出す */ --q->cnt; /* 取り出し後のキュー内のスレッド数を減算する */ return q->cnt; /* 取り出し後のキュー内のスレッド数を返却する */ }
void Box2dJointComponent::OnInitialise() { b2RevoluteJointDef& jointDef = static_cast<b2RevoluteJointDef&>(*mJointDef); std::shared_ptr<k::SceneNode> bodyANode = GetSceneNode().GetRootParent()->FindFirstInChildrenRecursive(mBodyA.c_str()); kassert(&*bodyANode); jointDef.bodyA = &bodyANode->GetSceneObject().GetComponent<Box2dBodyComponent>("Box2dBodyComponent")->GetBody(); std::shared_ptr<k::SceneNode> bodyBNode = GetSceneNode().GetRootParent()->FindFirstInChildrenRecursive(mBodyB.c_str()); kassert(&*bodyBNode); jointDef.bodyB = &bodyBNode->GetSceneObject().GetComponent<Box2dBodyComponent>("Box2dBodyComponent")->GetBody(); mJoint = mWorldComponent.lock()->GetWorld().CreateJoint(&jointDef); mJointDef = nullptr; }
void ap_b_c_input1 (aid_t p, bid_t b, aid_t v) { kassert (p == ap_b_c_input1_parameter); kassert (v == np_b_c_output_value); char* c = static_cast<char*> (syscall::buffer_map (b)); kassert (c != 0); kassert (strcmp (c, "np_b_c_output") == 0); kout << "\t" << __func__; no_schedule (); no_finish (); }
/** バディからページを取り出す @param[in] buddy バディページプール管理情報 @param[in] rm_page バディから取り出した要求オーダ以上で最初に見つかった空きページ @param[in] request_order 要求ページオーダ @param[in] cur_order rm_pageのページオーダ @return 返却する要求ページオーダのページに対するページフレーム情報 @note 取得したページを1対のバディの組みとみなし, 前半をページキューに追加 後半を次のオーダのキューに追加する処理を要求されたオーダになるまで 繰り返す(最初のページの最後尾から要求オーダ分のページを返却する) */ static page_frame * remove_page_from_page_queue(page_buddy *buddy, page_frame *rm_page, page_order request_order, page_order cur_order){ size_t size; queue *pg_queue; kassert(rm_page->order == cur_order); /* 申告されたオーダが正しいことを確認 */ pg_queue = &buddy->page_list[cur_order]; /* ページを取り出したキューを参照 */ size = 1 << cur_order; /* ページオーダからページサイズを算出 */ while (cur_order > request_order) { /* 要求より大きいページを切り出した場合 */ --cur_order; /* ページオーダを一つ下げる */ pg_queue = &buddy->page_list[cur_order]; /* 操作対象のページキューを更新 */ size >>= 1; /* ページサイズを更新 */ rm_page->order = cur_order; /* 取り出したページのページオーダを更新 */ kassert( !PAGE_CSTATE_NOT_FREED(rm_page) ); queue_add(pg_queue, &rm_page->link); /* ページをキューに追加 */ ++buddy->free_nr[cur_order]; #if defined(DEQUEUE_PAGE_DEBUG) kprintf(KERN_DBG, "add %p (next:%p, count:%d) to %p size %u " "order:%d[%u] req:%d \n", rm_page, rm_page + size, (int)(((void *)(rm_page + size) - (void *)rm_page)/sizeof(page_frame)), pg_queue, (unsigned int)size, (int)cur_order, (unsigned int)buddy->free_nr[cur_order], (int)request_order); #endif /* KERN_DEQUEUE_PAGE_DEBUG */ rm_page += size; /* 取り出したページのバディ(対向ページ)を参照 */ rm_page->order = cur_order; /* バディ側のページオーダを更新 */ } if ( rm_page->state & PAGE_CSTATE_RESERVED ) { /* 予約ページが含まれる場合は, PANIC */ kprintf(KERN_CRI, "Reserved page is dequeued in remove from page queue: " "%p pfn:%u flags=%x\n", rm_page, rm_page->pfn, rm_page->state); kassert(0); } return rm_page; }
inline size_t decref (frame_t frame) { kassert (frame >= begin_ && frame < end_); frame_entry_t idx = frame - begin_; /* Frame is allocated. */ kassert (entry_[idx] < 0); /* "Decrement" the reference count. */ size_t retval = -(++entry_[idx]); /* Free the frame. */ if (entry_[idx] == 0) { entry_[idx] = free_head_; free_head_ = idx; } return retval; }
static inline pte_t pte_create(uintptr_t ppn, int prot, int user) { pte_t pte = (ppn << PTE_PPN_SHIFT) | PTE_V; prot &= PROT_READ|PROT_WRITE|PROT_EXEC; if (user) { switch (prot) { case PROT_NONE: pte |= PTE_TYPE_SR; break; case PROT_READ: pte |= PTE_TYPE_UR_SR; break; case PROT_WRITE: pte |= PTE_TYPE_URW_SRW; break; case PROT_EXEC: pte |= PTE_TYPE_URX_SRX; break; case PROT_READ|PROT_WRITE: pte |= PTE_TYPE_URW_SRW; break; case PROT_READ|PROT_EXEC: pte |= PTE_TYPE_URX_SRX; break; case PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_URWX_SRWX; break; case PROT_READ|PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_URWX_SRWX; break; } } else { switch (prot) { case PROT_NONE: kassert(0); break; case PROT_READ: pte |= PTE_TYPE_SR; break; case PROT_WRITE: pte |= PTE_TYPE_SRW; break; case PROT_EXEC: pte |= PTE_TYPE_SRX; break; case PROT_READ|PROT_WRITE: pte |= PTE_TYPE_SRW; break; case PROT_READ|PROT_EXEC: pte |= PTE_TYPE_SRX; break; case PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_SRWX; break; case PROT_READ|PROT_WRITE|PROT_EXEC: pte |= PTE_TYPE_SRWX; break; } } return pte; }
vm_area_base (logical_address_t begin, logical_address_t end) : begin_ (begin), end_ (end) { kassert (begin_ <= end_); }
void Block::updateRefCount( uint64_t i_vaddr, PageTableManager::UsageStats_t i_stats ) { // Check containment, call down chain if address isn't in this block. if (!isContained(i_vaddr)) { if (iv_nextBlock) { iv_nextBlock->updateRefCount(i_vaddr, i_stats); } else { // No block owns this address. Code bug. printk("updateRefCount> i_vaddr=0x%.lX\n", i_vaddr ); kassert(iv_nextBlock); } return; } ShadowPTE* spte = getPTE(i_vaddr); // Adjust the LRU statistics if( i_stats.R ) { spte->zeroLRU(); } else { spte->incLRU(); } }
vaddr_t vmm_km_zalloc(size_t size) { // Pre kernel heap unmanaged memory allocator // This should not only be used before kheap_init has been called static vaddr_t placement_addr = 0; if(placement_addr == 0) { pmap_virtual_space(NULL, &kernel_vend); placement_addr = kernel_vend; } // Make sure enough memory is left! kassert((UINT32_MAX-placement_addr) >= size); vaddr_t start = placement_addr; vaddr_t end = placement_addr + size; // Allocate a new page if there is not enough memory if(end >= kernel_vend) { // Loop through and allocate pages until we have enough memory to serve the requested size for( ; kernel_vend < end; kernel_vend+=PAGESIZE) { paddr_t pa = pmm_alloc(); pmap_kenter_pa(kernel_vend, pa, VM_PROT_DEFAULT, PMAP_WRITE_BACK); } } // Zero the memory memset((void*)placement_addr, 0x0, size); placement_addr = end; return(start); }
vaddr_t pmap_steal_memory(size_t vsize) { // pmap_init must be called before this function can be used, otherwise // kernel_vend will be an incorrect value // kernel_vend and kernel_pend should be page aligned // This function should only be used before pmm_init is called static vaddr_t placement_addr = 0; placement_addr = (placement_addr == 0) ? kernel_vend : placement_addr; // Make sure enough memory is left! kassert((UINT32_MAX-placement_addr) >= vsize); vaddr_t start = placement_addr; vaddr_t end = placement_addr + vsize; // Allocate a new page if there is not enough memory if(end >= kernel_vend) { // Loop through and map the pages using pmap_kenter_pa while incrementing kernel_pend and kernel_vend for(; kernel_vend < end; kernel_vend+=PAGESIZE, kernel_pend+=PAGESIZE) { pmap_kenter_pa(kernel_vend, kernel_pend, VM_PROT_DEFAULT, PMAP_WRITE_BACK); } } // Zero the memory memset((void*)placement_addr, 0x0, vsize); placement_addr = end; return(start); }
static uintptr_t __page_alloc() { kassert(next_free_page != free_pages); uintptr_t addr = first_free_page + RISCV_PGSIZE * next_free_page++; memset((void*)addr, 0, RISCV_PGSIZE); return addr; }
void sched_load(pid pd) { kassert(pd >= 0 && pd < MAX_PID); int i; for (i = 0 ; i < MAX_PID ; i++) { if (tasks[i].pd == FREE_PID) { break; } } kassert_verbose(i != MAX_PID, "Scheduler run out of task slots!!!"); sched_task* tmp_task = &tasks[i]; tasks[i].pd = pd; tasks[i].quantum = SCHED_QUANTUM_DEFAULT; if (running_tasks == 0) { tasks[i].next = tmp_task; tasks[i].prev = tmp_task; last = tmp_task; first = tmp_task; } else { tasks[i].next = first; tasks[i].prev = last; last->next = tmp_task; if (last->prev == last) { last->prev = tmp_task; } last = tmp_task; } first->prev = last; running_tasks++; }
int sched_exit() { kassert(running_tasks > 0); pid pd; if (running_tasks > 1) { if (first->pd == actual->pd) { first = actual->next; } if (last->pd == actual->pd) { last = actual->prev; } sched_task* tmp_next = actual->next; (actual->prev)->next = actual->next; (actual->next)->prev = actual->prev; memset(actual, 0, sizeof(sched_task)); sched_task* old = actual; actual = tmp_next; pd = actual->pd; old->pd = FREE_PID; } else { memset(actual, 0, sizeof(sched_task)); actual->pd = FREE_PID; first = NULL; last = NULL; actual = NULL; pd = 0; } running_tasks--; return pd; }