]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/task_i.c
Work in progress. Remaking scheduling.
[arc.git] / system / kernel / task_i.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23 \r
24 #include "Os.h"\r
25 #include "pcb.h"\r
26 #include "sys.h"\r
27 #include <stdlib.h>\r
28 //#include "arch_offset.h"\r
29 #include "hooks.h"\r
30 #include "task_i.h"\r
31 #include "arch.h"\r
32 #include "ext_config.h"\r
33 #include "assert.h"\r
34 #include "internal.h"\r
35 \r
36 _Bool os_pcb_pid_valid( pcb_t *restrict pcb ) {\r
37         return ( pcb->pid > Oil_GetTaskCnt() ) ? 0 : 1;\r
38 }\r
39 /**\r
40  * Start an extended task.\r
41  * Tasks done:\r
42  * - Grab the internal resource for the process\r
43  * - Set it running state.\r
44  * - Start to execute the process\r
45  *\r
46  */\r
47 void os_proc_start_extended( void ) {\r
48         pcb_t *pcb;\r
49 \r
50         // TODO: Get internal resource\r
51         PRETASKHOOK();\r
52 \r
53         pcb = os_get_curr_pcb();\r
54         os_resource_get_internal();\r
55         os_pcb_make_running(pcb);\r
56 \r
57         os_arch_first_call();\r
58 \r
59         // If we have a extented process that that exits, we end up here\r
60         // See OS052,OS069, Autosar SWS\r
61         ERRORHOOK(E_OS_MISSINGEND);\r
62 \r
63         /* TODO: Terminate the task */\r
64         //while(1);\r
65 }\r
66 \r
67 /**\r
68  * Start an basic task.\r
69  * See extended task.\r
70  */\r
71 \r
72 void os_proc_start_basic( void ) {\r
73         pcb_t *pcb;\r
74 \r
75         // TODO: Get internal resource\r
76         PRETASKHOOK();\r
77 \r
78         pcb = os_get_curr_pcb();\r
79         os_resource_get_internal();\r
80         os_pcb_make_running(pcb);\r
81         os_arch_first_call();\r
82 \r
83         TerminateTask();\r
84 //      ERRORHOOK(E_OS_MISSINGEND);\r
85 }\r
86 \r
87 /**\r
88  * Setup the context for a pcb. The context differs for different arch's\r
89  * so we call the arch dependent functions also.\r
90  * The context at setup is always a small context.\r
91  *
92  * @param pcb Ptr to the pcb to setup context for.
93  */\r
94 void os_setup_context( pcb_t *pcb ) {\r
95         uint8_t *bottom;\r
96 \r
97         /* Find bottom of the stack so that we can place the\r
98          * context there.\r
99          *\r
100          * stack bottom = high address. stack top = low address\r
101          */\r
102         bottom = (uint8_t *)pcb->stack.top + pcb->stack.size;\r
103         pcb->stack.curr = bottom;\r
104         // TODO: aligments here..\r
105         // TODO :use function os_arch_get_call_size() ??\r
106 \r
107         // Make some space for back-chain.\r
108         bottom -= 16;\r
109         // Set the current stack so that it points to the context\r
110         pcb->stack.curr = bottom - os_arch_get_sc_size();\r
111 \r
112         os_arch_setup_context(pcb);\r
113 }\r
114 \r
115 /**\r
116  * Search for a specific task in the pcb list.\r
117  *
118  * @param tid The task id to search for
119  * @return Ptr to the found pcb or NULL
120  */\r
121 pcb_t *os_find_task( TaskType tid ) {\r
122         pcb_t *i_pcb;\r
123 \r
124         /* TODO: Implement this as an array */\r
125         TAILQ_FOREACH(i_pcb,& os_sys.pcb_head,pcb_list) {\r
126                 if(i_pcb->pid == tid ) {\r
127                         return i_pcb;\r
128                 }\r
129         }\r
130         assert(0);\r
131         return NULL;\r
132 }\r
133 \r
134 /**\r
135  * Adds a pcb to the list of pcb's
136  * @param pcb
137  */\r
138 TaskType os_add_task( pcb_t *pcb ) {\r
139         long msr;
140
141         Irq_Save(msr);  // Save irq status and disable interrupts\r
142 \r
143         pcb->pid = os_sys.task_cnt;\r
144         // Add to list of PCB's\r
145         TAILQ_INSERT_TAIL(& os_sys.pcb_head,pcb,pcb_list);\r
146         os_sys.task_cnt++;\r
147 \r
148         Irq_Restore(msr);  // Restore interrupts
149         return pcb->pid;\r
150 }\r
151 \r
152 \r
153 #define PRIO_ILLEGAL    -100\r
154 // TODO: we can't have O(n) search here.. hash on prio instead\r
155 \r
156 /**\r
157  * Find the top priority task. Even the running task is included.\r
158  *
159  * @return
160  */\r
161 \r
162 pcb_t *os_find_top_prio_proc( void ){\r
163         pcb_t *i_pcb;\r
164         pcb_t *top_prio_pcb = NULL;\r
165         prio_t top_prio = PRIO_ILLEGAL;\r
166 \r
167         os_isr_printf(D_TASK,"os_find_top_prio_proc\n");\r
168 \r
169         TAILQ_FOREACH(i_pcb,& os_sys.ready_head,ready_list) {\r
170                 // all ready task are canidates\r
171                 if( i_pcb->state & (ST_READY|ST_RUNNING)) {\r
172                         if( top_prio != PRIO_ILLEGAL ) {\r
173                                 if( i_pcb->prio > top_prio ) {\r
174                                         top_prio = i_pcb->prio;\r
175                                         top_prio_pcb = i_pcb;\r
176                                 }\r
177                         } else {\r
178                                 top_prio = i_pcb->prio;\r
179                                 top_prio_pcb = i_pcb;\r
180                         }\r
181                 } else {\r
182                         assert(0);\r
183                 }\r
184         }\r
185         os_isr_printf(D_TASK,"Found %s\n",top_prio_pcb->name);\r
186 \r
187         return top_prio_pcb;\r
188 }\r
189 \r
190 /**\r
191  * Used at startup to initialize a pcb. Is sometimes\r
192  * used to restore the state of a basic process.\r
193  *
194  * @param pcb The pcb to make virgin
195  */\r
196 \r
197 void os_pcb_make_virgin( pcb_t *pcb ) {\r
198         if( pcb->autostart ) {\r
199                 os_pcb_make_ready(pcb);\r
200         } else {\r
201                 pcb->state = ST_SUSPENDED;\r
202         }\r
203 \r
204         /* TODO: cleanup resource here ?? */\r
205         pcb->ev_set = 0;\r
206         pcb->ev_wait = 0;\r
207 \r
208         os_setup_context(pcb);\r
209 }\r
210 \r
211 #if 0\r
212 pcb_t *os_find_higher_priority_task( prio_t prio ) {\r
213         pcb_t *i_pcb;\r
214         pcb_t *h_prio_pcb = NULL;\r
215         prio_t t_prio = prio;\r
216 \r
217         TAILQ_FOREACH(i_pcb,& os_sys.ready_head,ready_list) {\r
218                 if( i_pcb->prio > t_prio ) {\r
219                         t_prio = i_pcb->prio;\r
220                         h_prio_pcb = i_pcb;\r
221                 }\r
222         }\r
223         return h_prio_pcb;\r
224 }\r
225 #endif\r
226 \r
227 \r