/*! * ミューテックスの初期化(動的型mutexの領域確保と初期化(freeリストを作成する)) * (返却値)E_NOMEM : メモリが取得できない * (返却値)E_OK : 正常終了 */ static ER dynamic_mtx_init(void) { int mtxids, i; MTXCB *mcb; mg_mtx_info.freehead = mg_mtx_info.alochead = NULL; /* start_init_tsk()の時以外 */ if (mg_mtx_info.power_count) { mtxids = MUTEX_ID_NUM << (mg_mtx_info.power_count - 1); /* 現在と同じ領域を確保する */ } /* start_init_tsk()の時 */ else { mtxids = MUTEX_ID_NUM << mg_mtx_info.power_count; } for (i = 0; i < mtxids; i++) { mcb = (MTXCB *)get_mpf_isr(sizeof(*mcb)); /* ノードのメモリ確保 */ /*メモリが取得できない*/ if(mcb == NULL) { return E_NOMEM; /* initタスクの時は,start_init_tsk()関数内でOSをスリープさせる */ } memset(mcb, -1, sizeof(*mcb)); /* 確保したノードを初期化 */ /* freeキューの作成 */ mcb->next = mg_mtx_info.freehead; mcb->prev = NULL; mg_mtx_info.freehead = mcb->next->prev = mcb; } return E_OK; }
/*! * タスクの領域確保と初期化(タスクのfreeリストを作成する) * (返却値)E_NOMEM : メモリが取得できない * (返却値)E_OK : 正常終了 */ static ER dynamic_tsk_init(void) { int tskids, i; TCB *tcb; g_tsk_info.freehead = g_tsk_info.alochead = NULL; /* start_init_tsk()の時以外 */ if (g_tsk_info.power_count) { tskids = TASK_ID_NUM << (g_tsk_info.power_count - 1); /* 現在と同じ領域を確保する */ } /* start_init_tsk()の時 */ else { tskids = g_tsk_info.tskid_num; } for (i = 0; i < tskids; i++) { tcb = (TCB *)get_mpf_isr(sizeof(*tcb)); /* ノードのメモリ確保 */ /*メモリが取得できない*/ if(tcb == NULL) { return E_NOMEM; /* initタスクの時は,start_init_tsk()関数内でOSをスリープさせる */ } memset(tcb, -1, sizeof(*tcb)); /* 確保したノードを初期化 */ /* freeキューの作成 */ tcb->free_next = g_tsk_info.freehead; tcb->free_prev = NULL; /* NULLを経由するとCodeSourceryはエラー(データアボートを発行する) */ if (tcb->free_next != NULL) { tcb->free_next->free_prev = tcb; } g_tsk_info.freehead = tcb; } return E_OK; }
/*! * ミューテックスの初期化(静的型mutexの領域確保と初期化(可変長配列として使用する)) * mtxids : 確保する可変長配列の個数 * (返却値)E_NOMEM : メモリが取得できない * (返却値)E_OK : 正常終了 */ static ER static_mtx_init(int mtxids) { MTXCB *mcb; int size = sizeof(*mcb) * mtxids; /* 可変長配列のサイズ */ mg_mtx_info.array = (MTXCB *)get_mpf_isr(size); /* 可変長配列確保 */ if (mg_mtx_info.array == NULL) { return E_NOMEM; /* initタスクの時は,start_init_tsk()関数内でOSをスリープさせる */ } /* 確保した可変長配列を初期化(可変長でも配列はメモリに連続しているのでこれでOK) */ memset(mg_mtx_info.array, -1, size); return E_OK; }
/*! * ミューテックスの初期化(mutex ID変換テーブルの領域確保と初期化) * -mutex IDが足らなくなった場合に呼ばれる * (返却値)E_NOMEM : メモリが取得できない(この返却値は) * (返却値)E_OK : 正常終了 */ ER mtx_init(void) { int mtxids, i; MTXCB *mcb; mtxids = MUTEX_ID_NUM << mg_mtx_info.power_count; /* 倍の領域を確保する(start_init_tsk()の時はデフォルト通り) */ mg_mtx_info.id_table = (MTXCB **)get_mpf_isr(sizeof(mcb) * mtxids); /* 変換テーブルの動的メモリ確保 */ /* mutexID変換テーブルの初期化(メモリにNULLを埋めるのにmemset()は使用できない) */ for (i = 0; i < mtxids; i++) { mg_mtx_info.id_table[i] = NULL; } /* MTXCBの静的型配列の作成及び初期化とMTXCBの動的型freeリストの作成と初期化 */ if ((E_NOMEM == static_mtx_init(mtxids)) || (E_NOMEM == dynamic_mtx_init())) { return E_NOMEM; /* initタスクの時は,start_init_tsk関数内でOSをスリープさせる */ } return E_OK; }
/*! * 差分のキューのノードを作成 * 多少のすれ違い(タイマ割込みによるノード解放とシステムコールによるノード作成)の考慮 * flag : タイマの要求種類 * request_sec : 要求タイマ値 * rqobjp : ソフトタイマを要求したオブジェクトのポインタ(ソフトタイマで周期機能を使用したいケースのみ指定する.) * func : タイマ満了時のコールバックルーチン * *argv : コールバックルーチンに渡すパラメータ * (返却値)E_NG : hard timerを差分のキュー管理しようとした場合 * (返却値)newtbf : 新規作成したタイマコントロールブロックへポインタ */ OBJP create_tmrcb_diffque(short flag, int request_sec, TMRRQ_OBJP rqobjp, TMR_CALLRTE func, void *argv) { TMRCB *newtbf; newtbf = (TMRCB *)get_mpf_isr(sizeof(*newtbf)); /* 動的メモリ取得要求 */ /* メモリが取得できない */ if(newtbf == NULL) { down_system(); } newtbf->next = newtbf->prev = NULL; newtbf->flag = flag; newtbf->msec = request_sec; newtbf->rqobjp = rqobjp; /* 周期機能を使用しない時は0が入る */ newtbf->func = func; newtbf->argv = argv; insert_tmrcb_diffque(newtbf); /* タイマコントロールブロックの挿入 */ return (OBJP)newtbf; }
/*! * タスクの初期化(task ID変換テーブルの領域確保と初期化) * -この関数は,kernel_obj_init()で呼ばれる場合と,taskIDが足らなくなった場合に呼ばれる * (返却値)E_NOMEM : メモリが取得できない(この返却値は) * (返却値)E_OK : 正常終了 */ ER tsk_init(void) { int tskids, i; TCB *tcb; tskids = g_tsk_info.tskid_num; /* 倍の領域を確保する(start_init_tsk()の時はデフォルト通り) */ g_tsk_info.id_table = (TCB **)get_mpf_isr(sizeof(tcb) * tskids); /* 変換テーブルの動的メモリ確保 */ if (g_tsk_info.id_table == NULL) { return E_NOMEM; /* initタスクの時は,start_init_tsk()関数内でOSをスリープさせる */ } /* taskID変換テーブルの初期化(メモリにNULLを埋めるのにmemset()は使用できない) */ for (i = 0; i < tskids; i++) { g_tsk_info.id_table[i] = NULL; } /* TCBの静的型配列の作成及び初期化とTCBの動的型freeリストの作成と初期化 */ if (E_NOMEM == dynamic_tsk_init()) { return E_NOMEM; /* initタスクの時は,start_init_tsk()関数内でOSをスリープさせる */ } return E_OK; }
/*! * レディーキューの初期化 * typeはenumでやっているので,パラメータチェックはいらない * type : スケジューラのタイプ * (返却値)E_NOMEM : メモリ不足 * (返却値)E_OK : 正常終了 */ ER ready_init(void) { RDYCB *rqcb; SCHDUL_TYPE type = mg_schdul_info.type; rqcb = (RDYCB *)get_mpf_isr(sizeof(*rqcb)); /* 動的メモリ取得 */ if (rqcb == NULL) { return E_NOMEM; } memset(rqcb, 0, sizeof(*rqcb)); mg_ready_info.entry = rqcb; /* レディー情報ブロックの設定 */ /* First Come First Sarvedとラウンドロビンスケジューリングの時は単一のレディーキュー */ if (type == FCFS_SCHEDULING || type == RR_SCHEDULING) { mg_ready_info.type = SINGLE_READY_QUEUE; /* キュー構造のレディーブロックのポインタ */ rquecb_init(&mg_ready_info.entry->un.single.ready, 0); /* ビットマップの処理はない */ } /* 簡易O(1)スケジューリング時はタイムアウトと優先度レベルごとのレディーキュー */ else if (type == ODRONE_SCHEDULING) { mg_ready_info.type = TIMEOUT_PRIORITY_READYQUE; mg_ready_info.entry->un.tmout_pri.activ = &mg_ready_info.entry->un.tmout_pri.activ_ready; mg_ready_info.entry->un.tmout_pri.expired = &mg_ready_info.entry->un.tmout_pri.expired_ready; /* キュー構造のレディーブロックのポインタ */ rquecb_init(mg_ready_info.entry->un.tmout_pri.activ_ready.que, PRIORITY_NUM); rquecb_init(mg_ready_info.entry->un.tmout_pri.expired_ready.que, PRIORITY_NUM); bitmap_init(); /*! ビットマップの初期化 */ } /* Fair Schedulerは実行時間の2分探索木のレディー構造 */ else if (type == FR_SCHEDULING) { mg_ready_info.type = BINARY_TREE; /* 2分木のレディーブロックの初期化(属性は実行時間) */ btreercb_init(&mg_ready_info.entry->un.btree.ready, 0, EXECTION_TIME); } /* Priority Fair Schedulerは実行時間の優先度レベルの2分探索木のレディー構造 */ else if (type == PFR_SCHEDULING) { mg_ready_info.type = PRIORITY_BINARY_TREE; btreercb_init(mg_ready_info.entry->un.pri_btree.ready, PRIORITY_NUM, EXECTION_TIME); bitmap_init(); /*! ビットマップの初期化 */ } /* EDFスケジューリングはデッドライン2分探索木のレディー構造 */ else if (type == EDF_SCHEDULING) { mg_ready_info.type = BINARY_TREE; /* 2分木のレディーブロックの初期化(属性はデッドライン時刻) */ btreercb_init(&mg_ready_info.entry->un.btree.ready, 0, DEADLINE_TIME); } /* LLFスケジューリングフロートタイム2分探索木のレディー構造 */ else if (type == LLF_SCHEDULING) { mg_ready_info.type = BINARY_TREE; /* 2分木のレディーブロックの初期化(属性は余裕時刻) */ btreercb_init(&mg_ready_info.entry->un.btree.ready, 0, FLOAT_TIME); } /* * 優先度スケジューリングとラウンドロビン×優先度スケジューリング,Multilevel Feedback Queue, * Rate Monotonic,Deadline Monotonicは優先度レベルごとのレディーキュー */ else { mg_ready_info.type = PRIORITY_READY_QUEUE; /* キュー構造のレディーブロックのポインタ */ rquecb_init(mg_ready_info.entry->un.pri.ready.que, PRIORITY_NUM); bitmap_init(); /*! ビットマップの初期化 */ } return E_OK; }
/*! * システムコール処理(acre_mtx():mutexコントロールブロックの作成(ID自動割付)) * type : 静的型か動的型か? * atr : タスクをレディーへ戻すアルゴリズム(FIFO順か?優先度順か?) * piver_mtx : 優先度逆転機構の選択 * maxlocks : 再帰ロックの上限値 * pcl_param : 優先度逆転プロトコル適用時のパラメータ(必要としない優先度逆転プロトコルもある) * (返却値)E_PAR : システムコールの引数不正 * (返却値)E_NOID : 動的メモリが取得できない(割付可能なIDがない) * (返却値)mcb : 正常終了(作成したmutexコントロールブロックへのポインタ) */ OBJP acre_mtx_isr(MTX_TYPE type, MTX_ATR atr, PIVER_TYPE piver_type, int maxlocks, int pcl_param) { MTXCB *mcb, *vmcb; /* 静的型mutexの場合 */ if (type == STATIC_MUTEX) { mcb = &mg_mtx_info.array[mg_mtx_info.counter]; } /* 動的型mutexの場合 */ else { mcb = mg_mtx_info.freehead; /* free headからノードを与える(抜き取るわけではない) */ mg_mtx_info.freehead = mcb->next; /* free headを一つ進める */ /* alocheadが空の場合 */ if (mg_mtx_info.alochead == NULL) { mg_mtx_info.alochead = mcb; } } mcb->mtxid = mg_mtx_info.counter; /* カウンタ(ID変換テーブル(可変長配列のインデックス)) */ mcb->mtx_type = type; /* 静的か動的かを記録 */ mcb->atr = atr; /* 属性 */ mcb->piver_type = piver_type; /* 優先度逆転機構 */ mcb->mtxvalue = 0; /* mutexの値,mutex作成時(初期値)は0 */ mcb->locks = 0; /* 再帰ロックの回数,mutex作成時(初期値)は0 */ mcb->maxlocks = maxlocks; /* 再帰ロックの上限値 */ mcb->ownerid = -1; /* 作成時,オーナーシップは指定しない */ mcb->pcl.pcl_next = mcb->pcl.pcl_prev = NULL; mcb->waithead = mcb->waittail = NULL; /* virtual priority inheritanceの場合,acre_mtx()の初回のみvirtual mtxを作成 */ if (piver_type == TA_VINHERIT && mg_mtx_info.virtual_mtx == NULL) { /* virtual mutexの作成 */ vmcb = (MTXCB *)get_mpf_isr(sizeof(*vmcb)); /* メモリ取得できなかった場合 */ if (vmcb == NULL) { down_system(); } /* メモリ取得できた場合,virtual mutexを初期化 */ else { /* mtxidは使用しない */ /* mutex typeは指定しない */ vmcb->atr = atr; /* 属性 */ /* 優先度逆転機構は指定しない */ vmcb->mtxvalue = 0; /* mutexの値,mutex作成時(初期値)は0 */ vmcb->locks = 0; /* 再帰ロックの回数,mutex作成時(初期値)は0 */ /* 再帰ロックの上限値は指定しない */ vmcb->ownerid = -1; /* 作成時,オーナーシップは指定しない */ /* 優先度逆転機構ポインタは使用しない */ vmcb->waithead = vmcb->waittail = NULL; mg_mtx_info.virtual_mtx = vmcb; /* グローバルエリアへ繋げておく */ } } /* 優先度逆転機構エリアが必要ない場合 */ else if (piver_type == TA_VOIDPCL || piver_type == TA_INHERIT || piver_type == TA_STACK) { mcb->pcl.pcl_param = -1; } /* 優先度逆転機構エリアが必要な場合 */ else { mcb->pcl.pcl_param = pcl_param; } DEBUG_OUTMSG("create mutexID for interrput handler\n"); return (OBJP)mcb; }