ER act_tsk(ID tskid) { ER ercd; uint_t itskpri; LOG_ACT_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); itskpri = get_ipri_self(tskid); t_lock_cpu(); if (test_dormant(itskpri)) { if(make_active(itskpri)) { run_task(itskpri); } ercd = E_OK; } else { ercd = E_QOVR; } t_unlock_cpu(); error_exit: LOG_ACT_TSK_LEAVE(ercd); return(ercd); }
/* * タスク管理モジュールの初期化 */ void initialize_task(void) { uint_t i, j; TCB *p_tcb; p_runtsk = NULL; p_schedtsk = NULL; reqflg = false; ipmflg = true; disdsp = false; dspflg = true; for (i = 0; i < TNUM_TPRI; i++) { queue_initialize(&(ready_queue[i])); } ready_primap = 0U; for (i = 0; i < tnum_tsk; i++) { j = INDEX_TSK(torder_table[i]); p_tcb = &(tcb_table[j]); p_tcb->p_tinib = &(tinib_table[j]); p_tcb->actque = false; make_dormant(p_tcb); queue_initialize(&(p_tcb->mutex_queue)); if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) { (void) make_active(p_tcb); } } }
FB::VariantMap ProfileManager::delete_profile(FB::DOM::WindowPtr window, std::string profilename) { profile_ptr p = unlock_profile(window, profilename); Profile *istore = p.get(); FB::VariantMap result; if (!istore) { result["error"] = true; result["error_msg"] = "Could not unlock profile"; } else { // delete profile entry profiles.erase(profilename); // delete file itself fs::path profilepath = broadmask_root(); profilepath /= profilename; fs::remove_all(profilepath); // p == active_profile p.reset(); make_active(p); result["error"] = false; ProfileManager::archive(this); } return result; }
ER iact_tsk(ID tskid) { ER ercd; uint_t itskpri; LOG_IACT_TSK_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); itskpri = get_ipri(tskid); i_lock_cpu(); if (test_dormant(itskpri)) { if(make_active(itskpri)) { reqflg = true; } ercd = E_OK; } else { ercd = E_QOVR; } i_unlock_cpu(); error_exit: LOG_IACT_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; bool_t dspreq = false; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); CHECK_NONSELF(p_tcb); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn2)) { ercd = E_OACV; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * p_tcbは自タスクでないため,(シングルプロセッサでは)実 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ * チが必要になることはない. */ (void) make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } if (!queue_empty(&(p_tcb->mutex_queue))) { if ((*mtxhook_release_all)(p_tcb)) { dspreq = true; } } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; if (make_active(p_tcb)) { dspreq = true; } } if (dspreq) { dispatch(); } ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); if (t_sense_lock()) { /* * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し * てからタスクを終了する.実装上は,サービスコール内でのCPU * ロックを省略すればよいだけ. */ } else { t_lock_cpu(); } if (disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ * チ許可状態にしてからタスクを終了する. */ disdsp = false; } if (!ipmflg) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す * る. */ t_set_ipm(TIPM_ENAALL); ipmflg = true; } dspflg = true; (void) make_non_runnable(p_runtsk); if (!queue_empty(&(p_runtsk->mutex_queue))) { (void) (*mtxhook_release_all)(p_runtsk); } #ifdef TOPPERS_SUPPORT_OVRHDR ovrtimer_stop(); #endif /* TOPPERS_SUPPORT_OVRHDR */ make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; (void) make_active(p_runtsk); } exit_and_dispatch(); ercd = E_SYS; error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); if (t_sense_lock()) { /* * CPUロック状態でext_tskが呼ばれた場合は,CPUロックを解除し * てからタスクを終了する.実装上は,サービスコール内でのCPU * ロックを省略すればよいだけ. */ } else { t_lock_cpu(); } if (disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合は,ディスパッ * チ許可状態にしてからタスクを終了する. */ disdsp = false; } if (t_get_ipm() != TIPM_ENAALL) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tsk * が呼ばれた場合は,IPMをTIPM_ENAALLにしてからタスクを終了す * る. */ t_set_ipm(TIPM_ENAALL); } dspflg = true; (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; (void) make_active(p_runtsk); } exit_and_dispatch(); return(E_SYS); error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER mact_tsk(ID tskid, ID prcid) { TCB *p_tcb; ER ercd; PCB *t_p_pcb; PCB *f_p_pcb; bool_t dspreq = false; LOG_MACT_TSK_ENTER(tskid, prcid); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); CHECK_PRCID_INI(prcid); t_lock_cpu(); p_tcb = get_tcb_self(tskid, get_my_p_pcb()); prcid = (prcid == TPRC_INI)? p_tcb->p_tinib->iaffinity : prcid; T_CHECK_MIG(p_tcb->p_tinib->affinity_mask, prcid); /* 現在割り付けられているプロセッサと移動先のプロセッサのタスクロックを取得 */ t_acquire_dual_tsk_lock(p_tcb, prcid, &f_p_pcb, &t_p_pcb); if (TSTAT_DORMANT(p_tcb->tstat)) { LOG_TSKMIG(p_tcb, f_p_pcb->prcid, prcid); p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { dspreq = dispatch_request(t_p_pcb); } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; p_tcb->actprc = prcid; ercd = E_OK; } else { ercd = E_QOVR; } release_dual_tsk_lock(f_p_pcb, t_p_pcb); if (dspreq) { dispatch(); } t_unlock_cpu(); error_exit: LOG_MACT_TSK_LEAVE(ercd); return(ercd); }
ER act_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_ACT_TSK_ENTER(tskid); CHECK_UNL(); /*[NGKI1114]*/ if (tskid == TSK_SELF && !sense_context()) { p_tcb = p_runtsk; /*[NGKI1121]*/ } else { CHECK_ID(VALID_TSKID(tskid)); /*[NGKI1115]*/ p_tcb = get_tcb(tskid); } lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; /*[NGKI1116]*/ } else if (TSTAT_DORMANT(p_tcb->tstat)) { make_active(p_tcb); /*[NGKI1118]*/ if (p_runtsk != p_schedtsk) { if (!sense_context()) { dispatch(); } else { request_dispatch(); } } ercd = E_OK; } else if ((p_tcb->p_tinib->tskatr & TA_NOACTQUE) != 0U || p_tcb->actque) { ercd = E_QOVR; /*[NGKI3528]*/ } else { p_tcb->actque = true; /*[NGKI3527]*/ ercd = E_OK; } unlock_cpu(); error_exit: LOG_ACT_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); CHECK_NONSELF(p_tcb); t_lock_cpu(); if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * p_tcbは自タスクでないため,(シングルプロセッサでは)実 * 行状態でなく,make_non_runnable(p_tcb)でタスクディスパッ * チが必要になることはない. */ (void) make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; if (make_active(p_tcb)) { dispatch(); } } ercd = E_OK; } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER imact_tsk(ID tskid, ID prcid) { TCB *p_tcb; ER ercd; PCB *t_p_pcb; PCB *f_p_pcb; LOG_IMACT_TSK_ENTER(tskid, prcid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); CHECK_PRCID_INI(prcid); p_tcb = get_tcb(tskid); prcid = (prcid == TPRC_INI)? p_tcb->p_tinib->iaffinity : prcid; CHECK_MIG(p_tcb->p_tinib->affinity_mask, prcid); i_lock_cpu(); /* 現在割り付けられているプロセッサと移動先のプロセッサのタスクロックを取得 */ i_acquire_dual_tsk_lock(p_tcb, prcid, &f_p_pcb, &t_p_pcb); if (TSTAT_DORMANT(p_tcb->tstat)) { LOG_TSKMIG(p_tcb, f_p_pcb->prcid, prcid); p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { if (dispatch_request(t_p_pcb)) { t_p_pcb->reqflg = true; } } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; p_tcb->actprc = prcid; ercd = E_OK; } else { ercd = E_QOVR; } release_dual_tsk_lock(f_p_pcb, t_p_pcb); i_unlock_cpu(); error_exit: LOG_IMACT_TSK_LEAVE(ercd); return(ercd); }
uint64_t timer__request_impl(CORBA_Object _caller, objref_t timer_obj, uint64_t time, int flags, idl4_server_environment * _env) { struct timer *timer = (struct timer *)timer_obj; struct driver *device = timer->timer_service->device; uint64_t abs_time; int is_earliest; if (timer->state != timer_cancelled_e) { /* We need to cancel the timer first */ timer__cancel_impl(_caller, timer_obj, _env); } abs_time = time; if (!(flags & TIMER_ABSOLUTE)) { abs_time += timer_current_time(device); } if (flags & TIMER_PERIODIC) { if (flags & TIMER_ABSOLUTE) { return -1; } timer->state = timer_periodic_e; timer->period = time; } else { timer->state = timer_oneshot_e; } timer->timeout = abs_time; is_earliest = make_active(timer); // debug_active(timer); /* Set a request for that point in time */ if (is_earliest) { if (timer_timeout (device, abs_time, timer_callback, 0, (uintptr_t)timer)) { timer_callback(0, 0, NULL, (uintptr_t)timer); } } return abs_time; }
SYSCALL ER ter_tsk(ID tskid) { TCB *tcb; UINT tstat; ER ercd; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); tcb = get_tcb(tskid); CHECK_NONSELF(tcb); t_lock_cpu(); if (TSTAT_DORMANT(tstat = tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(tstat)) { make_non_runnable(tcb); } else if (TSTAT_WAITING(tstat)) { wait_cancel(tcb); } make_dormant(tcb); if (tcb->actcnt) { tcb->actcnt = FALSE; if (make_active(tcb)) { dispatch(); } } ercd = E_OK; } t_unlock_cpu(); exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER act_tsk(ID tskid) { TCB *p_tcb; ER ercd; bool_t dspreq = false; PCB *p_pcb; LOG_ACT_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); t_lock_cpu(); p_tcb = get_tcb_self(tskid, get_my_p_pcb()); p_pcb = t_acquire_tsk_lock(p_tcb); if (TSTAT_DORMANT(p_tcb->tstat)) { if (make_active(p_tcb)) { dspreq = dispatch_request(p_pcb); } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; ercd = E_OK; } else { ercd = E_QOVR; } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } t_unlock_cpu(); error_exit: LOG_ACT_TSK_LEAVE(ercd); return(ercd); }
bool ProfileManager::is_active_and_valid (std::string profilename) { if (!active_profile.get() || !cached_at) return false; // No profile cached if (profilename.compare(active_profile->profilename()) != 0) return false; // Different profile cached // compare cache time int cache_hold = 7200; // 2 hours time_t current = time (NULL); if (current > (cached_at + cache_hold)) { // Store and invalidate cache store_active(); active_profile.reset(); make_active(active_profile); return false; } // Profile matches and is valid return true; }
ER act_tsk(ID tskid) { TCB *p_tcb; ER ercd; LOG_ACT_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID_SELF(tskid); p_tcb = get_tcb_self(tskid); t_lock_cpu(); if (p_tcb->p_tinib->tskatr == TA_NOEXS) { ercd = E_NOEXS; } else if (VIOLATE_ACPTN(p_tcb->p_tinib->acvct.acptn1)) { ercd = E_OACV; } else if (TSTAT_DORMANT(p_tcb->tstat)) { if (make_active(p_tcb)) { dispatch(); } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; ercd = E_OK; } else { ercd = E_QOVR; } t_unlock_cpu(); error_exit: LOG_ACT_TSK_LEAVE(ercd); return(ercd); }
ER iact_tsk(ID tskid) { TCB *p_tcb; ER ercd; PCB *p_pcb; LOG_IACT_TSK_ENTER(tskid); CHECK_INTCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); i_lock_cpu(); p_pcb = i_acquire_tsk_lock(p_tcb); if (TSTAT_DORMANT(p_tcb->tstat)) { if (make_active(p_tcb)) { if (dispatch_request(p_pcb)) { p_pcb->reqflg = true; } } ercd = E_OK; } else if (!(p_tcb->actque)) { p_tcb->actque = true; ercd = E_OK; } else { ercd = E_QOVR; } release_tsk_lock(p_pcb); i_unlock_cpu(); error_exit: LOG_IACT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; PCB *t_p_pcb; PCB *my_p_pcb; TCB *p_runtsk; bool_t locked; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); /* * CPUロック状態でext_tskが呼ばれた場合は,ロック取得時に割込みを許可 * しない. * ロック取得時に割込みを許可しないのは, 過度状態の場合にロックを取得 * できなかった場合に割込みを許可すると,割込みが入りサスペンド状態と * なってしまうためである. */ locked = t_sense_lock(); retry: if (locked) { my_p_pcb = acquire_tsk_lock_without_preemption_self(); } else { t_lock_cpu(); my_p_pcb = t_acquire_tsk_lock_self_without_runnable_check(); } p_runtsk = my_p_pcb->p_runtsk; /* 再起動時のマイグレーションなし */ if ((p_runtsk->actprc == TPRC_NONE) || (p_runtsk->actprc == my_p_pcb->prcid)) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合に対応して,ディスパッ * チ許可状態にしてからタスクを終了する. */ my_p_pcb->disdsp = false; /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tskが呼ばれ * た場合に対応して,IPMをTIPM_ENAALLにしてからタスクを終了する. */ t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; my_p_pcb->dspflg = true; /* * スピンロックを取得している場合は,スピンロックを解除する */ force_unlock_spin(my_p_pcb); (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; p_runtsk->actprc = TPRC_NONE; (void) make_active(p_runtsk); } release_tsk_lock(my_p_pcb); exit_and_dispatch(); ercd = E_SYS; } else { /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_runtsk->actprc); /* 一旦タスクロックを離す */ release_tsk_lock(my_p_pcb); /* * 現在割り付けられているプロセッサと移動先のプロセッサのタスク * ロックを取得 */ if (locked) { acquire_dual_tsk_lock_without_preemption(p_runtsk, p_runtsk->actprc, &my_p_pcb, &t_p_pcb); } else { t_acquire_dual_tsk_lock(p_runtsk, p_runtsk->actprc, &my_p_pcb, &t_p_pcb); } /* * マイグレーション先のプロセッサが変更された場合はリトライ */ if (p_runtsk->actprc != t_p_pcb->prcid) { release_dual_tsk_lock(p_runtsk->p_pcb, t_p_pcb); goto retry; } /* * ここで各カーネル状態を変更するのは,ディスパッチ禁止状態と割込 * み優先度マスク全解除状態でない状態による過度状態の場合に,各カ * ーネル状態を変更してから,ロック取得関数で割込みを許可して割込 * みが入ると,割込みからのリターン時にディスパッチャが呼ばれてし * まい,休止状態となるためである. */ my_p_pcb->disdsp = false; t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; my_p_pcb->dspflg = true; force_unlock_spin(my_p_pcb); /* 現在コンテキストを捨ててマイグレーション */ exit_and_migrate(p_runtsk->actprc); ercd = E_SYS; } error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
ER ext_tsk(void) { ER ercd; PCB *my_p_pcb; TCB *p_runtsk; LOG_EXT_TSK_ENTER(); CHECK_TSKCTX(); /* * CPUロック状態でext_tskが呼ばれた場合は,ロック取得時に割込みを許可 * しない. * ロック取得時に割込みを許可しないのは, 過度状態の場合にロックを取得 * できなかった場合に割込みを許可すると,割込みが入りサスペンド状態と * なってしまうためである. * ディスパッチ禁止や割込み優先度マスク全解除状態でない場合の過度状態の * 場合は,割込みが入っても割込みの出口でディスパッチャに行かずに戻って * くるため問題ない. */ if (t_sense_lock()) { my_p_pcb = acquire_tsk_lock_without_preemption_self(); } else { t_lock_cpu(); my_p_pcb = t_acquire_tsk_lock_self_without_runnable_check(); } p_runtsk = my_p_pcb->p_runtsk; if (my_p_pcb->disdsp) { /* * ディスパッチ禁止状態でext_tskが呼ばれた場合に対応して,ディスパッ * チ許可状態にしてからタスクを終了する. */ my_p_pcb->disdsp = false; } if (!my_p_pcb->ipmflg) { /* * 割込み優先度マスク(IPM)がTIPM_ENAALL以外の状態でext_tskが呼ばれ * た場合に対応して,IPMをTIPM_ENAALLにしてからタスクを終了する. */ t_set_ipm(TIPM_ENAALL); my_p_pcb->ipmflg = true; } my_p_pcb->dspflg = true; /* * スピンロックを取得している場合は,スピンロックを解除する */ force_unlock_spin(my_p_pcb); /* 再起動時のマイグレーションなし */ if ((p_runtsk->actprc == TPRC_NONE) || (p_runtsk->actprc == my_p_pcb->prcid)) { (void) make_non_runnable(p_runtsk); make_dormant(p_runtsk); if (p_runtsk->actque) { p_runtsk->actque = false; p_runtsk->actprc = TPRC_NONE; (void) make_active(p_runtsk); } release_tsk_lock(my_p_pcb); exit_and_dispatch(); ercd = E_SYS; } else { /* 現在コンテキストを捨ててマイグレーション */ exit_and_migrate(p_runtsk->actprc); ercd = E_SYS; } error_exit: LOG_EXT_TSK_LEAVE(ercd); return(ercd); }
int pretest(void) { unsigned int i; int ret = 0; /* anchor_t processing test */ { struct anchor_struct anch_st = { 0x1234, 0x3, 0x11, 0xA }; anchor_t anch; make_anchor(&anch_st, &anch); extract_anchor(&anch_st, &anch); } /* active_t processing test */ for (i = 0; i < 100; i++) { struct active_struct act_st; active_t act; void *p; p = memalign(4096,32); act_st.addr = p; act_st.credits = i; make_active(&act_st, &act); extract_active(&act_st, &act); if (__ull(act_st.addr) != (u64)p) { DPRINTF("ERROR TO SET ACTIVE-ADDRESS<%p != %p>\n", p, act_st.addr); free(p); ret = 1; goto PRETEST_FAIL; } if (__ull(act_st.credits) != (i & ACTIVE_CREDITS_MASK)) { DPRINTF("ERROR TO SET ACTIVE-CREDITS<%lu>\n", act_st.credits); free(p); ret = 2; goto PRETEST_FAIL; } free(p); } return 0; PRETEST_FAIL: return ret; }
void *alloc_active(procheap_t *fromheap) { active_t old_active, new_active; struct active_struct new_active_st; desc_t *desc; struct anchor_struct old_anchor_st, new_anchor_st; anchor_t old_anchor, new_anchor; void *addr = NULL; size_t next_index; // // <1> reserve block // // other thread can change active, this loop must read active // repeatly. DPRINTF("try alloc from active\n"); do { // copy active field of heap memcpy((void *)&old_active, (void *)&(fromheap->active), sizeof(active_t)); if (old_active == ZERO_ACTIVE) goto ACTIVE_FAIL; // copy old active into new active extract_active(&new_active_st, &old_active); // set credits if (ACTIVE_GET_CREDITS(old_active) == 0) new_active = ZERO_ACTIVE; else new_active_st.credits = new_active_st.credits - 1; make_active(&new_active_st, &new_active); DPRINTF("old active = 0x%llX new active=0x%llX\n", (u64)old_active, (u64)new_active); } while (atomic_cas((void *)&(fromheap->active), old_active, new_active) == ATOMIC_FAIL); // // <2> pop block // DPRINTF("new_active.addr=%p\n", ACTIVE_GET_ADDR(new_active)); DPRINTF("new_active.credits=%llu\n", ACTIVE_GET_CREDITS(new_active)); desc = ACTIVE_GET_ADDR(new_active); do { // copy anchor into old_anchor and new_anchor memcpy((void *)&old_anchor, (void *)&(desc->anchor), sizeof(anchor_t)); extract_anchor(&old_anchor_st, &old_anchor); extract_anchor(&new_anchor_st, &old_anchor); DPRINTF("desc->next=%p sb=%p heap=%p size=%lu max=%lu\n", desc->next, desc->sb, desc->heap, desc->size, desc->maxcount); DPRINTF("anchor->tag=%lu state=%lu counter=%lu avail=%lu\n", old_anchor_st.tag, old_anchor_st.state, old_anchor_st.counter, old_anchor_st.avail); /* get free block */ addr = desc->sb + old_anchor_st.avail * desc->size; /* set avail that are index of next free block */ next_index = *(u64 *)addr; new_anchor_st.avail = next_index; DPRINTF("free block->%p next block=%lu\n", addr, next_index); /* increase tag for ABA problem */ new_anchor_st.tag = old_anchor_st.tag + 1; /* set state & counter */ if (ACTIVE_GET_CREDITS(old_active) == 0) { if (old_anchor_st.counter == 0) { /* no free block */ new_anchor_st.state = ANCHOR_STATE_FULL; } else { new_anchor_st.state = old_anchor_st.state; new_anchor_st.counter -= MIN(old_anchor_st.counter, MAXCREDITS); } } else { /* do nothing */ } /* building new anchor is finished */ make_anchor(&new_anchor_st, &new_anchor); DPRINTF("old anchor=%llX new anchor=%llX\n", (u64)old_anchor, (u64)new_anchor); } while (atomic_cas((void *)&(desc->anchor), old_anchor, new_anchor) == ATOMIC_FAIL); /* If there is no credits, but more free block */ return addr; ACTIVE_FAIL: DPRINTF("alloc from active fail: no active\n"); goto FUNC_END; FUNC_END: return NULL; }
ER_UINT acre_tsk(const T_CTSK *pk_ctsk) { TCB *p_tcb; TINIB *p_tinib; ATR tskatr; TASK task; PRI itskpri; size_t stksz; STK_T *stk; ER ercd; LOG_ACRE_TSK_ENTER(pk_ctsk); CHECK_TSKCTX_UNL(); tskatr = pk_ctsk->tskatr; task = pk_ctsk->task; itskpri = pk_ctsk->itskpri; stksz = pk_ctsk->stksz; stk = pk_ctsk->stk; CHECK_RSATR(tskatr, TA_ACT|TA_NOACTQUE|TARGET_TSKATR); CHECK_PAR(FUNC_ALIGN(task)); CHECK_PAR(FUNC_NONNULL(task)); CHECK_PAR(VALID_TPRI(itskpri)); CHECK_PAR(stksz >= TARGET_MIN_STKSZ); if (stk != NULL) { CHECK_PAR(STKSZ_ALIGN(stksz)); CHECK_PAR(STACK_ALIGN(stk)); } lock_cpu(); if (queue_empty(&free_tcb)) { ercd = E_NOID; } else { if (stk == NULL) { stk = kernel_malloc(ROUND_STK_T(stksz)); tskatr |= TA_MEMALLOC; } if (stk == NULL) { ercd = E_NOMEM; } else { p_tcb = ((TCB *) queue_delete_next(&free_tcb)); p_tinib = (TINIB *)(p_tcb->p_tinib); p_tinib->tskatr = tskatr; p_tinib->exinf = pk_ctsk->exinf; p_tinib->task = task; p_tinib->ipriority = INT_PRIORITY(itskpri); #ifdef USE_TSKINICTXB init_tskinictxb(&(p_tinib->tskinictxb), stksz, stk); #else /* USE_TSKINICTXB */ p_tinib->stksz = stksz; p_tinib->stk = stk; #endif /* USE_TSKINICTXB */ p_tcb->actque = false; make_dormant(p_tcb); if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) { make_active(p_tcb); } ercd = TSKID(p_tcb); } } unlock_cpu(); error_exit: LOG_ACRE_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd; bool_t dspreq = false; PCB *p_pcb; PCB *my_p_pcb; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); p_pcb = t_acquire_tsk_lock(p_tcb); my_p_pcb = get_my_p_pcb(); /* 自タスクを指定するとエラー */ if ((p_tcb) == my_p_pcb->p_runtsk) { ercd = E_ILUSE; } /* 異なるプロセッサに割り付けられているタスクならエラーとする */ else if (p_pcb != my_p_pcb) { ercd = E_OBJ; } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; } else { if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; /* * マイグレーション要求がキューイングしている場合は, * マイグレーション処理を行う. */ if ((p_tcb->actprc != TPRC_NONE) && (p_tcb->actprc != my_p_pcb->prcid)) { p_tcb->p_pcb = get_mp_p_pcb(p_tcb->actprc); } p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_tcb->p_pcb); } } ercd = E_OK; } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
ER_UINT acre_tsk(const T_CTSK *pk_ctsk) { ID domid; const DOMINIB *p_dominib; TCB *p_tcb; TINIB *p_tinib; ATR tskatr; SIZE sstksz, ustksz; void *sstk, *ustk; ACPTN acptn; ER ercd; LOG_ACRE_TSK_ENTER(pk_ctsk); CHECK_TSKCTX_UNL(); CHECK_MACV_READ(pk_ctsk, T_CTSK); CHECK_RSATR(pk_ctsk->tskatr, TA_ACT|TARGET_TSKATR|TA_DOMMASK); domid = get_atrdomid(pk_ctsk->tskatr); CHECK_ATRDOMID_ACTIVE(domid); CHECK_ALIGN_FUNC(pk_ctsk->task); CHECK_NONNULL_FUNC(pk_ctsk->task); CHECK_TPRI(pk_ctsk->itskpri); p_dominib = (domid == TDOM_SELF) ? p_runtsk->p_tinib->p_dominib : (domid == TDOM_KERNEL) ? &dominib_kernel : get_dominib(domid); if (p_dominib == &dominib_kernel) { /* * システムタスクの場合 */ ustksz = 0U; ustk = NULL; CHECK_PAR(pk_ctsk->sstk == NULL); CHECK_PAR(pk_ctsk->stksz > 0U); sstksz = pk_ctsk->stksz; sstk = pk_ctsk->stk; if (sstk != NULL) { CHECK_PAR(pk_ctsk->sstksz == 0U); } else { sstksz += pk_ctsk->sstksz; } } else { /* * ユーザタスクの場合 */ ustksz = pk_ctsk->stksz; ustk = pk_ctsk->stk; CHECK_PAR(ustksz >= TARGET_MIN_USTKSZ); CHECK_NOSPT(ustk != NULL); CHECK_TARGET_USTACK(ustksz, ustk, p_dominib); sstksz = pk_ctsk->sstksz; sstk = pk_ctsk->sstk; } CHECK_PAR(sstksz >= TARGET_MIN_SSTKSZ); if (sstk != NULL) { CHECK_ALIGN_STKSZ(sstksz); CHECK_ALIGN_STACK(sstk); } CHECK_ACPTN(sysstat_acvct.acptn3); tskatr = pk_ctsk->tskatr; t_lock_cpu(); if (queue_empty(&free_tcb)) { ercd = E_NOID; } else { if (sstk == NULL) { sstk = kernel_malloc(ROUND_STK_T(sstksz)); tskatr |= TA_MEMALLOC; } if (sstk == NULL) { ercd = E_NOMEM; } else { p_tcb = ((TCB *) queue_delete_next(&free_tcb)); p_tinib = (TINIB *)(p_tcb->p_tinib); p_tinib->p_dominib = p_dominib; p_tinib->tskatr = tskatr; p_tinib->exinf = pk_ctsk->exinf; p_tinib->task = pk_ctsk->task; p_tinib->ipriority = INT_PRIORITY(pk_ctsk->itskpri); #ifdef USE_TSKINICTXB init_tskinictxb(&(p_tinib->tskinictxb), p_dominib, sstksz, sstk, utsksz, ustk, pk_ctsk); #else /* USE_TSKINICTXB */ p_tinib->sstksz = sstksz; p_tinib->sstk = sstk; p_tinib->ustksz = ustksz; p_tinib->ustk = ustk; #endif /* USE_TSKINICTXB */ p_tinib->texatr = TA_NULL; p_tinib->texrtn = NULL; acptn = default_acptn(domid); p_tinib->acvct.acptn1 = acptn; p_tinib->acvct.acptn2 = acptn; p_tinib->acvct.acptn3 = acptn | rundom; p_tinib->acvct.acptn4 = acptn; p_tcb->actque = false; make_dormant(p_tcb); queue_initialize(&(p_tcb->mutex_queue)); if ((p_tcb->p_tinib->tskatr & TA_ACT) != 0U) { make_active(p_tcb); } ercd = TSKID(p_tcb); } } t_unlock_cpu(); error_exit: LOG_ACRE_TSK_LEAVE(ercd); return(ercd); }
ER ter_tsk(ID tskid) { TCB *p_tcb; ER ercd = E_OK; bool_t dspreq = false; PCB *f_p_pcb; PCB *t_p_pcb; PCB *my_p_pcb; PCB *p_pcb; LOG_TER_TSK_ENTER(tskid); CHECK_TSKCTX_UNL(); CHECK_TSKID(tskid); p_tcb = get_tcb(tskid); t_lock_cpu(); retry: p_pcb = t_acquire_tsk_lock(p_tcb); my_p_pcb = get_my_p_pcb(); /* 自タスクを指定するとエラー */ if ((p_tcb) == my_p_pcb->p_runtsk) { ercd = E_ILUSE; release_tsk_lock(p_pcb); } /* 異なるプロセッサに割り付けられているタスクならエラーとする */ else if (p_pcb != my_p_pcb) { ercd = E_OBJ; release_tsk_lock(p_pcb); } else if (TSTAT_DORMANT(p_tcb->tstat)) { ercd = E_OBJ; release_tsk_lock(p_pcb); } else { if (!(TSTAT_WAITING(p_tcb->tstat) && TSTAT_WAIT_WOBJ(p_tcb->tstat))) { /* オブジェクト待ち以外の状態の場合 */ if ((p_tcb->actprc == TPRC_NONE) || (p_tcb->actprc == p_pcb->prcid)) { /* 再起動時のマイグレーションなし */ if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { /* オブジェクト待ち以外の待ち状態の場合 */ wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_pcb); } } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } } else { /* 起動要求キューイングあり & 他プロセッサにマイグレーションあり */ /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_tcb->actprc); /* 一旦タスクロックを離す */ release_tsk_lock(p_pcb); /* * 現在割り付けられているプロセッサと移動先のプロセッサのタスク * ロックを取得 */ t_acquire_dual_tsk_lock(p_tcb, p_tcb->actprc, &p_pcb, &t_p_pcb); /* * マイグレーション先のプロセッサが変更された場合はリトライ * 対象タスクと自タスクが所属するプロセッサが異なる場合も * リトライする. */ if ((p_tcb->actprc != t_p_pcb->prcid) || (p_pcb != my_p_pcb)) { release_dual_tsk_lock(p_pcb, t_p_pcb); goto retry; } if (TSTAT_RUNNABLE(p_tcb->tstat)) { /* * 対象タスクが他プロセッサ上のタスクかつRUNNABLEの場合, * RUN状態の可能性があるため,ディスパッチ要求を出す必要があるが, * 本システムコールは同じプロセッサに割り付けられているタスクのみ * に発行可能であるので,ディスパッチ要求を出す必要はない. */ (void)make_non_runnable(p_tcb); } else if (TSTAT_WAITING(p_tcb->tstat)) { /* オブジェクト待ち以外の待ち状態の場合 */ wait_dequeue_tmevtb(p_tcb); } make_dormant(p_tcb); p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; f_p_pcb = p_pcb; p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { /* * 現在所属するプロセッサと同じプロセッサにマイグレー * ションする場合はここに来ないため,dispatch_request() * 戻り値はチェックしない. */ (void)dispatch_request(t_p_pcb); } release_dual_tsk_lock(f_p_pcb, t_p_pcb); } } else { /* オブジェクト待ち状態の場合 */ if ((p_tcb->actprc == TPRC_NONE) || (p_tcb->actprc == p_pcb->prcid)) { /* 再起動時のマイグレーションなし */ /* * デッドロック回避のため,ロックを取得し直す */ WOBJCB *p_wobjcb = p_tcb->p_wobjcb; release_tsk_lock(p_pcb); /* * あらためて * オブジェクトロック -> タスクロック * の順でロックを取得 */ TEST_G_LABEL("_test_ter_tsk_01"); t_acquire_obj_lock(&GET_OBJLOCK(p_wobjcb)); if ((p_pcb = t_acquire_nested_tsk_lock(p_tcb, &GET_OBJLOCK(p_wobjcb))) == NULL){ goto retry; } /* * オブジェクト待ち状態以外ないし,異なるオブジェクトに対する待ち * になっていないかチェック. */ if ((TSTAT_WAITING(p_tcb->tstat) && !TSTAT_WAIT_WOBJ(p_tcb->tstat)) || p_wobjcb != p_tcb->p_wobjcb) { release_nested_tsk_lock(p_pcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); goto retry; } wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); make_dormant(p_tcb); if (p_tcb->actque) { p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; if (make_active(p_tcb)) { dspreq = dispatch_request(p_pcb); } } release_tsk_lock(p_pcb); if (dspreq) { dispatch(); } } else { /* 起動要求キューイングあり & 他プロセッサへのマイグレーション */ /* 移動先のプロセッサのPCBを取得 */ t_p_pcb = get_mp_p_pcb(p_tcb->actprc); /* * デッドロック回避のため,ロックを取得し直す */ WOBJCB *p_wobjcb = p_tcb->p_wobjcb; release_tsk_lock(p_pcb); /* * あらためて * オブジェクトロック -> タスクロック * の順でロックを取得 */ TEST_G_LABEL("_test_ter_tsk_02"); t_acquire_obj_lock(&GET_OBJLOCK(p_wobjcb)); if (t_acquire_nested_dual_tsk_lock(p_tcb, p_tcb->actprc, &GET_OBJLOCK(p_wobjcb), &p_pcb, &t_p_pcb)) { goto retry; } /* * 異なるオブジェクトに対する待ちないし,オブジェクト待ち状態以外に * になっていない,異なるプロセッサへのマイグレーション,対象タスク * がマイグレートしているならリトライ. */ if ((p_wobjcb != p_tcb->p_wobjcb) || (TSTAT_WAITING(p_tcb->tstat) && !TSTAT_WAIT_WOBJ(p_tcb->tstat)) || (get_mp_p_pcb(p_tcb->actprc) != t_p_pcb) || (p_pcb != my_p_pcb)) { release_dual_tsk_lock(p_pcb, t_p_pcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); goto retry; } wait_dequeue_wobj(p_tcb); wait_dequeue_tmevtb(p_tcb); release_obj_lock(&GET_OBJLOCK(p_wobjcb)); make_dormant(p_tcb); p_tcb->actque = false; p_tcb->actprc = TPRC_NONE; f_p_pcb = p_pcb; p_tcb->p_pcb = t_p_pcb; if (make_active(p_tcb)) { /* * 現在所属するプロセッサと同じプロセッサにマイグレー * ションする場合はここに来ないため,dispatch_request() * 戻り値はチェックしない. */ (void)dispatch_request(t_p_pcb); } release_dual_tsk_lock(f_p_pcb, t_p_pcb); } } } t_unlock_cpu(); error_exit: LOG_TER_TSK_LEAVE(ercd); return(ercd); }
void *alloc_newsb(procheap_t *fromheap) { desc_t *new_desc; struct anchor_struct anchor_st; struct active_struct active_st; active_t new_active; anchor_t new_anchor; void *ret; DPRINTF("alloc from new-sb\n"); /* desc address must be aligned to store credits in active */ //new_desc = (desc_t *)memalign(ACTIVE_ADDR_ALIGN, //sizeof(desc_t)); new_desc = get_desc(); /* allocate new super-block */ new_desc->sb = get_newsb(fromheap->sc->sbsize); setup_sb(new_desc->sb, fromheap->sc->sz, fromheap->sc->sbsize); /* setup descriptor */ new_desc->size = fromheap->sc->sz; new_desc->maxcount = fromheap->sc->sbsize / new_desc->size; new_desc->heap = fromheap; /* setup active for heap */ active_st.addr = new_desc; active_st.credits = MIN(new_desc->maxcount, MAXCREDITS) - 1; make_active(&active_st, &new_active); /* setup anchor for desc */ anchor_st.avail = 1; anchor_st.counter = new_desc->maxcount - active_st.credits - 1; anchor_st.state = ANCHOR_STATE_ACTIVE; /* set anchor into desc */ make_anchor(&(anchor_st), &new_anchor); memcpy((void *)&(new_desc->anchor), (void *)&new_anchor, sizeof(anchor_t)); /* * LOCATE MEMORY FENSE HERE * -> why? */ /* set active into heap -> must be done atomically */ if (atomic_cas((void *)&(fromheap->active), ZERO_ACTIVE, /* active is empty */ (u64)new_active) == ATOMIC_SUCCESS) { desc_t **p = (desc_t **)(new_desc->sb); DPRINTF("new superblock->%p\n", new_desc->sb); DPRINTF("new desc->%p\n", new_desc); DPRINTF("set new active:0x%llX\n", (u64)(new_active)); DPRINTF("set new anchor:0x%llX\n", (u64)(new_anchor)); *p = new_desc; ret = (void *)((desc_t **)new_desc->sb + 1); } else { /* another thread already have set new superblock, this thread do roll-back */ free(new_desc->sb); put_desc(new_desc); ret = NULL; } return ret; }