OSDN Git Service

ae5cec7c9672a8bb0bf87fecc6ea85736290224f
[mochi/master.git] / src / kernel / ProcMng / ProcMngTask.c
1 /******************************************************************************/
2 /* src/kernel/ProcMng/ProcMngTask.c                                           */
3 /*                                                                 2017/03/16 */
4 /* Copyright (C) 2017 Mochi.                                                  */
5 /******************************************************************************/
6 /******************************************************************************/
7 /* インクルード                                                               */
8 /******************************************************************************/
9 /* 共通ヘッダ */
10 #include <stdarg.h>
11 #include <stdint.h>
12 #include <string.h>
13 #include <hardware/IA32/IA32Instruction.h>
14
15 /* 外部モジュールヘッダ */
16 #include <Cmn.h>
17 #include <Debug.h>
18 #include <MemMng.h>
19 #include <ProcMng.h>
20
21 /* 内部モジュールヘッダ */
22 #include "ProcMngSched.h"
23 #include "ProcMngTask.h"
24 #include "ProcMngTss.h"
25
26
27 /******************************************************************************/
28 /* 定義                                                                       */
29 /******************************************************************************/
30 /* デバッグトレースログ出力マクロ */
31 #ifdef DEBUG_LOG_ENABLE
32 #define DEBUG_LOG( ... )                        \
33     DebugLogOutput( CMN_MODULE_PROCMNG_TASK,    \
34                     __LINE__,                   \
35                     __VA_ARGS__ )
36 #else
37 #define DEBUG_LOG( ... )
38 #endif
39
40 /* タスクID使用フラグ */
41 #define TASK_ID_UNUSED ( 0 )    /** 未使用 */
42 #define TASK_ID_USED   ( 1 )    /** 使用済 */
43
44 /* スタックサイズ */
45 #define TASK_KERNEL_STACK_SIZE ( 1024000 )  /**< カーネルスタックサイズ */
46 #define TASK_STACK_SIZE        ( 1024000 )  /**< スタックサイズ         */
47
48 /** タスクスタック情報 */
49 typedef struct {
50     void   *pTopAddr;       /**< 先頭アドレス */
51     void   *pBottomAddr;    /**< 後尾アドレス */
52     size_t size;            /**< サイズ       */
53 } taskStackInfo_t;
54
55 /** タスク管理テーブル構造体 */
56 typedef struct {
57     uint8_t              used;              /**< 使用フラグ               */
58     uint8_t              type;              /**< タスクタイプ             */
59     uint8_t              state;             /**< タスク状態               */
60     uint8_t              reserved;          /**< パディング               */
61     ProcMngTaskContext_t context;           /**< コンテキスト             */
62     void                 *pEntryPoint;      /**< エントリポイント         */
63     taskStackInfo_t      kernelStackInfo;   /**< カーネルスタックアドレス */
64     taskStackInfo_t      stackInfo;         /**< スタックアドレス         */
65 } taskTbl_t;
66
67
68 /******************************************************************************/
69 /* 変数定義                                                                   */
70 /******************************************************************************/
71 /** タスク管理テーブル */
72 static taskTbl_t gTaskTbl[ PROCMNG_TASK_ID_NUM ];
73
74
75 /******************************************************************************/
76 /* グローバル関数定義                                                         */
77 /******************************************************************************/
78 /******************************************************************************/
79 /**
80  * @brief       タスク追加
81  * @details     タスク追加を行う。
82  * 
83  * @param[in]   taskType     タスクタイプ
84  *                  - PROCMNG_TASK_TYPE_DRIVER ドライバ
85  *                  - PROCMNG_TASK_TYPE_SERVER サーバ
86  *                  - PROCMNG_TASK_TYPE_USER   ユーザ
87  * @param[in]   *pEntryPoint エントリポイント
88  * 
89  * @retval      PROCMNG_TASK_ID_NULL 失敗
90  * @retval      PROCMNG_TASK_ID_MIN  タスクID最小値
91  * @retval      PROCMNG_TASK_ID_MAX  タスクID最大値
92  */
93 /******************************************************************************/
94 uint32_t ProcMngTaskAdd( uint8_t taskType,
95                          void    *pEntryPoint )
96 {
97     void            *pKernelStack; /* カーネルスタック */
98     void            *pStack;       /* スタック         */
99     int32_t         ret;           /* 関数戻り値       */
100     uint32_t        taskId;        /* タスクID         */
101     taskStackInfo_t *pStackInfo;   /* スタック情報     */
102     
103     /* 初期化 */
104     pKernelStack = NULL;
105     pStack       = NULL;
106     ret          = CMN_FAILURE;
107     taskId       = PROCMNG_TASK_ID_MIN;
108     pStackInfo   = NULL;
109     
110     /* デバッグトレースログ出力 */
111     DEBUG_LOG( "%s() start. taskType=%u, pEntryPoint=%010p",
112                __func__,
113                taskType,
114                pEntryPoint );
115     
116     /* 空タスク検索 */
117     for ( ; taskId < PROCMNG_TASK_ID_MAX; taskId++ ) {
118         /* 使用フラグ判定 */
119         if ( gTaskTbl[ taskId ].used == TASK_ID_UNUSED ) {
120             /* 未使用 */
121             
122             /* カーネルスタック領域割り当て */
123             pKernelStack = MemMngAreaAlloc( TASK_KERNEL_STACK_SIZE );
124             
125             /* スタック領域割り当て */
126             pStack = MemMngAreaAlloc( TASK_STACK_SIZE );
127             
128             /* 割り当て結果判定 */
129             if ( ( pKernelStack == NULL ) ||
130                  ( pStack       == NULL )    ) {
131                 /* 失敗 */
132                 
133                 /* [TODO] */
134                 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
135                 
136                 return PROCMNG_TASK_ID_NULL;
137             }
138             
139             /* タスク基本設定 */
140             gTaskTbl[ taskId ].used        = TASK_ID_USED;
141             gTaskTbl[ taskId ].type        = taskType;
142             gTaskTbl[ taskId ].state       = 0;
143             gTaskTbl[ taskId ].context.eip = ( uint32_t ) ProcMngTaskStart;
144             gTaskTbl[ taskId ].context.esp = ( uint32_t ) pKernelStack + TASK_KERNEL_STACK_SIZE;
145             gTaskTbl[ taskId ].pEntryPoint = pEntryPoint;
146             
147             /* カーネルスタック情報設定 */
148             pStackInfo              = &( gTaskTbl[ taskId ].kernelStackInfo );
149             pStackInfo->pTopAddr    = pKernelStack;
150             pStackInfo->pBottomAddr = pKernelStack + TASK_KERNEL_STACK_SIZE;
151             pStackInfo->size        = TASK_KERNEL_STACK_SIZE;
152             
153             /* スタック情報設定 */
154             pStackInfo              = &( gTaskTbl[ taskId ].stackInfo );
155             pStackInfo->pTopAddr    = pStack;
156             pStackInfo->pBottomAddr = pStack + TASK_STACK_SIZE;
157             pStackInfo->size        = TASK_STACK_SIZE;
158             
159             /* スケジューラ追加 */
160             ret = ProcMngSchedAdd( taskId );
161             
162             /* 追加結果判定 */
163             if ( ret == CMN_FAILURE ) {
164                 /* 失敗 */
165                 
166                 /* [TODO] */
167                 /* 設定したタスクを初期化する処理。異常処理はちょっと後回し */
168                 
169                 return PROCMNG_TASK_ID_NULL;
170             }
171             
172             /* デバッグトレースログ出力 */
173             DEBUG_LOG( "%s() end. ret=%u", __func__, taskId );
174             
175             return taskId;
176         }
177     }
178     
179     /* デバッグトレースログ出力 */
180     DEBUG_LOG( "%s() end. ret=%u", __func__, PROCMNG_TASK_ID_NULL );
181     
182     return PROCMNG_TASK_ID_NULL;
183 }
184
185
186 /******************************************************************************/
187 /**
188  * @brief       コンテキスト取得
189  * @details     指定したタスクIDのコンテキストを取得する。
190  * 
191  * @param[in]   taskId タスクID
192  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
193  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
194  * 
195  * @return      コンテキスト
196  */
197 /******************************************************************************/
198 ProcMngTaskContext_t ProcMngTaskGetContext( uint32_t taskId )
199 {
200     /* コンテキスト返却 */
201     return gTaskTbl[ taskId ].context;
202 }
203
204
205 /******************************************************************************/
206 /**
207  * @brief       カーネルスタックアドレス取得
208  * @details     指定したタスクIDのカーネルスタックアドレスを取得する。
209  * 
210  * @param[in]   taskId タスクID
211  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
212  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
213  * 
214  * @return      カーネルスタックアドレス
215  */
216 /******************************************************************************/
217 void *ProcMngTaskGetKernelStack( uint32_t taskId )
218 {
219     /* カーネルスタックアドレス返却 */
220     return gTaskTbl[ taskId ].kernelStackInfo.pBottomAddr;
221 }
222
223
224 /******************************************************************************/
225 /**
226  * @brief       タスクタイプ取得
227  * @details     指定したタスクIDのタスクタイプを取得する。
228  * 
229  * @param[in]   taskId タスクID
230  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
231  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
232  * 
233  * @retval      PROCMNG_TASK_TYPE_DRIVER ドライバ
234  * @retval      PROCMNG_TASK_TYPE_SERVER サーバ
235  * @retval      PROCMNG_TASK_TYPE_USER   ユーザ
236  */
237 /******************************************************************************/
238 uint8_t ProcMngTaskGetType( uint32_t taskId )
239 {
240     /* タスクタイプ返却 */
241     return gTaskTbl[ taskId ].type;
242 }
243
244
245 /******************************************************************************/
246 /**
247  * @brief       タスク管理初期化
248  * @details     タスク管理サブモジュールの初期化を行う。
249  */
250 /******************************************************************************/
251 void ProcMngTaskInit( void )
252 {
253     /* デバッグトレースログ出力 */
254     DEBUG_LOG( "%s() start.", __func__ );
255     
256     /* タスク管理テーブル初期化 */
257     memset( gTaskTbl, 0, sizeof ( gTaskTbl ) );
258     
259     /* アイドルタスク設定 */
260     gTaskTbl[ PROCMNG_TASK_ID_IDLE ].used = TASK_ID_USED;   /* 使用フラグ */
261     
262     /* デバッグトレースログ出力 */
263     DEBUG_LOG( "%s() end.", __func__ );
264     
265     return;
266 }
267
268
269 /******************************************************************************/
270 /**
271  * @brief       コンテキスト設定
272  * @details     指定したタスクIDのコンテキストを設定する。
273  * 
274  * @param[in]   taskId    設定先タスクID
275  *                  - PROCMNG_TASK_ID_MIN タスクID最小値
276  *                  - PROCMNG_TASK_ID_MAX タスクID最大値
277  * @param[in]   *pContext コンテキスト
278  */
279 /******************************************************************************/
280 void ProcMngTaskSetContext( uint32_t             taskId,
281                             ProcMngTaskContext_t *pContext )
282 {
283     /* コンテキスト設定 */
284     gTaskTbl[ taskId ].context = *pContext;
285     
286     return;
287 }
288
289
290 /******************************************************************************/
291 /**
292  * @brief       タスク起動開始
293  * @details     タスクの起動を開始する。
294  */
295 /******************************************************************************/
296 void ProcMngTaskStart( void )
297 {
298     void      *pEntryPoint; /* エントリポイント         */
299     void      *pStack;      /* スタックアドレス         */
300     uint8_t   taskType;     /* タスクタイプ             */
301     uint32_t  taskId;       /* タスクID                 */
302     uint32_t  codeSegSel;   /* コードセグメントセレクタ */
303     uint32_t  dataSegSel;   /* データセグメントセレクタ */
304     taskTbl_t *pTask;       /* タスク管理情報           */
305     
306     /* デバッグトレースログ出力 */
307     DEBUG_LOG( "%s() start.", __func__ );
308     
309     /* 初期化 */
310     taskId      = ProcMngSchedGetTaskId();      /* タスクID         */
311     pTask       = &( gTaskTbl[ taskId ] );      /* タスク管理情報   */
312     pEntryPoint = pTask->pEntryPoint;           /* エントリポイント */
313     pStack      = pTask->stackInfo.pBottomAddr; /* スタックアドレス */
314     taskType    = pTask->type;                  /* タスクタイプ     */
315     
316     /* デバッグトレースログ出力 */
317     DEBUG_LOG( "taskId=%d, pEntryPoint=%p, pStack=%p",
318                taskId,
319                pEntryPoint,
320                pStack );
321     
322     /* タスクタイプ判定 */
323     if ( taskType == PROCMNG_TASK_TYPE_DRIVER ) {
324         /* ドライバ */
325         
326         /* セグメントセレクタ設定 */
327         codeSegSel = MEMMNG_SEGSEL_DRIVER_CODE;     /* コード */
328         dataSegSel = MEMMNG_SEGSEL_DRIVER_DATA;     /* データ */
329         
330     } else if ( taskType == PROCMNG_TASK_TYPE_SERVER ) {
331         /* サーバ */
332         
333         codeSegSel = MEMMNG_SEGSEL_SERVER_CODE;     /* コード */
334         dataSegSel = MEMMNG_SEGSEL_SERVER_DATA;     /* データ */
335         
336     } else {
337         /* ユーザ */
338         
339         codeSegSel = MEMMNG_SEGSEL_USER_CODE;       /* コード */
340         dataSegSel = MEMMNG_SEGSEL_USER_DATA;       /* データ */
341     }
342     
343     /* iretd命令用スタック設定 */
344     IA32InstructionPush( dataSegSel );              /* ss     */
345     IA32InstructionPush( ( uint32_t ) pStack );     /* esp    */
346     IA32InstructionPush( 0x00003202 );              /* eflags */
347     IA32InstructionPush( codeSegSel );              /* cs     */
348     IA32InstructionPush( ( uint32_t ) pEntryPoint );/* eip    */
349     
350     /* セグメントレジスタ設定用スタック設定 */
351     IA32InstructionPush( dataSegSel );              /* gs */
352     IA32InstructionPush( dataSegSel );              /* fs */
353     IA32InstructionPush( dataSegSel );              /* es */
354     IA32InstructionPush( dataSegSel );              /* ds */
355     
356     /* 汎用レジスタ設定用スタック設定 */
357     IA32InstructionPush( 0 );                       /* eax           */
358     IA32InstructionPush( 0 );                       /* ecx           */
359     IA32InstructionPush( 0 );                       /* edx           */
360     IA32InstructionPush( 0 );                       /* ebx           */
361     IA32InstructionPush( 0 );                       /* esp( 未使用 ) */
362     IA32InstructionPush( 0 );                       /* ebp           */
363     IA32InstructionPush( 0 );                       /* esi           */
364     IA32InstructionPush( 0 );                       /* edi           */
365     
366     /* 汎用レジスタ設定 */
367     IA32InstructionPopad();
368     
369     /* セグメントレジスタ設定 */
370     IA32InstructionPopDs();
371     IA32InstructionPopEs();
372     IA32InstructionPopFs();
373     IA32InstructionPopGs();
374     
375     /* タスクエントリポイントへ移行 */
376     IA32InstructionIretd();
377     
378     /* not return */
379 }
380
381
382 /******************************************************************************/