00001 /*************************************************************************** 00002 * lock.c 00003 * (C) 2010 Ivan Meleca 00004 * Based on original code written by Ruben Meleca 00005 * www.milos.it 00006 00007 # This program is free software; you can redistribute it and/or modify 00008 # it under the terms of the GNU General Public License as published by 00009 # the Free Software Foundation; either version 2 of the License, or 00010 # (at your option) any later version. 00011 # 00012 # This program is distributed in the hope that it will be useful, 00013 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 # GNU General Public License for more details. 00016 # 00017 # You should have received a copy of the GNU General Public License 00018 # along with this program; if not, write to the Free Software 00019 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 ***************************************************************************/ 00022 00023 #include "lock.h" 00024 #include "heap.h" 00025 #include "dbgterm.h" 00026 #include <common/common.h> 00027 #include <core/system.h> 00028 00052 u8 __lockCount = 0; 00063 __PLOCK_LIST __lockList = __NULL; 00081 __PLOCK __lockCreate(__VOID) 00082 { 00083 __PLOCK lock; 00084 __PLOCK_LIST list; 00085 __PLOCK_LIST list_root = __NULL; 00086 00087 __systemStop(); 00088 00089 /* Alloc and assign */ 00090 lock = __heapAlloc(sizeof(__LOCK)); 00091 if (!lock) 00092 { 00093 __systemStart(); 00094 return __NULL; 00095 } 00096 00097 lock->state = __LOCK_RELEASED; 00098 lock->type = __LOCK_TYPE_NORMAL; 00099 lock->owner = __NULL; 00100 lock->parent = __threadGetCurrent(); 00101 00102 /* Add to list */ 00103 list = __lockList; 00104 while(list != __NULL) 00105 { 00106 /* Remember last list */ 00107 list_root = list; 00108 list = list->next; 00109 } 00110 00111 list = __heapAllocZero(sizeof(__LOCK_LIST)); 00112 if (!list) 00113 { 00114 __heapFree(lock); 00115 __systemStart(); 00116 return __NULL; 00117 } 00118 00119 list->lock = lock; 00120 list->next = __NULL; 00121 00122 if (__lockList == __NULL) 00123 { 00124 __lockList = list; 00125 } else 00126 { 00127 list_root->next = list; 00128 } 00129 00130 __lockCount++; 00131 00132 __systemStart(); 00133 00134 return lock; 00135 } 00136 00147 __STATIC u8 __lockWait(__PLOCK lock, u32 wait) 00148 { 00149 u8 ret = __EVRET_TIMEOUT; 00150 00151 __eventReset(&lock->event); 00152 ret = __eventWait(&lock->event, wait); 00153 return ret; 00154 } 00155 00168 __BOOL __lockOwn(__PLOCK lock, u32 wait) 00169 { 00170 u32 time = 0; 00171 00172 __systemStop(); 00173 00174 /* Check if __lockOwn is not being called from an already 00175 * "owner" thread. 00176 */ 00177 if (lock->state == __LOCK_LOCKED && lock->owner == __threadGetCurrent()) { 00178 __systemStart(); 00179 return __TRUE; 00180 } 00181 00182 /* Here, in the case of a failed lock wait, we will 00183 * reuse the time left to wait again. 00184 * For example can happen that: 00185 * 00186 * 1- Thread1 and Thread2 has the same priority, so they won't preempt 00187 * each other. 00188 * 2- Thread1 owns a lock, and goes suspended. 00189 * 3- Thread2 wants to own the locked lock, but the lock 00190 * is busy, so it will enter __lockWait(). 00191 * 4- Thread1 wakes up, and releases the lock (__lockRelease()), 00192 * setting Thread2 ready to run. But soon after releasing, Thread1 owns the lock again, 00193 * and goes suspended. 00194 * 5- Thread2, waked up and ready to run by the __lockRelease() call (from Thread1) 00195 * tries to own the lock, but it founds it locked. 00196 * 00197 */ 00198 time = wait; 00199 while (lock->state != __LOCK_RELEASED && time) 00200 { 00201 __lockWait(lock, time); 00202 time = __threadGetCurrent()->th_wait; 00203 } 00204 00205 if (lock->state != __LOCK_RELEASED) 00206 { 00207 __systemStart(); 00208 return __FALSE; 00209 } 00210 00211 lock->state = __LOCK_LOCKED; 00212 lock->owner = __threadGetCurrent(); 00213 00214 __systemStart(); 00215 return __TRUE; 00216 } 00217 00226 __BOOL __lockRelease(__PLOCK lock) 00227 { 00228 if (!lock) return __FALSE; 00229 00230 __systemStop(); 00231 lock->state = __LOCK_RELEASED; 00232 lock->owner = __NULL; 00233 00234 /* wake threads waiting for this lock */ 00235 __eventSetOne(&lock->event); 00236 __systemStart(); 00237 00238 return __TRUE; 00239 } 00240 00249 __VOID __lockDestroy(__PLOCK lock) 00250 { 00251 __PLOCK_LIST list = __NULL; 00252 __PLOCK_LIST root_list = __NULL; 00253 00254 list = __lockList; 00255 root_list = list; 00256 00257 __systemStop(); 00258 while (list) 00259 { 00260 if (list->lock == lock) 00261 { 00262 __heapFree(lock); 00263 00264 if (__lockList == list) 00265 { 00266 (list->next != __NULL) ? (__lockList = list->next) : (__lockList = __NULL); 00267 } else 00268 { 00269 (list->next != __NULL) ? (root_list->next = list->next) : (root_list->next = __NULL); 00270 } 00271 00272 __heapFree(list); 00273 00274 __lockCount--; 00275 00276 __systemStart(); 00277 return; 00278 } 00279 00280 root_list = list; 00281 list = list->next; 00282 } 00283 __systemStart(); 00284 return; 00285 } 00286 00292 u32 __lockGetCount(__VOID) 00293 { 00294 return __lockCount; 00295 } 00296 00302 __PLOCK_LIST __lockGetList(__VOID) 00303 { 00304 return __lockList; 00305 } 00306