POK(kernelpart)
/home/jaouen/pok_official/pok/trunk/kernel/core/thread.c
Go to the documentation of this file.
00001 /*
00002  *                               POK header
00003  *
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team
00013  *
00014  * Created by julien on Thu Jan 15 23:34:13 2009
00015  */
00016 
00024 #include <types.h>
00025 
00026 #include <arch.h>
00027 #include <core/debug.h>
00028 #include <core/error.h>
00029 #include <core/thread.h>
00030 #include <core/sched.h>
00031 #include <core/partition.h>
00032 #include <core/time.h>
00033 
00034 #include <core/instrumentation.h>
00035 
00036 #ifdef POK_NEEDS_THREADS
00037 
00044 pok_thread_t                     pok_threads[POK_CONFIG_NB_THREADS];
00045 
00046 extern pok_partition_t     pok_partitions[POK_CONFIG_NB_PARTITIONS];
00047 
00048 #ifdef POK_NEEDS_SCHED_RMS
00049 
00054 void pok_thread_insert_sort(uint16_t index_low, uint16_t index_high)
00055 {
00056     uint32_t i=index_high,j=0;
00057     pok_thread_t val;
00058 
00059     val=pok_threads[i];
00060     j=i-1;
00061     while ( j>= index_low && pok_threads[j].period > val.period)
00062     {
00063         pok_threads[j+1] = pok_threads[j];
00064         j--;
00065     }
00066     pok_threads[j+1]=val;
00067 }
00068 #endif
00069 
00070 
00075 void pok_thread_init(void)
00076 {
00077    uint32_t i;
00078 
00079 #ifdef POK_NEEDS_PARTITIONS
00080    uint32_t total_threads;
00081    uint8_t  j;
00082 
00083    total_threads = 0;
00084 
00085    for (j = 0 ; j < POK_CONFIG_NB_PARTITIONS ; j++)
00086    {
00087       total_threads = total_threads + pok_partitions[j].nthreads;
00088    }
00089 
00090 #if defined (POK_NEEDS_DEBUG) || defined (POK_NEEDS_ERROR_HANDLING)
00091    if (total_threads != (POK_CONFIG_NB_THREADS - 2))
00092    {
00093 #ifdef POK_NEEDS_DEBUG
00094       printf ("Error in configuration, bad number of threads\n");
00095 #endif
00096 #ifdef POK_NEEDS_ERROR_HANDLING
00097       pok_kernel_error (POK_ERROR_KIND_KERNEL_CONFIG);
00098 #endif
00099    }
00100 #endif
00101 #endif
00102 
00103    pok_threads[KERNEL_THREAD].priority     = pok_sched_get_priority_min(0);
00104    pok_threads[KERNEL_THREAD].base_priority        = pok_sched_get_priority_min(0);
00105    pok_threads[KERNEL_THREAD].state                = POK_STATE_RUNNABLE;
00106    pok_threads[KERNEL_THREAD].next_activation = 0;
00107 
00108    pok_threads[IDLE_THREAD].period                     = 0;
00109    pok_threads[IDLE_THREAD].deadline                   = 0;
00110    pok_threads[IDLE_THREAD].time_capacity              = 0;
00111    pok_threads[IDLE_THREAD].next_activation            = 0;
00112    pok_threads[IDLE_THREAD].remaining_time_capacity    = 0;
00113    pok_threads[IDLE_THREAD].wakeup_time                = 0;
00114    pok_threads[IDLE_THREAD].entry                      = pok_arch_idle;
00115    pok_threads[IDLE_THREAD].base_priority                      = pok_sched_get_priority_min(0);
00116    pok_threads[IDLE_THREAD].state                      = POK_STATE_RUNNABLE;
00117 
00118    pok_threads[IDLE_THREAD].sp                         = pok_context_create
00119                                                    (IDLE_THREAD,                                                                             IDLE_STACK_SIZE,
00120                                                    (uint32_t)pok_arch_idle);
00121 
00122    for (i = 0; i < POK_CONFIG_NB_THREADS; ++i)
00123    {
00124       pok_threads[i].period                     = 0;
00125       pok_threads[i].deadline                   = 0;
00126       pok_threads[i].time_capacity              = 0;
00127       pok_threads[i].remaining_time_capacity    = 0;
00128       pok_threads[i].next_activation            = 0;
00129       pok_threads[i].wakeup_time                = 0;
00130       pok_threads[i].state                      = POK_STATE_STOPPED;
00131   }
00132 }
00133 
00134 #ifdef POK_NEEDS_PARTITIONS
00135 
00141 pok_ret_t pok_partition_thread_create (uint32_t*                  thread_id,
00142                                        const pok_thread_attr_t*   attr,
00143                                        const uint8_t              partition_id)
00144 {
00145    uint32_t id;
00146    uint32_t stack_vaddr;
00150    if (  (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_COLD) &&
00151          (pok_partitions[partition_id].mode != POK_PARTITION_MODE_INIT_WARM) )
00152    {
00153       return POK_ERRNO_MODE;
00154    }
00155 
00156    if (pok_partitions[partition_id].thread_index >= pok_partitions[partition_id].thread_index_high)
00157    {
00158 #ifdef POK_NEEDS_ERROR_HANDLING
00159       POK_ERROR_CURRENT_PARTITION (POK_ERROR_KIND_PARTITION_CONFIGURATION);
00160 #endif
00161       return POK_ERRNO_TOOMANY;
00162    }
00163 
00164    id = pok_partitions[partition_id].thread_index_low +  pok_partitions[partition_id].thread_index;
00165    pok_partitions[partition_id].thread_index =  pok_partitions[partition_id].thread_index + 1;
00166 
00167     if ((attr->priority <= pok_sched_get_priority_max (pok_partitions[partition_id].sched)) && (attr->priority >= pok_sched_get_priority_min (pok_partitions[partition_id].sched)))
00168    {
00169       pok_threads[id].priority      = attr->priority;
00170       pok_threads[id].base_priority      = attr->priority;
00171    }
00172 
00173    if (attr->period > 0)
00174    {
00175       pok_threads[id].period          = attr->period;
00176       pok_threads[id].next_activation = attr->period;
00177    }
00178 
00179    if (attr->deadline > 0)
00180    {
00181       pok_threads[id].deadline      = attr->deadline;
00182    }
00183 
00184 #ifdef POK_NEEDS_SCHED_HFPPS
00185    pok_threads[id].payback = 0;
00186 #endif /* POK_NEEDS_SCHED_HFPPS */
00187 
00188    if (attr->time_capacity > 0)
00189    {
00190       pok_threads[id].time_capacity = attr->time_capacity;
00191       pok_threads[id].remaining_time_capacity = attr->time_capacity;
00192    }
00193    else
00194    {
00195       pok_threads[id].remaining_time_capacity   = POK_THREAD_DEFAULT_TIME_CAPACITY;
00196       pok_threads[id].time_capacity             = POK_THREAD_DEFAULT_TIME_CAPACITY;
00197    }
00198 
00199    stack_vaddr = pok_thread_stack_addr (partition_id, pok_partitions[partition_id].thread_index);
00200 
00201    pok_threads[id].state                   = POK_STATE_RUNNABLE;
00202    pok_threads[id].wakeup_time   = 0;
00203    pok_threads[id].sp                 = pok_space_context_create (partition_id,
00204                                                              (uint32_t)attr->entry,
00205                                                              stack_vaddr,
00206                                                              0xdead,
00207                                                              0xbeaf);
00208    /*
00209     *  FIXME : current debug session about exceptions-handled
00210    printf ("thread sp=0x%x\n", pok_threads[id].sp);
00211    printf ("thread stack vaddr=0x%x\n", stack_vaddr);
00212    */
00213    pok_threads[id].partition        = partition_id; 
00214    pok_threads[id].entry            = attr->entry;
00215    pok_threads[id].init_stack_addr  = stack_vaddr;
00216    *thread_id = id;
00217 
00218 #ifdef POK_NEEDS_SCHED_RMS
00219    if ((pok_partitions[partition_id].sched == POK_SCHED_RMS) && (id > pok_partitions[partition_id].thread_index_low))
00220    {
00221       pok_thread_insert_sort(pok_partitions[partition_id].thread_index_low+1,id);
00222    }
00223 #endif
00224 
00225 #ifdef POK_NEEDS_INSTRUMENTATION
00226       pok_instrumentation_task_archi (id);
00227 #endif
00228 
00229    return POK_ERRNO_OK;
00230 }
00231 #endif
00232 
00233 
00238 void pok_thread_start(void (*entry)(), unsigned int id)
00239 {
00240    (void) id;
00241    entry();
00242 }
00243 
00244 #ifdef POK_NEEDS_THREAD_SLEEP
00245 pok_ret_t pok_thread_sleep (uint32_t time)
00246 {
00247    uint64_t mytime;
00248    mytime = time + POK_GETTICK();
00249    pok_sched_lock_current_thread_timed (mytime);
00250    pok_sched ();
00251    return POK_ERRNO_OK;
00252 }
00253 #endif
00254 
00255 #ifdef POK_NEEDS_THREAD_SLEEP_UNTIL
00256 pok_ret_t pok_thread_sleep_until (uint32_t time)
00257 {
00258    pok_sched_lock_current_thread_timed ((uint64_t)time);
00259    pok_sched ();
00260    return POK_ERRNO_OK;
00261 }
00262 #endif
00263 
00264 #if defined (POK_NEEDS_THREAD_SUSPEND) || defined (POK_NEEDS_ERROR_HANDLING)
00265 pok_ret_t pok_thread_suspend (void)
00266 {
00267    pok_sched_stop_self ();
00268    pok_sched ();
00269    return POK_ERRNO_OK;
00270 }
00271 #endif
00272 
00273 #ifdef POK_NEEDS_ERROR_HANDLING
00274 pok_ret_t pok_thread_restart (const uint32_t tid)
00275 {
00280    pok_threads[tid].remaining_time_capacity  = pok_threads[tid].time_capacity;
00281    pok_threads[tid].state                    = POK_STATE_WAIT_NEXT_ACTIVATION;
00282    pok_threads[tid].wakeup_time              = 0;
00283 
00295    pok_threads[tid].sp                = pok_space_context_create (pok_threads[tid].partition,
00296                                                              (uint32_t)pok_threads[tid].entry,
00297                                                              pok_threads[tid].init_stack_addr,
00298                                                              0xdead,
00299                                                              0xbeaf);
00300 
00301    return POK_ERRNO_OK;
00302 }
00303 #endif
00304 
00305 pok_ret_t pok_thread_delayed_start (const uint32_t id, const uint32_t ms)
00306 {
00307   if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
00308     return POK_ERRNO_THREADATTR;
00309   pok_threads[id].priority = pok_threads[id].base_priority;
00310   //reset stack
00311   pok_context_reset(POK_USER_STACK_SIZE,pok_threads[id].init_stack_addr);
00312   if ((long long)pok_threads[id].period == -1) //-1 <==> ARINC INFINITE_TIME_VALUE
00313     {
00314       if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL)
00315         {
00316           if (ms == 0)
00317             {
00318               pok_threads[id].state = POK_STATE_RUNNABLE;
00319               pok_threads[id].end_time = POK_GETTICK() + pok_threads[id].time_capacity;
00320             }
00321           else
00322             {
00323               pok_threads[id].state = POK_STATE_WAITING;
00324               pok_threads[id].wakeup_time = POK_GETTICK() + ms;
00325             }
00326           //the preemption is always enabled so
00327           pok_sched();
00328         }
00329       else //the partition mode is cold or warm start
00330         {
00331           pok_threads[id].state = POK_STATE_DELAYED_START;
00332           pok_threads[id].wakeup_time = ms;
00333         }
00334     }
00335   else
00336     {
00337       if (pok_partitions[pok_threads[id].partition].mode == POK_PARTITION_MODE_NORMAL)
00338             { // set the first release point
00339               pok_threads[id].next_activation = ms + POK_GETTICK();
00340               pok_threads[id].end_time = pok_threads[id].deadline + pok_threads[id].next_activation;
00341             }
00342       else
00343            {
00344              pok_threads[id].state = POK_STATE_DELAYED_START;
00345              pok_threads[id].wakeup_time = ms; // temporarly storing the delay, see set_partition_mode
00346            }
00347     }
00348   return POK_ERRNO_OK;
00349 }
00350 
00351 pok_ret_t pok_thread_get_status (const uint32_t id, pok_thread_attr_t *attr)
00352 {
00353   if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
00354     return POK_ERRNO_PARAM;
00355   attr->deadline = pok_threads[id].end_time;
00356   attr->state = pok_threads[id].state;
00357   attr->priority = pok_threads[id].priority;
00358   attr->entry = pok_threads[id].entry;
00359   attr->period = pok_threads[id].period;
00360   attr->time_capacity = pok_threads[id].time_capacity;
00361   attr->stack_size = POK_USER_STACK_SIZE;
00362   return POK_ERRNO_OK;
00363 }
00364 
00365 pok_ret_t      pok_thread_set_priority (const uint32_t id, const uint32_t priority)
00366 {
00367         if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
00368                 return POK_ERRNO_PARAM;
00369         pok_threads[id].priority = priority;
00370         /* preemption is always enabled so ... */
00371         pok_sched();
00372         return POK_ERRNO_OK;
00373 }
00374 
00375 pok_ret_t pok_thread_resume (const uint32_t id)
00376 {
00377         if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id)
00378                 return POK_ERRNO_THREADATTR;
00379         pok_threads[id].wakeup_time = POK_GETTICK();
00380         pok_threads[id].state = POK_STATE_RUNNABLE;
00381         /* preemption is always enabled */
00382         pok_sched();
00383         return POK_ERRNO_OK;
00384 }
00385 
00386 pok_ret_t pok_thread_suspend_target (const uint32_t id)
00387 {
00388         if (POK_CURRENT_PARTITION.thread_index_low > id || POK_CURRENT_PARTITION.thread_index_high < id || id == POK_SCHED_CURRENT_THREAD)
00389                 return POK_ERRNO_THREADATTR;
00390         pok_threads[id].state = POK_STATE_STOPPED;
00391         return POK_ERRNO_OK;
00392 }
00393 
00394 #endif