OSDN Git Service

プロセス管理モジュール追加
authorMochi <master.c.mochi@gmail.com>
Thu, 2 Mar 2017 14:21:02 +0000 (23:21 +0900)
committerMochi <master.c.mochi@gmail.com>
Thu, 2 Mar 2017 14:21:02 +0000 (23:21 +0900)
src/kernel/InitCtrl/InitCtrlInit.c
src/kernel/Makefile
src/kernel/ProcMng/ProcMngInit.c [new file with mode: 0644]
src/kernel/ProcMng/ProcMngSched.c [new file with mode: 0644]
src/kernel/ProcMng/ProcMngSched.h [new file with mode: 0644]
src/kernel/ProcMng/ProcMngTask.c [new file with mode: 0644]
src/kernel/ProcMng/ProcMngTask.h [new file with mode: 0644]
src/kernel/ProcMng/ProcMngTss.c [new file with mode: 0644]
src/kernel/ProcMng/ProcMngTss.h [new file with mode: 0644]
src/kernel/include/ProcMng.h [new file with mode: 0644]

index 61e7e87..1408ca6 100644 (file)
@@ -13,6 +13,7 @@
 /* 外部モジュールヘッダ */
 #include <IntMng.h>
 #include <MemMng.h>
+#include <ProcMng.h>
 #include <TimerMng.h>
 
 /* 内部モジュールヘッダ */
@@ -39,7 +40,7 @@ void InitCtrlInit( void )
     MemMngInit( &map, 1 );
     
     /* プロセス管理モジュール初期化 */
-    /* [TODO] */
+    ProcMngInit();
     
     /* 割込み管理モジュール初期化 */
     IntMngInit();
index 2b06724..ae65678 100644 (file)
@@ -1,6 +1,6 @@
 #******************************************************************************#
 #* src/kernel/Makefile                                                        *#
-#*                                                                 2017/02/17 *#
+#*                                                                 2017/03/01 *#
 #* Copyright (C) 2016-2017 Mochi.                                             *#
 #******************************************************************************#
 #******************************************************************************#
@@ -22,7 +22,11 @@ SRCS = InitCtrl/InitCtrlInit.c \
        IntMng/IntMngHdl.c      \
        IntMng/IntMngPic.c      \
        TimerMng/TimerMngInit.c \
-       TimerMng/TimerMngPit.c
+       TimerMng/TimerMngPit.c  \
+       ProcMng/ProcMngInit.c   \
+       ProcMng/ProcMngTss.c    \
+       ProcMng/ProcMngTask.c   \
+       ProcMng/ProcMngSched.c
 
 # Cフラグ
 CFLAGS = -O             \
