ISIX-RTOS - small operating system for ARM microcontrollers 1.2
|
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 */