Milos RTOS v0.3.4a
Real Time Operating System
lock.c
Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Defines