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 #include <sos/assert.h>
022 
023 
024 #include "ksynch.h"
025 
026 
027 sos_ret_t sos_ksema_init(struct sos_ksema *sema, const char *name,
028                          int initial_value,
029                          sos_kwaitq_ordering_t ordering)
030 {
031   sema->value = initial_value;
032   return sos_kwaitq_init(& sema->kwaitq, name, ordering);
033 }
034 
035 
036 sos_ret_t sos_ksema_dispose(struct sos_ksema *sema)
037 {
038   return sos_kwaitq_dispose(& sema->kwaitq);
039 }
040 
041 
042 sos_ret_t sos_ksema_down(struct sos_ksema *sema,
043                          struct sos_time *timeout)
044 {
045   sos_ui32_t flags;
046   sos_ret_t retval;
047 
048   sos_disable_IRQs(flags);
049   retval = SOS_OK;
050 
051   sema->value --;
052   if (sema->value < 0)
053     {
054       /* Wait for somebody to wake us */
055       retval = sos_kwaitq_wait(& sema->kwaitq, timeout);
056 
057       /* Something wrong happened (timeout, external wakeup, ...) ? */
058       if (SOS_OK != retval)
059         {
060           /* Yes: pretend we did not ask for the semaphore */
061           sema->value ++;
062         }
063     }
064 
065   sos_restore_IRQs(flags);
066   return retval;
067 }
068 
069 
070 sos_ret_t sos_ksema_trydown(struct sos_ksema *sema)
071 {
072   sos_ui32_t flags;
073   sos_ret_t retval;
074 
075   sos_disable_IRQs(flags);
076 
077   /* Can we take the semaphore without blocking ? */
078   if (sema->value >= 1)
079     {
080       /* Yes: we take it now */
081       sema->value --;      
082       retval = SOS_OK;
083     }
084   else
085     {
086       /* No: we signal it */
087       retval = -SOS_EBUSY;
088     }
089 
090   sos_restore_IRQs(flags);
091   return retval;
092 }
093 
094 
095 sos_ret_t sos_ksema_up(struct sos_ksema *sema)
096 {
097   sos_ui32_t flags;
098   sos_ret_t retval;
099 
100   sos_disable_IRQs(flags);
101 
102   sema->value ++;
103   retval = sos_kwaitq_wakeup(& sema->kwaitq, 1, SOS_OK);
104 
105   sos_restore_IRQs(flags);
106   return retval;
107 }
108 
109 
110 sos_ret_t sos_kmutex_init(struct sos_kmutex *mutex, const char *name,
111                           sos_kwaitq_ordering_t ordering)
112 {
113   mutex->owner = NULL;
114   return sos_kwaitq_init(& mutex->kwaitq, name, ordering);
115 }
116 
117 
118 sos_ret_t sos_kmutex_dispose(struct sos_kmutex *mutex)
119 {
120   return sos_kwaitq_dispose(& mutex->kwaitq);
121 }
122 
123 
124 /*
125  * Implementation based on ownership transfer (ie no while()
126  * loop). The only assumption is that the thread awoken by
127  * kmutex_unlock is not suppressed before effectively waking up: in
128  * that case the mutex will be forever locked AND unlockable (by
129  * nobody other than the owner, but this is not natural since this
130  * owner already issued an unlock()...). The same problem happens with
131  * the semaphores, but in a less obvious manner.
132  */
133 sos_ret_t sos_kmutex_lock(struct sos_kmutex *mutex,
134                           struct sos_time *timeout)
135 {
136   __label__ exit_kmutex_lock;
137   sos_ui32_t flags;
138   sos_ret_t retval;
139 
140   sos_disable_IRQs(flags);
141   retval = SOS_OK;
142 
143   /* Mutex already owned ? */
144   if (NULL != mutex->owner)
145     {
146       /* Owned by us or by someone else ? */
147       if (sos_thread_get_current() == mutex->owner)
148         {
149           /* Owned by us: do nothing */
150           retval = -SOS_EBUSY;
151           goto exit_kmutex_lock;
152         }
153 
154       /* Wait for somebody to wake us */
155       retval = sos_kwaitq_wait(& mutex->kwaitq, timeout);
156 
157       /* Something wrong happened ? */
158       if (SOS_OK != retval)
159         {
160           goto exit_kmutex_lock;
161         }
162     }
163 
164   /* Ok, the mutex is available to us: take it */
165   mutex->owner = sos_thread_get_current();
166 
167  exit_kmutex_lock:
168   sos_restore_IRQs(flags);
169   return retval;
170 }
171 
172 
173 sos_bool_t sos_kmutex_owned_by_me(struct sos_kmutex const* mutex)
174 {
175   sos_ui32_t flags;
176   sos_bool_t retval;
177 
178   sos_disable_IRQs(flags);
179   retval = (sos_thread_get_current() == mutex->owner);
180   sos_restore_IRQs(flags);
181 
182   return retval;
183 }
184 
185 
186 sos_ret_t sos_kmutex_trylock(struct sos_kmutex *mutex)
187 {
188   sos_ui32_t flags;
189   sos_ret_t retval;
190 
191   sos_disable_IRQs(flags);
192 
193   /* Mutex available to us ? */
194   if (NULL == mutex->owner)
195     {
196       /* Great ! Take it now */
197       mutex->owner = sos_thread_get_current();
198 
199       retval = SOS_OK;
200     }
201   else
202     {
203       /* No: signal it */
204       retval = -SOS_EBUSY;
205     }
206 
207   sos_restore_IRQs(flags);
208   return retval;
209 }
210 
211 
212 sos_ret_t sos_kmutex_unlock(struct sos_kmutex *mutex)
213 {
214   sos_ui32_t flags;
215   sos_ret_t  retval;
216 
217   sos_disable_IRQs(flags);
218 
219   if (sos_thread_get_current() != mutex->owner)
220     retval = -SOS_EPERM;
221 
222   else if (sos_kwaitq_is_empty(& mutex->kwaitq))
223     {
224       /*
225        * There is NOT ANY thread waiting => we really mark the mutex
226        * as FREE
227        */
228       mutex->owner = NULL;
229       retval = SOS_OK;
230     }
231   else
232     {
233       /*
234        * There is at least 1 thread waiting => we DO NOT mark the
235        * mutex as free !
236        * Actually, we should have written:
237        *   mutex->owner = thread_that_is_woken_up;
238        * But the real Id of the next thread owning the mutex is not
239        * that important. What is important here is that mutex->owner
240        * IS NOT NULL and does not correspond to any existing thread
241        * (address 0x43 is a good candidate because, in SOS, addresses
242        * below 4kB are never mapped in order to catch invalid
243        * pointers). Otherwise there will be a possibility for the
244        * thread woken up here to have the mutex stolen by a thread
245        * locking the mutex in the meantime.
246        */
247 #define MUTEX_STILL_LOCKED ((struct sos_thread*) 0x43)
248       mutex->owner = MUTEX_STILL_LOCKED;
249 
250       /* We wake up ONE thread ONLY */
251       retval = sos_kwaitq_wakeup(& mutex->kwaitq, 1, SOS_OK);
252     } 
253  
254   sos_restore_IRQs(flags);
255   return retval;
256 }

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