diff --git a/src/kernel/ProcMng/ProcMngInit.c b/src/kernel/ProcMng/ProcMngInit.c
new file mode 100644 (file)
index 0000000..82b0d33
--- /dev/null
@@ -0,0 +1,44 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngInit.c                                           */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+
+/* 外部モジュールヘッダ */
+
+/* 内部モジュールヘッダ */
+#include "ProcMngSched.h"
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* グローバル関数定義                                                         */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief       プロセス管理初期化
+ * @details     プロセス管理内サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngInit( void )
+{
+    /* TSS管理サブモジュール初期化 */
+    ProcMngTssInit();
+    
+    /* タスク管理サブモジュール初期化 */
+    ProcMngTaskInit();
+    
+    /* スケジューラサブモジュール初期化 */
+    ProcMngSchedInit();
+    
+    return;
+}
+
+
+/******************************************************************************/
diff --git a/src/kernel/ProcMng/ProcMngSched.c b/src/kernel/ProcMng/ProcMngSched.c
new file mode 100644 (file)
index 0000000..9832f79
--- /dev/null
@@ -0,0 +1,426 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngSched.c                                          */
+/*                                                                 2017/03/02 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <MLib/MLib.h>
+#include <MLib/Basic/MLibBasicList.h>
+#include <hardware/IA32/IA32Instruction.h>
+
+/* 外部モジュールヘッダ */
+#include <Cmn.h>
+
+/* 内部モジュールヘッダ */
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* 定義                                                                       */
+/******************************************************************************/
+/** 実行可能タスクグループ数 */
+#define SCHED_RUNGRP_NUM       ( 2 )
+
+/** アイドルタスク情報インデックス */
+#define SCHED_IDLE_IDX         ( 0 )
+
+/* タスク情報使用フラグ */
+#define SCHED_TASK_INFO_UNUSED ( 0 )    /**< 未使用 */
+#define SCHED_TASK_INFO_USED   ( 1 )    /**< 使用中 */
+
+/* スケジューラ実行中レベル */
+#define SCHED_LEVEL_DRIVER     ( 0 )    /**< ドライバレベル */
+#define SCHED_LEVEL_SERVER     ( 1 )    /**< サーバレベル   */
+#define SCHED_LEVEL_USER       ( 2 )    /**< ユーザレベル   */
+
+/** タスク情報構造体 */
+typedef struct {
+    MLibBasicListNode_t node;           /**< 連結リスト情報 */
+    uint8_t             used;           /**< 使用フラグ     */
+    uint8_t             reserved[ 3 ];  /**< 予約           */
+    uint32_t            taskId;         /**< タスクID       */
+} schedTaskInfo_t;
+
+/** 実行可能タスクグループ構造体 */
+typedef struct {
+    MLibBasicList_t driverQ;            /**< ドライバタスクキュー */
+    MLibBasicList_t serverQ;            /**< サーバタスクキュー   */
+    MLibBasicList_t userQ;              /**< ユーザタスクキュー   */
+} schedRunGrp_t;
+
+/** 待ちタスクグループ構造体 */
+typedef struct {
+    MLibBasicList_t waitQ;              /**< 待ちキュー */
+} schedWaitGrp_t;
+
+/** スケジューラテーブル構造体 */
+typedef struct {
+    schedTaskInfo_t *pRunningTaskInfo;              /**< 実行中タスク情報        */
+    uint32_t        runFlg;                         /**< タスク実行済みフラグ    */
+    uint32_t        runningGrpIdx;                  /**< 実行中タスクグループIDX */
+    uint32_t        reservedGrpIdx;                 /**< 予約タスクグループIDX   */
+    schedRunGrp_t   runGrp[ SCHED_RUNGRP_NUM ];     /**< 実行可能タスクグループ  */
+    schedWaitGrp_t  waitGrp;                        /**< 待ちタスクグループ      */
+    MLibBasicList_t freeQ;                          /**< 空タスクキュー          */
+    schedTaskInfo_t taskInfo[ PROCMNG_TASK_ID_NUM ];/**< タスク情報              */
+} schedTbl_t;
+
+
+/******************************************************************************/
+/* ローカル関数プロトタイプ宣言                                               */
+/******************************************************************************/
+/* 実行予約タスクグループエンキュー */
+static void SchedEnqueueToReservedGrp( schedTaskInfo_t *pTaskInfo );
+
+/* 実行可能タスクグループ役割切替 */
+static void SchedSwitchRunGrpRole( void );
+
+/* タスクスイッチ */
+static void SchedSwitchTask( uint32_t nowTaskId,
+                             uint32_t nextTaskId );
+
+/* タスクスイッチ終了ポイント(ラベル) */
+void SchedSwitchTaskEnd( void );
+
+
+/******************************************************************************/
+/* 変数定義                                                                   */
+/******************************************************************************/
+/** スケジューラテーブル */
+static schedTbl_t gSchedTbl;
+
+
+/******************************************************************************/
+/* グローバル関数定義                                                         */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief       スケジュール追加
+ * @details     指定したタスクIDをスケジュールに追加する。
+ * 
+ * @param[in]   taskId タスクID
+ *                  - PROCMNG_TASK_ID_MIN タスクID最小値
+ *                  - PROCMNG_TASK_ID_MAX タスクID最大値
+ * 
+ * @retval      CMN_SUCCESS 成功
+ * @retval      CMN_FAILURE 失敗
+ */
+/******************************************************************************/
+int32_t ProcMngSchedAdd( uint32_t taskId )
+{
+    schedTaskInfo_t *pTaskInfo; /* タスク情報 */
+    
+    /* 空タスクキューから空タスク情報取得 */
+    pTaskInfo =
+        ( schedTaskInfo_t * ) MLibBasicListRemoveTail( &( gSchedTbl.freeQ ) );
+    
+    /* 取得結果判定 */
+    if ( pTaskInfo == NULL ) {
+        /* 空タスク情報無し */
+        
+        return CMN_FAILURE;
+    }
+    
+    /* タスク情報設定 */
+    pTaskInfo->used   = SCHED_TASK_INFO_USED;   /* 使用フラグ */
+    pTaskInfo->taskId = taskId;                 /* タスクID   */
+    
+    /* 実行予約タスクグループにエンキュー */
+    SchedEnqueueToReservedGrp( pTaskInfo );
+    
+    return CMN_SUCCESS;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       スケジューラ実行
+ * @details     スケジューラを実行して次に実行可能なタスクにタスクスイッチする。
+ */
+/******************************************************************************/
+void ProcMngSchedExec( void )
+{
+    uint32_t        level;          /* 実行中レベル         */
+    uint32_t        nowTaskId;      /* 実行中タスクID       */
+    schedRunGrp_t   *pRunningGrp;   /* 実行中タスクグループ */
+    schedTaskInfo_t *pTaskInfo;     /* タスク情報           */
+    
+    /* 初期化 */
+    level       = SCHED_LEVEL_DRIVER;
+    nowTaskId   = gSchedTbl.pRunningTaskInfo->taskId;
+    pRunningGrp = NULL;
+    pTaskInfo   = NULL;
+    
+    /* 実行中タスク判定 */
+    if ( nowTaskId == PROCMNG_TASK_ID_IDLE ) {
+        /* アイドルタスク */
+        
+        /* 実行可能タスクグループ役割切替 */
+        SchedSwitchRunGrpRole();
+        
+    } else {
+        /* アイドルタスク以外 */
+        
+        /* 実行予約タスクグループにキューイング */
+        SchedEnqueueToReservedGrp( gSchedTbl.pRunningTaskInfo );
+    }
+    
+    /* 実行中タスクグループ設定 */
+    pRunningGrp = &gSchedTbl.runGrp[ gSchedTbl.runningGrpIdx ];
+    
+    do {
+        /* 実行中レベル判定 */
+        if ( level == SCHED_LEVEL_DRIVER ) {
+            /* ドライバレベル */
+            
+            /* ドライバキューからデキュー */
+            pTaskInfo = ( schedTaskInfo_t * )
+                MLibBasicListRemoveTail( &( pRunningGrp->driverQ ) );
+            
+        } else if ( level == SCHED_LEVEL_SERVER ) {
+            /* サーバレベル */
+            
+            /* サーバキューからデキュー */
+            pTaskInfo = ( schedTaskInfo_t * )
+                MLibBasicListRemoveTail( &( pRunningGrp->serverQ ) );
+            
+        } else if ( level == SCHED_LEVEL_USER ) {
+            /* ユーザレベル */
+            
+            /* ユーザキューからデキュー */
+            pTaskInfo = ( schedTaskInfo_t * )
+                MLibBasicListRemoveTail( &( pRunningGrp->userQ ) );
+            
+        } else {
+            /* 他 */
+            
+            /* タスク実行済フラグ判定 */
+            if ( gSchedTbl.runFlg == false ) {
+                /* 実行済みタスク無 */
+                
+                /* アイドルタスク設定 */
+                pTaskInfo = &gSchedTbl.taskInfo[ SCHED_IDLE_IDX ];
+                break;
+                
+            } else {
+                /* 実行済みタスク有 */
+                
+                /* 実行可能タスクグループ役割切替 */
+                SchedSwitchRunGrpRole();
+                
+                /* 再スケジューリング */
+                ProcMngSchedExec();
+                
+                return;
+            }
+        }
+        
+        /* 実行中レベル加算 */
+        level++;
+        
+    /* デキュー結果判定 */
+    } while ( pTaskInfo == NULL );
+    
+    /* 実行中タスク情報切り替え */
+    gSchedTbl.pRunningTaskInfo = pTaskInfo;
+    
+    /* タスクスイッチ */
+    SchedSwitchTask( nowTaskId, pTaskInfo->taskId );
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       タスクID取得
+ * @details     現在実行中タスクのタスクIDを取得する。
+ * 
+ * @retval      PROCMNG_TASK_ID_MIN タスクID最小値
+ * @retval      PROCMNG_TASK_ID_MAX タスクID最大値
+ */
+/******************************************************************************/
+uint32_t ProcMngSchedGetTaskId( void )
+{
+    /* タスクID返却 */
+    return gSchedTbl.pRunningTaskInfo->taskId;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       スケジューラ初期化
+ * @details     スケジューラサブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngSchedInit( void )
+{
+    uint32_t        i;              /* カウンタ           */
+    MLibRet_t       retMLib;        /* MLib関数戻り値     */
+    schedTaskInfo_t *pIdleTaskInfo; /* アイドルタスク情報 */
+    
+    /* スケジューラテーブル0初期化 */
+    memset( &gSchedTbl, 0, sizeof ( schedTbl_t ) );
+    
+    /* 実行可能タスクグループIDX設定 */
+    gSchedTbl.runningGrpIdx  = 0;
+    gSchedTbl.reservedGrpIdx = 1;
+    
+    /* タスク実行済フラグ初期化 */
+    gSchedTbl.runFlg = false;
+    
+    /* アイドルタスク情報初期化 */
+    pIdleTaskInfo              = &gSchedTbl.taskInfo[ SCHED_IDLE_IDX ];
+    gSchedTbl.pRunningTaskInfo = pIdleTaskInfo;
+    pIdleTaskInfo->used        = SCHED_TASK_INFO_USED;
+    pIdleTaskInfo->taskId      = PROCMNG_TASK_ID_IDLE;
+    
+    /* 空タスクキュー初期化 */
+    for ( i = 1; i < PROCMNG_TASK_ID_NUM; i++ ) {
+        /* エンキュー */
+        retMLib =  MLibBasicListInsertHead( &( gSchedTbl.freeQ ),
+                                            &( gSchedTbl.taskInfo[ i ].node ) );
+        
+        /* エンキュー結果判定 */
+        if ( retMLib != MLIB_SUCCESS ) {
+            /* 失敗 */
+            
+            /* [TODO] トレース出力 */
+        }
+    }
+    
+    return;
+}
+
+
+/******************************************************************************/
+/* ローカル関数定義                                                           */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief       実行予約タスクグループエンキュー
+ * @details     実行予約タスクグループにタスク情報をキューイングする。
+ * 
+ * @param[in]   *pTaskInfo タスク情報
+ */
+/******************************************************************************/
+static void SchedEnqueueToReservedGrp( schedTaskInfo_t *pTaskInfo )
+{
+    uint8_t         taskType;         /* タスクタイプ           */
+    MLibRet_t       retMLib;          /* MLib関数戻り値         */
+    schedRunGrp_t   *pReservedGrp;    /* 実行予約タスクグループ */
+    MLibBasicList_t *pTaskQ;          /* タスクキュー           */
+    
+    /* 初期化 */
+    taskType     = PROCMNG_TASK_TYPE_USER;
+    pTaskQ       = NULL;
+    pReservedGrp = &gSchedTbl.runGrp[ gSchedTbl.reservedGrpIdx ];
+    retMLib      = MLIB_FAILURE;
+    
+    /* タスクタイプ取得 */
+    taskType = ProcMngTaskGetType( pTaskInfo->taskId );
+    
+    /* タスクタイプ判定 */
+    if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
+        /* ドライバ */
+        
+        /* タスクキュー設定 */
+        pTaskQ = &pReservedGrp->driverQ;
+        
+    } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
+        /* サーバ */
+        
+        /* タスクキュー設定 */
+        pTaskQ = &pReservedGrp->serverQ;
+        
+    } else {
+        /* ユーザ */
+        
+        /* タスクキュー設定 */
+        pTaskQ = &pReservedGrp->userQ;
+    }
+    
+    /* エンキュー */
+    retMLib =  MLibBasicListInsertHead( pTaskQ,
+                                        &( pTaskInfo->node ) );
+    
+    /* エンキュー結果判定 */
+    if ( retMLib != MLIB_SUCCESS ) {
+        /* 失敗 */
+        
+        /* [TODO] トレース出力 */
+    }
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       実行可能タスクグループ役割切替
+ * @details     実行可能タスクグループの役割を切り替える。
+ */
+/******************************************************************************/
+static void SchedSwitchRunGrpRole( void )
+{
+    /* グループ役割切替 */
+    gSchedTbl.runningGrpIdx  ^= 1;
+    gSchedTbl.reservedGrpIdx ^= 1;
+    
+    /* タスク実行済みフラグ初期化 */
+    gSchedTbl.runFlg = false;
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       タスクスイッチ
+ * @details     現在実行中タスクのコンテキストを保存し、指定されたタスクIDのコ
+ *              ンテキストを復元してタスクスイッチする。
+ * 
+ * @param[in]   nowTaskId  現在実行中のタスクID
+ * @param[in]   nextTaskId タスクスイッチ先タスクID
+ */
+/******************************************************************************/
+static void SchedSwitchTask( uint32_t nowTaskId,
+                             uint32_t nextTaskId )
+{
+    void                 *pKernelStack; /* カーネルスタック */
+    ProcMngTaskContext_t context;       /* コンテキスト     */
+    
+    /* 初期化 */
+    memset( &context, 0, sizeof ( ProcMngTaskContext_t ) );
+    
+    /* コンテキスト退避 */
+    context.eip = ( uint32_t ) SchedSwitchTaskEnd;
+    context.esp = IA32InstructionGetEsp();
+    ProcMngTaskSetContext( nowTaskId, &context );
+    
+    /* コンテキスト復旧 */
+    context = ProcMngTaskGetContext( nextTaskId );
+    
+    /* カーネルスタック設定 */
+    pKernelStack = ProcMngTaskGetKernelStack( nextTaskId );
+    ProcMngTssSetEsp0( ( uint32_t ) pKernelStack );
+    
+    /* タスクスイッチ */
+    IA32InstructionSwitchTask( ( void * ) context.eip,
+                               ( void * ) context.esp  );
+    
+    /* ラベル */
+    __asm__ __volatile__ ( "SchedSwitchTaskEnd:" );
+    
+    return;
+}
+
+
+/******************************************************************************/
diff --git a/src/kernel/ProcMng/ProcMngSched.h b/src/kernel/ProcMng/ProcMngSched.h
new file mode 100644 (file)
index 0000000..b912878
--- /dev/null
@@ -0,0 +1,27 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngSched.h                                          */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+#ifndef PROCMNG_SCHED_H
+#define PROCMNG_SCHED_H
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+#include <Cmn.h>
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言                                             */
+/******************************************************************************/
+/* スケジュール追加 */
+extern int32_t ProcMngSchedAdd( uint32_t taskId );
+
+/* タスクID取得 */
+extern uint32_t ProcMngSchedGetTaskId( void );
+
+/* スケジューラ初期化 */
+extern void ProcMngSchedInit( void );
+
+
+/******************************************************************************/
+#endif
diff --git a/src/kernel/ProcMng/ProcMngTask.c b/src/kernel/ProcMng/ProcMngTask.c
new file mode 100644 (file)
index 0000000..42ff005
--- /dev/null
@@ -0,0 +1,343 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTask.c                                           */
+/*                                                                 2017/03/02 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+#include <string.h>
+#include <hardware/IA32/IA32Instruction.h>
+
+/* 外部モジュールヘッダ */
+#include <MemMng.h>
+#include <ProcMng.h>
+
+/* 内部モジュールヘッダ */
+#include "ProcMngSched.h"
+#include "ProcMngTask.h"
+#include "ProcMngTss.h"
+
+
+/******************************************************************************/
+/* 定義                                                                       */
+/******************************************************************************/
+/* タスクID使用フラグ */
+#define TASK_ID_UNUSED ( 0 )    /** 未使用 */
+#define TASK_ID_USED   ( 1 )    /** 使用済 */
+
+/* スタックサイズ */
+#define TASK_KERNEL_STACK_SIZE ( 8192 ) /**< カーネルスタックサイズ */
+#define TASK_STACK_SIZE        ( 8192 ) /**< スタックサイズ         */
+
+/** タスクスタック情報 */
+typedef struct {
+    void   *pTopAddr;       /**< 先頭アドレス */
+    void   *pBottomAddr;    /**< 後尾アドレス */
+    size_t size;            /**< サイズ       */
+} taskStackInfo_t;
+
+/** タスク管理テーブル構造体 */
+typedef struct {
+    uint8_t              used;              /**< 使用フラグ               */
+    uint8_t              type;              /**< タスクタイプ             */
+    uint8_t              state;             /**< タスク状態               */
+    uint8_t              reserved;          /**< パディング               */
+    ProcMngTaskContext_t context;           /**< コンテキスト             */
+    void                 *pEntryPoint;      /**< エントリポイント         */
+    taskStackInfo_t      kernelStackInfo;   /**< カーネルスタックアドレス */
+    taskStackInfo_t      stackInfo;         /**< スタックアドレス         */
+} taskTbl_t;
+
+
+/******************************************************************************/
+/* 変数定義                                                                   */
+/******************************************************************************/
+/** タスク管理テーブル */
+static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
+
+
+/******************************************************************************/
+/* グローバル関数定義                                                         */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief       タスク追加
+ * @details     タスク追加を行う。
+ * 
+ * @param[in]   taskType     タスクタイプ
+ *                  - PROCMNG_TASK_TYPE_KERNEL カーネル
+ *                  - PROCMNG_TASK_TYPE_DRIVER ドライバ
+ *                  - PROCMNG_TASK_TYPE_SERVER サーバ
+ *                  - PROCMNG_TASK_TYPE_USER   ユーザ
+ * @param[in]   *pEntryPoint エントリポイント
+ * 
+ * @retval      PROCMNG_TASK_ID_NULL 失敗
+ * @retval      PROCMNG_TASK_ID_MIN  タスクID最小値
+ * @retval      PROCMNG_TASK_ID_MAX  タスクID最大値
+ */
+/******************************************************************************/
+uint32_t ProcMngTaskAdd( uint8_t taskType,
+                         void    *pEntryPoint )
+{
+    void            *pKernelStack; /* カーネルスタック */
+    void            *pStack;       /* スタック         */
+    int32_t         ret;           /* 関数戻り値       */
+    uint32_t        taskId;        /* タスクID         */
+    taskStackInfo_t *pStackInfo;   /* スタック情報     */
+    
+    /* 初期化 */
+    pKernelStack = NULL;
+    pStack       = NULL;
+    ret          = CMN_FAILURE;
+    taskId       = PROCMNG_TASK_ID_MIN;
+    pStackInfo   = NULL;
+    
+    /* 空タスク検索 */
+    for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
+        /* 使用フラグ判定 */
+        if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
+            /* 未使用 */
+            
+            /* カーネルスタック領域割り当て */
+            pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
+            
+            /* スタック領域割り当て */
+            pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
+            
+            /* 割り当て結果判定 */
+            if ( ( pKernelStack == NULL ) ||
+                 ( pStack       == NULL )    ) {
+                /* 失敗 */
+                
+                /* [TODO] */
+                /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
+                
+                return PROCMNG_TASK_ID_NULL;
+            }
+            
+            /* タスク基本設定 */
+            gTaskTbl[ taskId ].used        = TASK_ID_USED;
+            gTaskTbl[ taskId ].type        = taskType;
+            gTaskTbl[ taskId ].state       = 0;
+            gTaskTbl[ taskId ].context.eip = ( uint32_t ) ProcMngTaskStart;
+            gTaskTbl[ taskId ].context.esp = ( uint32_t ) pKernelStack;
+            gTaskTbl[ taskId ].pEntryPoint = pEntryPoint;
+            
+            /* カーネルスタック情報設定 */
+            pStackInfo              = &( gTaskTbl[ taskId ].kernelStackInfo );
+            pStackInfo->pTopAddr    = pKernelStack;
+            pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
+            pStackInfo->size        = TASK_KERNEL_STACK_SIZE;
+            
+            /* スタック情報設定 */
+            pStackInfo              = &( gTaskTbl[ taskId ].stackInfo );
+            pStackInfo->pTopAddr    = pStack;
+            pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
+            pStackInfo->size        = TASK_STACK_SIZE;
+            
+            /* スケジューラ追加 */
+            ret = ProcMngSchedAdd( taskId );
+            
+            /* 追加結果判定 */
+            if ( ret == CMN_FAILURE ) {
+                /* 失敗 */
+                
+                /* [TODO] */
+                /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
+                
+                return PROCMNG_TASK_ID_NULL;
+            }
+            
+            return taskId;
+        }
+    }
+    
+    return PROCMNG_TASK_ID_NULL;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       コンテキスト取得
+ * @details     指定したタスクIDのコンテキストを取得する。
+ * 
+ * @param[in]   taskId タスクID
+ *                  - PROCMNG_TASK_ID_MIN タスクID最小値
+ *                  - PROCMNG_TASK_ID_MAX タスクID最大値
+ * 
+ * @return      コンテキスト
+ */
+/******************************************************************************/
+ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
+{
+    /* コンテキスト返却 */
+    return gTaskTbl[ taskId ].context;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       カーネルスタックアドレス取得
+ * @details     指定したタスクIDのカーネルスタックアドレスを取得する。
+ * 
+ * @param[in]   taskId タスクID
+ *                  - PROCMNG_TASK_ID_MIN タスクID最小値
+ *                  - PROCMNG_TASK_ID_MAX タスクID最大値
+ * 
+ * @return      カーネルスタックアドレス
+ */
+/******************************************************************************/
+void *ProcMngTaskGetKernelStack( uint32_t taskId )
+{
+    /* カーネルスタックアドレス返却 */
+    return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       タスクタイプ取得
+ * @details     指定したタスクIDのタスクタイプを取得する。
+ * 
+ * @param[in]   taskId タスクID
+ *                  - PROCMNG_TASK_ID_MIN タスクID最小値
+ *                  - PROCMNG_TASK_ID_MAX タスクID最大値
+ * 
+ * @retval      PROCMNG_TASK_TYPE_DRIVER ドライバ
+ * @retval      PROCMNG_TASK_TYPE_SERVER サーバ
+ * @retval      PROCMNG_TASK_TYPE_USER   ユーザ
+ */
+/******************************************************************************/
+uint8_t ProcMngTaskGetType( uint32_t taskId )
+{
+    /* タスクタイプ返却 */
+    return gTaskTbl[ taskId ].type;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       タスク管理初期化
+ * @details     タスク管理サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngTaskInit( void )
+{
+    /* タスク管理テーブル初期化 */
+    memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
+    
+    /* アイドルタスク設定 */
+    gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used = TASK_ID_USED;   /* 使用フラグ */
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       コンテキスト設定
+ * @details     指定したタスクIDのコンテキストを設定する。
+ * 
+ * @param[in]   taskId    設定先タスクID
+ *                  - PROCMNG_TASK_ID_MIN タスクID最小値
+ *                  - PROCMNG_TASK_ID_MAX タスクID最大値
+ * @param[in]   *pContext コンテキスト
+ */
+/******************************************************************************/
+void ProcMngTaskSetContext( uint32_t             taskId,
+                            ProcMngTaskContext_t *pContext )
+{
+    /* コンテキスト設定 */
+    gTaskTbl[ taskId ].context = *pContext;
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       タスク起動開始
+ * @details     タスクの起動を開始する。
+ */
+/******************************************************************************/
+void ProcMngTaskStart( void )
+{
+    void      *pEntryPoint; /* エントリポイント         */
+    void      *pStack;      /* スタックアドレス         */
+    uint8_t   taskType;     /* タスクタイプ             */
+    uint32_t  taskId;       /* タスクID                 */
+    uint32_t  codeSegSel;   /* コードセグメントセレクタ */
+    uint32_t  dataSegSel;   /* データセグメントセレクタ */
+    taskTbl_t *pTask;       /* タスク管理情報           */
+    
+    /* 初期化 */
+    taskId      = ProcMngSchedGetTaskId();      /* タスクID         */
+    pTask       = &( gTaskTbl[ taskId ] );      /* タスク管理情報   */
+    pEntryPoint = pTask->pEntryPoint;           /* エントリポイント */
+    pStack      = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
+    taskType    = pTask->type;                  /* タスクタイプ     */
+    
+    /* タスクタイプ判定 */
+    if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
+        /* ドライバ */
+        
+        /* セグメントセレクタ設定 */
+        codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE;     /* コード */
+        dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA;     /* データ */
+        
+    } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
+        /* サーバ */
+        
+        codeSegSel = MEMMNG_SEGSEL_SERVER_CODE;     /* コード */
+        dataSegSel = MEMMNG_SEGSEL_SERVER_DATA;     /* データ */
+        
+    } else {
+        /* ユーザ */
+        
+        codeSegSel = MEMMNG_SEGSEL_USER_CODE;       /* コード */
+        dataSegSel = MEMMNG_SEGSEL_USER_DATA;       /* データ */
+    }
+    
+    /* iretd命令用スタック設定 */
+    IA32InstructionPush( dataSegSel );              /* ss     */
+    IA32InstructionPush( ( uint32_t ) pStack );     /* esp    */
+    IA32InstructionPush( 0x00003202 );              /* eflags */
+    IA32InstructionPush( codeSegSel );              /* cs     */
+    IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip    */
+    
+    /* セグメントレジスタ設定用スタック設定 */
+    IA32InstructionPush( dataSegSel );              /* gs */
+    IA32InstructionPush( dataSegSel );              /* fs */
+    IA32InstructionPush( dataSegSel );              /* es */
+    IA32InstructionPush( dataSegSel );              /* ds */
+    
+    /* 汎用レジスタ設定用スタック設定 */
+    IA32InstructionPush( 0 );                       /* eax           */
+    IA32InstructionPush( 0 );                       /* ecx           */
+    IA32InstructionPush( 0 );                       /* edx           */
+    IA32InstructionPush( 0 );                       /* ebx           */
+    IA32InstructionPush( 0 );                       /* esp( 未使用 ) */
+    IA32InstructionPush( 0 );                       /* ebp           */
+    IA32InstructionPush( 0 );                       /* esi           */
+    IA32InstructionPush( 0 );                       /* edi           */
+    
+    /* 汎用レジスタ設定 */
+    IA32InstructionPopad();
+    
+    /* セグメントレジスタ設定 */
+    IA32InstructionPopDs();
+    IA32InstructionPopEs();
+    IA32InstructionPopFs();
+    IA32InstructionPopGs();
+    
+    /* タスクエントリポイントへ移行 */
+    IA32InstructionIretd();
+    
+    /* not return */
+}
+
+
+/******************************************************************************/
diff --git a/src/kernel/ProcMng/ProcMngTask.h b/src/kernel/ProcMng/ProcMngTask.h
new file mode 100644 (file)
index 0000000..811ca02
--- /dev/null
@@ -0,0 +1,52 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTask.h                                           */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+#ifndef PROCMNG_TASK_H
+#define PROCMNG_TASK_H
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <stdint.h>
+
+/* 外部モジュールヘッダ */
+#include <ProcMng.h>
+
+
+/******************************************************************************/
+/* 定義                                                                       */
+/******************************************************************************/
+/** コンテキスト構造体 */
+typedef struct {
+    uint32_t eip;   /**< eipレジスタ */
+    uint32_t esp;   /**< espレジスタ */
+} ProcMngTaskContext_t;
+
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言                                             */
+/******************************************************************************/
+/* コンテキスト取得 */
+extern ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId );
+
+/* カーネルスタックアドレス取得 */
+extern void *ProcMngTaskGetKernelStack( uint32_t taskId );
+
+/* タスクタイプ取得 */
+extern uint8_t ProcMngTaskGetType( uint32_t taskId );
+
+/* タスク管理初期化 */
+extern void ProcMngTaskInit( void );
+
+/* コンテキスト設定 */
+extern void ProcMngTaskSetContext( uint32_t             taskId,
+                                   ProcMngTaskContext_t *pContext );
+
+/* タスク起動開始 */
+extern void ProcMngTaskStart( void );
+
+
+/******************************************************************************/
+#endif
diff --git a/src/kernel/ProcMng/ProcMngTss.c b/src/kernel/ProcMng/ProcMngTss.c
new file mode 100644 (file)
index 0000000..ba2448d
--- /dev/null
@@ -0,0 +1,85 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTss.c                                            */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+/******************************************************************************/
+/* インクルード                                                               */
+/******************************************************************************/
+/* 共通ヘッダ */
+#include <string.h>
+#include <hardware/IA32/IA32.h>
+#include <hardware/IA32/IA32Descriptor.h>
+#include <hardware/IA32/IA32Instruction.h>
+#include <hardware/IA32/IA32Tss.h>
+
+/* 外部モジュールヘッダ */
+#include <MemMng.h>
+
+/* 内部モジュールヘッダ */
+
+
+/******************************************************************************/
+/* 変数定義                                                                   */
+/******************************************************************************/
+/** TSS */
+static IA32Tss_t gTss;
+
+
+/******************************************************************************/
+/* グローバル関数定義                                                         */
+/******************************************************************************/
+/******************************************************************************/
+/**
+ * @brief       TSS管理初期化
+ * @details     TSS管理サブモジュールの初期化を行う。
+ */
+/******************************************************************************/
+void ProcMngTssInit( void )
+{
+    uint16_t index;     /* GDTエントリ番号    */
+    uint16_t selector;  /* セグメントセレクタ */
+    
+    /* TSS初期化 */
+    memset( &gTss, 0, sizeof ( IA32Tss_t ) );
+    
+    /* TSSディスクリプタ設定 */
+    index = MemMngGdtAdd(
+                &gTss,                          /* セグメントベース     */
+                sizeof ( IA32Tss_t ) - 1,       /* セグメントサイズ     */
+                IA32_DESCRIPTOR_G_BYTE,         /* リミット粒度         */
+                IA32_DESCRIPTOR_S_SYSTEM,       /* システムフラグ       */
+                IA32_DESCRIPTOR_TYPE_TSS32,     /* セグメントタイプ     */
+                IA32_DESCRIPTOR_DPL_0,          /* セグメント特権レベル */
+                IA32_DESCRIPTOR_DB_UNUSED   );  /* オペレーションサイズ */
+    
+    /* セグメントセレクタ設定 */
+    selector = IA32_SEGMENT_SELECTOR( index,            /* インデックス */
+                                      IA32_TI_GDT,      /* TI           */
+                                      IA32_RPL_0   );   /* RPL          */
+    
+    /* TR設定 */
+    IA32InstructionLtr( selector );
+    
+    return;
+}
+
+
+/******************************************************************************/
+/**
+ * @brief       ESP0設定
+ * @details     TSSのESP0フィールドを設定する。
+ * 
+ * @param[in]   esp0 ESP0設定値
+ */
+/******************************************************************************/
+void ProcMngTssSetEsp0( uint32_t esp0 )
+{
+    /* esp0設定 */
+    gTss.esp0 = esp0;
+    
+    return;
+}
+
+
+/******************************************************************************/
diff --git a/src/kernel/ProcMng/ProcMngTss.h b/src/kernel/ProcMng/ProcMngTss.h
new file mode 100644 (file)
index 0000000..1c7ce15
--- /dev/null
@@ -0,0 +1,19 @@
+/******************************************************************************/
+/* src/kernel/ProcMng/ProcMngTss.h                                            */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+#ifndef PROCMNG_TSS_H
+#define PROCMNG_TSS_H
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言                                             */
+/******************************************************************************/
+/* TSS管理初期化 */
+extern void ProcMngTssInit( void );
+
+/* ESP0設定 */
+extern void ProcMngTssSetEsp0( uint32_t esp0 );
+
+
+/******************************************************************************/
+#endif
diff --git a/src/kernel/include/ProcMng.h b/src/kernel/include/ProcMng.h
new file mode 100644 (file)
index 0000000..35c2171
--- /dev/null
@@ -0,0 +1,41 @@
+/******************************************************************************/
+/* src/kernel/include/ProcMng.h                                               */
+/*                                                                 2017/03/01 */
+/* Copyright (C) 2017 Mochi.                                                  */
+/******************************************************************************/
+#ifndef PROCMNG_H
+#define PROCMNG_H
+/******************************************************************************/
+/* 定義                                                                       */
+/******************************************************************************/
+/* タスクID */
+#define PROCMNG_TASK_ID_MIN  ( 0 )                      /** タスクID最小値 */
+#define PROCMNG_TASK_ID_MAX  ( 4096 )                   /** タスクID最大値 */
+#define PROCMNG_TASK_ID_NULL ( PROCMNG_TASK_ID_MAX + 1 )/** タスクID無     */
+#define PROCMNG_TASK_ID_NUM  ( PROCMNG_TASK_ID_MAX + 1 )/** タスクID数     */
+#define PROCMNG_TASK_ID_IDLE ( 0 )                      /** アイドルタスク */
+
+/* タスクタイプ */
+#define PROCMNG_TASK_TYPE_DRIVER ( 0 )  /** ドライバ */
+#define PROCMNG_TASK_TYPE_SERVER ( 1 )  /** サーバ   */
+#define PROCMNG_TASK_TYPE_USER   ( 2 )  /** ユーザ   */
+
+
+/******************************************************************************/
+/* グローバル関数プロトタイプ宣言                                             */
+/******************************************************************************/
+/*---------------*/
+/* ProcMngInit.c */
+/*---------------*/
+/* プロセス管理初期化 */
+extern void ProcMngInit( void );
+
+/*--------------*/
+/* ProcMngSched */
+/*--------------*/
+/* スケジューラ実行 */
+extern void ProcMngSchedExec( void );
+
+
+/******************************************************************************/
+#endif