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

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