SimpleOS

LXR

Navigation



Site hébergé par : enix

The LXR Cross Referencer for SOS

source navigation ]
diff markup ]
identifier search ]
general search ]
 
 
Article:1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 6.5 ] [ 7 ] [ 7.5 ] [ 8 ] [ 9 ] [ 9.5 ]

001 /* Copyright (C) 2004 David Decotigny
002 
003    This program is free software; you can redistribute it and/or
004    modify it under the terms of the GNU General Public License
005    as published by the Free Software Foundation; either version 2
006    of the License, or (at your option) any later version.
007    
008    This program is distributed in the hope that it will be useful,
009    but WITHOUT ANY WARRANTY; without even the implied warranty of
010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
011    GNU General Public License for more details.
012    
013    You should have received a copy of the GNU General Public License
014    along with this program; if not, write to the Free Software
015    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016    USA. 
017 */
018 
019 
020 #include <hwcore/irq.h>
021 
022 
023 #include "ksynch.h"
024 
025 
026 sos_ret_t sos_ksema_init(struct sos_ksema *sema, const char *name,
027                          int initial_value,
028                          sos_kwaitq_ordering_t ordering)
029 {
030   sema->value = initial_value;
031   return sos_kwaitq_init(& sema->kwaitq, name, ordering);
032 }
033 
034 
035 sos_ret_t sos_ksema_dispose(struct sos_ksema *sema)
036 {
037   return sos_kwaitq_dispose(& sema->kwaitq);
038 }
039 
040 
041 sos_ret_t sos_ksema_down(struct sos_ksema *sema,
042                          struct sos_time *timeout)
043 {
044   sos_ui32_t flags;
045   sos_ret_t retval;
046 
047   sos_disable_IRQs(flags);
048   retval = SOS_OK;
049 
050   sema->value --;
051   if (sema->value < 0)
052     {
053       /* Wait for somebody to wake us */
054       retval = sos_kwaitq_wait(& sema->kwaitq, timeout);
055 
056       /* Something wrong happened (timeout, external wakeup, ...) ? */
057       if (SOS_OK != retval)
058         {
059           /* Yes: pretend we did not ask for the semaphore */
060           sema->value ++;
061         }
062     }
063 
064   sos_restore_IRQs(flags);
065   return retval;
066 }
067 
068 
069 sos_ret_t sos_ksema_trydown(struct sos_ksema *sema)
070 {
071   sos_ui32_t flags;
072   sos_ret_t retval;
073 
074   sos_disable_IRQs(flags);
075 
076   /* Can we take the semaphore without blocking ? */
077   if (sema->value >= 1)
078     {
079       /* Yes: we take it now */
080       sema->value --;      
081       retval = SOS_OK;
082     }
083   else
084     {
085       /* No: we signal it */
086       retval = -SOS_EBUSY;
087     }
088 
089   sos_restore_IRQs(flags);
090   return retval;
091 }
092 
093 
094 sos_ret_t sos_ksema_up(struct sos_ksema *sema)
095 {
096   sos_ui32_t flags;
097   sos_ret_t retval;
098 
099   sos_disable_IRQs(flags);
100 
101   sema->value ++;
102   retval = sos_kwaitq_wakeup(& sema->kwaitq, 1, SOS_OK);
103 
104   sos_restore_IRQs(flags);
105   return retval;
106 }
107 
108 
109 sos_ret_t sos_kmutex_init(struct sos_kmutex *mutex, const char *name,
110                           sos_kwaitq_ordering_t ordering)
111 {
112   mutex->owner = NULL;
113   return sos_kwaitq_init(& mutex->kwaitq, name, ordering);
114 }
115 
116 
117 sos_ret_t sos_kmutex_dispose(struct sos_kmutex *mutex)
118 {
119   return sos_kwaitq_dispose(& mutex->kwaitq);
120 }
121 
122 
123 /*
124  * Implementation based on ownership transfer (ie no while()
125  * loop). The only assumption is that the thread awoken by
126  * kmutex_unlock is not suppressed before effectively waking up: in
127  * that case the mutex will be forever locked AND unlockable (by
128  * nobody other than the owner, but this is not natural since this
129  * owner already issued an unlock()...). The same problem happens with
130  * the semaphores, but in a less obvious manner.
131  */
132 sos_ret_t sos_kmutex_lock(struct sos_kmutex *mutex,
133                           struct sos_time *timeout)
134 {
135   __label__ exit_kmutex_lock;
136   sos_ui32_t flags;
137   sos_ret_t retval;
138 
139   sos_disable_IRQs(flags);
140   retval = SOS_OK;
141 
142   /* Mutex already owned ? */
143   if (NULL != mutex->owner)
144     {
145       /* Owned by us or by someone else ? */
146       if (sos_thread_get_current() == mutex->owner)
147         {
148           /* Owned by us: do nothing */
149           retval = -SOS_EBUSY;
150           goto exit_kmutex_lock;
151         }
152 
153       /* Wait for somebody to wake us */
154       retval = sos_kwaitq_wait(& mutex->kwaitq, timeout);
155 
156       /* Something wrong happened ? */
157       if (SOS_OK != retval)
158         {
159           goto exit_kmutex_lock;
160         }
161     }
162 
163   /* Ok, the mutex is available to us: take it */
164   mutex->owner = sos_thread_get_current();
165 
166  exit_kmutex_lock:
167   sos_restore_IRQs(flags);
168   return retval;
169 }
170 
171 
172 sos_ret_t sos_kmutex_trylock(struct sos_kmutex *mutex)
173 {
174   sos_ui32_t flags;
175   sos_ret_t retval;
176 
177   sos_disable_IRQs(flags);
178 
179   /* Mutex available to us ? */
180   if (NULL == mutex->owner)
181     {
182       /* Great ! Take it now */
183       mutex->owner = sos_thread_get_current();
184 
185       retval = SOS_OK;
186     }
187   else
188     {
189       /* No: signal it */
190       retval = -SOS_EBUSY;
191     }
192 
193   sos_restore_IRQs(flags);
194   return retval;
195 }
196 
197 
198 sos_ret_t sos_kmutex_unlock(struct sos_kmutex *mutex)
199 {
200   sos_ui32_t flags;
201   sos_ret_t  retval;
202 
203   sos_disable_IRQs(flags);
204 
205   if (sos_thread_get_current() != mutex->owner)
206     retval = -SOS_EPERM;
207 
208   else if (sos_kwaitq_is_empty(& mutex->kwaitq))
209     {
210       /*
211        * There is NOT ANY thread waiting => we really mark the mutex
212        * as FREE
213        */
214       mutex->owner = NULL;
215       retval = SOS_OK;
216     }
217   else
218     {
219       /*
220        * There is at least 1 thread waiting => we DO NOT mark the
221        * mutex as free !
222        * Actually, we should have written:
223        *   mutex->owner = thread_that_is_woken_up;
224        * But the real Id of the next thread owning the mutex is not
225        * that important. What is important here is that mutex->owner
226        * IS NOT NULL. Otherwise there will be a possibility for the
227        * thread woken up here to have the mutex stolen by a thread
228        * locking the mutex in the meantime.
229        */
230       retval = sos_kwaitq_wakeup(& mutex->kwaitq, 1, SOS_OK);
231     } 
232  
233   sos_restore_IRQs(flags);
234   return retval;
235 }

source navigation ] diff markup ] identifier search ] general search ]