ISIX-RTOS - small operating system for ARM microcontrollers 1.2

multiple_objects.c

Go to the documentation of this file.
00001 /*
00002  * multiple_objects.c
00003  *
00004  *  Created on: 24-03-2011
00005  *      Author: lucck
00006  */
00007 
00008 /*--------------------------------------------------------------*/
00009 #ifdef ISIX_CONFIG_USE_MULTIOBJECTS     //If timers are enabled
00010 
00011 /*--------------------------------------------------------------*/
00012 #include <isix/config.h>
00013 #include <isix/types.h>
00014 #include <isix/semaphore.h>
00015 #include <prv/semaphore.h>
00016 #include <prv/fifo.h>
00017 #include <isix/multiple_objects.h>
00018 #include <prv/list.h>
00019 #include <prv/scheduler.h>
00020 #include <isix/error.h>
00021 #include <prv/multiple_objects.h>
00022 /*--------------------------------------------------------------*/
00023 #ifndef ISIX_DEBUG_MULTIOBJECTS
00024 #define ISIX_DEBUG_MULTIOBJECTS ISIX_DBG_OFF
00025 #endif
00026 
00027 
00028 #if ISIX_DEBUG_MULTIOBJECTS == ISIX_DBG_ON
00029 #include <isix/printk.h>
00030 #else
00031 #define isix_printk(...)
00032 #endif
00033 
00034 
00035 
00036 /*--------------------------------------------------------------*/
00037 //Multiple objects wating list
00038 static list_entry_t waiting_objects;
00039 
00040 /*--------------------------------------------------------------*/
00041 //Initialize the multiple objects waiting
00042 void ixixp_multiple_objects_init( void )
00043 {
00044         list_init( &waiting_objects );
00045 }
00046 
00047 /*--------------------------------------------------------------*/
00048 //Return taskID waiting for semgroup
00049 int isixp_wakeup_multiple_waiting_tasks( const sem_t *sem, int (*wkup_fun)(task_t *) )
00050 {
00051         isixp_enter_critical();
00052         prio_t prio = isix_get_min_priority();
00053         multiple_obj_t *mobj;
00054         list_for_each_entry( &waiting_objects, mobj, inode)
00055         {
00056                 for(size_t s=0; s<mobj->ihwnd_len; s++)
00057                 {
00058                         if(mobj->ihwnd[s].sem->type == IHANDLE_T_SEM)
00059                         {
00060                                 if( mobj->ihwnd[s].sem == sem )
00061                                 {
00062                                         if(mobj->task_id->prio < prio ) prio = mobj->task_id->prio;
00063                                         int retval = wkup_fun(mobj->task_id);
00064                                         if(retval<0) { isixp_exit_critical(); return retval;} else break;
00065                                 }
00066                         }
00067                         else if(mobj->ihwnd[s].sem->type == IHANDLE_T_FIFO)
00068                         {
00069                                 if( &mobj->ihwnd[s].fifo->rx_sem == sem )
00070                                 {
00071                                         if(mobj->task_id->prio < prio ) prio = mobj->task_id->prio;
00072                                         int retval = wkup_fun(mobj->task_id);
00073                                         if(retval<0) { isixp_exit_critical(); return retval;} else break;
00074                                 }
00075                         }
00076                 }
00077         }
00078         isixp_exit_critical();
00079         return prio;
00080 }
00081 /*--------------------------------------------------------------*/
00082 //Delete obj item
00083 void isixp_delete_from_multiple_wait_list(const task_t *task )
00084 {
00085         isixp_enter_critical();
00086         multiple_obj_t *mobj;
00087         list_for_each_entry( &waiting_objects, mobj, inode)
00088         {
00089                 if( mobj->task_id == task )
00090                 {
00091                         list_delete( &mobj->inode );
00092                         break;
00093                 }
00094         }
00095         isixp_exit_critical();
00096 }
00097 
00098 /*--------------------------------------------------------------*/
00099 int isix_wait_for_multiple_objects(size_t count, tick_t timeout, const ihandle_t *hwnd)
00100 {
00101         int retval = ISIX_EOK;
00102         //If nothing to to - exit
00103         if( hwnd==NULL  ) return ISIX_EINVARG;
00104         multiple_obj_t multiple_obj =
00105         {
00106                 hwnd, count, isix_current_task, {NULL, NULL}
00107         };
00108     //Enter critical state
00109         isixp_enter_critical();
00110         //Check if any fifo.rxsem, or sem is signaled
00111         for(size_t o = 0; o < count; o++)
00112         {
00113                 if( hwnd[o].sem->type == IHANDLE_T_SEM )
00114                 {
00115                         if( hwnd[o].sem->value > 0 )
00116                         {
00117                                 isixp_exit_critical();
00118                 return o+1;
00119                         }
00120                 }
00121                 else if( hwnd[o].sem->type == IHANDLE_T_FIFO )
00122                 {
00123                         if( hwnd[o].fifo->rx_sem.value > 0 )
00124                         {
00125                                 isixp_exit_critical();
00126                 return o+1;
00127                         }
00128                 }
00129                 else
00130                 {
00131                         isix_printk("Obj is not fifo and it is not sem. Stack corrupted?");
00132                         isix_bug();
00133                 }
00134         }
00135     do {
00136                 //Add to waiting object group
00137                 list_insert_end( &waiting_objects, &multiple_obj.inode );
00138                 if(isix_current_task->state & TASK_READY)
00139                 {
00140                                 isix_current_task->state &= ~(TASK_READY| TASK_RUNNING );
00141                                 isixp_delete_task_from_ready_list(isix_current_task);
00142                                 isix_printk("Delete task from ready list");
00143                 }
00144                         //If any task remove task from ready list
00145                 if(timeout)
00146                 {
00147                         //Add to waiting list
00148                         isixp_add_task_to_waiting_list(isix_current_task,timeout);
00149                         isix_current_task->state |= TASK_SLEEPING;
00150                         isix_printk("Wait after %d ticks",isix_current_task->jiffies);
00151                 }
00152                 //Note state to wait for multiple objects
00153                 isix_current_task->state |= TASK_WAITING_MULTIPLE;
00154                 //Yield the CPU
00155                 isixp_exit_critical();
00156                 isix_yield();
00157                 //Section back to the task after the wakeup
00158                 isixp_enter_critical();
00159                 isix_printk("After wakeup task state 0x%02x", isix_current_task->state );
00160                 if(!(isix_current_task->state & TASK_MULTIPLE_WKUP))
00161                 {
00162                         retval = ISIX_ETIMEOUT;
00163                         break;
00164                 }
00165                 for( size_t o = 0; o < count; o++ )
00166                 {
00167                         if( hwnd[o].sem->type == IHANDLE_T_SEM )
00168                         {
00169                                 isix_printk("Sem value %d",hwnd[o].sem->value);
00170                                 if( hwnd[o].sem->value > 0)
00171                                 {
00172                                         retval = o+1; break;
00173                                 }
00174                         }
00175                         else if( hwnd[o].sem->type == IHANDLE_T_FIFO )
00176                         {
00177                                 isix_printk("Fifo value %d",hwnd[o].sem->value);
00178                                 if( hwnd[o].fifo->rx_sem.value > 0 )
00179                                 {
00180                                         retval = o+1; break;
00181                                 }
00182                         }
00183                         else
00184                         {
00185                                 isix_printk("Obj is not fifo and it is not sem. Stack corrupted?");
00186                                 isix_bug();
00187                         }
00188                 }
00189         } while(0);
00190         //Delete from object group list
00191         if( multiple_obj.inode.next ) list_delete( &multiple_obj.inode );
00192         if( retval == ISIX_EOK )
00193         {
00194                 isix_printk("Waiting task not found when it is excepted task_state %02x",isix_current_task->state);
00195                 isix_bug();
00196         }
00197         //Exit critical section
00198         isixp_exit_critical();
00199         //return
00200         return retval;
00201 }
00202 /*--------------------------------------------------------------*/
00203 #else
00204 
00205 //NOTE: avoid warning iso C forbid empty translation unit
00206 static inline void ixixp_multiple_objects_init( void ) {}
00207 
00208 #endif /* ISIX_CONFIG_USE_MULTIOBJECTS */
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines