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 #include <sos/klibc.h>
020 #include <sos/list.h>
021 #include <sos/assert.h>
022 #include <hwcore/irq.h>
023 
024 #include "kwaitq.h"
025 
026 
027 sos_ret_t sos_kwaitq_init(struct sos_kwaitq *kwq,
028                           const char *name)
029 {
030   memset(kwq, 0x0, sizeof(struct sos_kwaitq));
031 
032 #ifdef SOS_KWQ_DEBUG
033   if (! name)
034     name = "<unknown>";
035   strzcpy(kwq->name, name, SOS_KWQ_DEBUG_MAX_NAMELEN);
036 #endif
037   list_init_named(kwq->waiting_list,
038                   prev_entry_in_kwaitq, next_entry_in_kwaitq);
039 
040   return SOS_OK;
041 }
042 
043 
044 sos_ret_t sos_kwaitq_dispose(struct sos_kwaitq *kwq)
045 {
046   sos_ui32_t flags;
047   sos_ret_t retval;
048 
049   sos_disable_IRQs(flags);
050   if (list_is_empty_named(kwq->waiting_list,
051                           prev_entry_in_kwaitq, next_entry_in_kwaitq))
052     retval = SOS_OK;
053   else
054     retval = -SOS_EBUSY;
055 
056   sos_restore_IRQs(flags);
057   return retval;
058 }
059 
060 
061 sos_bool_t sos_kwaitq_is_empty(const struct sos_kwaitq *kwq)
062 {
063   sos_ui32_t flags;
064   sos_ret_t retval;
065 
066   sos_disable_IRQs(flags);
067   retval = list_is_empty_named(kwq->waiting_list,
068                                prev_entry_in_kwaitq, next_entry_in_kwaitq);
069 
070   sos_restore_IRQs(flags);
071   return retval;  
072 }
073 
074 
075 sos_ret_t sos_kwaitq_init_entry(struct sos_kwaitq_entry *kwq_entry)
076 {
077   memset(kwq_entry, 0x0, sizeof(struct sos_kwaitq_entry));
078   kwq_entry->thread = sos_thread_get_current();
079   return SOS_OK;
080 }
081 
082 
083 /** Internal helper function equivalent to sos_kwaitq_add_entry(), but
084     without interrupt protection scheme, and explicit priority
085     ordering */
086 inline static sos_ret_t _kwaitq_add_entry(struct sos_kwaitq *kwq,
087                                           struct sos_kwaitq_entry *kwq_entry)
088 {
089   /* This entry is already added in the kwaitq ! */
090   SOS_ASSERT_FATAL(NULL == kwq_entry->kwaitq);
091 
092   /* sos_kwaitq_init_entry() has not been called ?! */
093   SOS_ASSERT_FATAL(NULL != kwq_entry->thread);
094 
095   /* (Re-)Initialize wakeup status of the entry */
096   kwq_entry->wakeup_triggered = FALSE;
097   kwq_entry->wakeup_status    = SOS_OK;
098 
099   /* Add the thread in the list */
100   list_add_tail_named(kwq->waiting_list, kwq_entry,
101                       prev_entry_in_kwaitq, next_entry_in_kwaitq);
102 
103   /* Update the list of waitqueues for the thread */
104   list_add_tail_named(kwq_entry->thread->kwaitq_list, kwq_entry,
105                       prev_entry_for_thread, next_entry_for_thread);
106 
107   kwq_entry->kwaitq = kwq;
108 
109   return SOS_OK;
110 }
111 
112 
113 sos_ret_t sos_kwaitq_add_entry(struct sos_kwaitq *kwq,
114                                struct sos_kwaitq_entry *kwq_entry)
115 {
116   sos_ui32_t flags;
117   sos_ret_t retval;
118 
119   sos_disable_IRQs(flags);
120   retval = _kwaitq_add_entry(kwq, kwq_entry);
121   sos_restore_IRQs(flags);
122 
123   return retval;
124 }
125 
126 
127 /** Internal helper function equivalent to sos_kwaitq_remove_entry(),
128     but without interrupt protection scheme */
129 inline static sos_ret_t
130 _kwaitq_remove_entry(struct sos_kwaitq *kwq,
131                      struct sos_kwaitq_entry *kwq_entry)
132 {
133   SOS_ASSERT_FATAL(kwq_entry->kwaitq == kwq);
134 
135   list_delete_named(kwq->waiting_list, kwq_entry,
136                     prev_entry_in_kwaitq, next_entry_in_kwaitq);
137 
138   list_delete_named(kwq_entry->thread->kwaitq_list, kwq_entry,
139                     prev_entry_for_thread, next_entry_for_thread);
140 
141   kwq_entry->kwaitq = NULL;
142   return SOS_OK;
143 }
144 
145 
146 sos_ret_t sos_kwaitq_remove_entry(struct sos_kwaitq *kwq,
147                                   struct sos_kwaitq_entry *kwq_entry)
148 {
149   sos_ui32_t flags;
150   sos_ret_t retval;
151 
152   sos_disable_IRQs(flags);
153   retval = _kwaitq_remove_entry(kwq, kwq_entry);
154   sos_restore_IRQs(flags);
155 
156   return retval;
157 }
158 
159 
160 sos_ret_t sos_kwaitq_wait(struct sos_kwaitq *kwq,
161                           struct sos_time *timeout)
162 {
163   sos_ui32_t flags;
164   sos_ret_t retval;
165   struct sos_kwaitq_entry kwq_entry;
166 
167   sos_kwaitq_init_entry(& kwq_entry);
168 
169   sos_disable_IRQs(flags);
170 
171   retval = _kwaitq_add_entry(kwq, & kwq_entry);
172 
173   /* Wait for wakeup or timeout */
174   sos_thread_sleep(timeout);
175   /* Woken up ! */
176 
177   /* Sleep delay elapsed ? */
178   if (! kwq_entry.wakeup_triggered)
179     {
180       /* Yes (timeout occured, or wakeup on another waitqueue): remove
181          the waitq entry by ourselves */
182       _kwaitq_remove_entry(kwq, & kwq_entry);
183       retval = -SOS_EINTR;
184     }
185   else
186     {
187       retval = kwq_entry.wakeup_status;
188     }
189   
190   sos_restore_IRQs(flags);
191 
192   /* We were correctly awoken: position return status */
193   return retval;
194 }
195 
196 
197 sos_ret_t sos_kwaitq_wakeup(struct sos_kwaitq *kwq,
198                             unsigned int nb_threads,
199                             sos_ret_t wakeup_status)
200 {
201   sos_ui32_t flags;
202 
203   sos_disable_IRQs(flags);
204 
205   /* Wake up as much threads waiting in waitqueue as possible (up to
206      nb_threads), scanning the list in FIFO order */
207   while (! list_is_empty_named(kwq->waiting_list,
208                                prev_entry_in_kwaitq, next_entry_in_kwaitq))
209     {
210       struct sos_kwaitq_entry *kwq_entry
211         = list_get_head_named(kwq->waiting_list,
212                               prev_entry_in_kwaitq, next_entry_in_kwaitq);
213 
214       /* Enough threads woken up ? */
215       if (nb_threads <= 0)
216         break;
217 
218       /*
219        * Ok: wake up the thread for this entry
220        */
221 
222       /* Thread already woken up ? */
223       if (SOS_THR_RUNNING == sos_thread_get_state(kwq_entry->thread))
224         {
225           /* Yes => Do nothing because WE are that woken-up thread. In
226              particular: don't call set_ready() here because this
227              would result in an inconsistent configuration (currently
228              running thread marked as "waiting for CPU"...). */
229           continue;
230         }
231       else
232         {
233           /* No => wake it up now. */
234           sos_sched_set_ready(kwq_entry->thread);
235         }
236 
237       /* Remove this waitq entry */
238       _kwaitq_remove_entry(kwq, kwq_entry);
239       kwq_entry->wakeup_triggered = TRUE;
240       kwq_entry->wakeup_status    = wakeup_status;
241 
242       /* Next iteration... */
243       nb_threads --;
244     }
245 
246   sos_restore_IRQs(flags);
247 
248   return SOS_OK;
249 }

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