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 #ifndef _SOS_KWAITQ_H_
019 #define _SOS_KWAITQ_H_
020 
021 #include <sos/errno.h>
022 #include <sos/thread.h>
023 #include <sos/time.h>
024 
025 
026 /**
027  * @kwaitq.h
028  *
029  * Low-level functions to manage queues of threads waiting for a
030  * resource. These functions are public, except
031  * sos_kwaitq_change_priority() that is a callback for the thread
032  * subsystem. However, for higher-level synchronization primitives
033  * such as mutex, semaphores, conditions, ... prefer to look at the
034  * corresponding libraries.
035  */
036 
037 
038 /**
039  * Define this if you want to know the names of the kwaitq
040  */
041 // #define SOS_KWQ_DEBUG
042 
043 
044 /* Forward declaration */
045 struct sos_kwaitq_entry;
046 
047 
048 /**
049  * The threads in the kwaitqs can be ordered in FIFO or in decreasing
050  * priority order.
051  */
052 typedef enum { SOS_KWQ_ORDER_FIFO, SOS_KWQ_ORDER_PRIO } sos_kwaitq_ordering_t;
053 
054 
055 #include <sos/sched.h>
056 
057 
058 /**
059  * Definition of a waitqueue. In a kwaitq, the threads can be ordererd
060  * either in FIFO order (SOS_KWQ_ORDER_FIFO) or in decreasing priority
061  * order (SOS_KWQ_ORDER_PRIO ; with FIFO ordering for same-prio
062  * threads).
063  * 
064  * A more efficient method to store the threads ordered by their
065  * priority would have been to use 1 list for each priority level. But
066  * we have to be careful to the size of a kwaitq structure here:
067  * potentially there are thousands of kwaitq in a running system
068  * (basically: 1 per opened file !). The algorithm we use to order the
069  * threads in the kwaitq in this case is highly under-optimal (naive
070  * linear insertion): as an exercise, one can implement a more
071  * efficient algorithm (think of a heap).
072  */
073 struct sos_kwaitq
074 {
075 #ifdef SOS_KWQ_DEBUG
076 # define SOS_KWQ_DEBUG_MAX_NAMELEN 32
077   char name[SOS_KWQ_DEBUG_MAX_NAMELEN];
078 #endif
079   sos_kwaitq_ordering_t ordering;
080   struct sos_kwaitq_entry *waiting_list;
081 };
082 
083 
084 /**
085  * Definition of an entry for a thread waiting in the waitqueue
086  */
087 struct sos_kwaitq_entry
088 {
089   /** The thread associted with this entry */
090   struct sos_thread *thread;
091 
092   /** The kwaitqueue this entry belongs to */
093   struct sos_kwaitq *kwaitq;
094 
095   /** TRUE when somebody woke up this entry */
096   sos_bool_t wakeup_triggered;
097 
098   /** The status of wakeup for this entry. @see wakeup_status argument
099       of sos_kwaitq_wakeup() */
100   sos_ret_t wakeup_status;
101 
102   /** Other entries in this kwaitqueue */
103   struct sos_kwaitq_entry *prev_entry_in_kwaitq, *next_entry_in_kwaitq;
104 
105   /** Other entries for the thread */
106   struct sos_kwaitq_entry *prev_entry_for_thread, *next_entry_for_thread;  
107 };
108 
109 
110 /**
111  * Initialize an empty waitqueue.
112  *
113  * @param name Used only if SOS_KWQ_DEBUG is defined (safe [deep
114  * copied])
115  */
116 sos_ret_t sos_kwaitq_init(struct sos_kwaitq *kwq,
117                           const char *name,
118                           sos_kwaitq_ordering_t ordering);
119 
120 
121 /**
122  * Release a waitqueue, making sure that no thread is in it.
123  *
124  * @return -SOS_EBUSY in case a thread is still in the waitqueue.
125  */
126 sos_ret_t sos_kwaitq_dispose(struct sos_kwaitq *kwq);
127 
128 
129 /**
130  * Return whether there are no threads in the waitq
131  */
132 sos_bool_t sos_kwaitq_is_empty(const struct sos_kwaitq *kwq);
133 
134 
135 /**
136  * Initialize a waitqueue entry. Mainly consists in updating the
137  * "thread" field of the entry (set to current running thread), and
138  * initializing the remaining of the entry as to indicate it does not
139  * belong to any waitq.
140  */
141 sos_ret_t sos_kwaitq_init_entry(struct sos_kwaitq_entry *kwq_entry);
142 
143 
144 /**
145  * Add an entry (previously initialized with sos_kwaitq_init_entry())
146  * in the given waitqueue.
147  *
148  * @note: No state change/context switch can occur here ! Among other
149  * things: the current executing thread is not preempted.
150  */
151 sos_ret_t sos_kwaitq_add_entry(struct sos_kwaitq *kwq,
152                                struct sos_kwaitq_entry *kwq_entry);
153 
154 
155 /**
156  * Remove the given kwaitq_entry from the kwaitq.
157  *
158  * @note: No state change/context switch can occur here ! Among other
159  * things: the thread associated with the entry is not necessarilly
160  * the same as the one currently running, and does not preempt the
161  * current running thread if they are different.
162  */
163 sos_ret_t sos_kwaitq_remove_entry(struct sos_kwaitq *kwq,
164                                   struct sos_kwaitq_entry *kwq_entry);
165 
166 
167 /**
168  * Helper function to make the current running thread block in the
169  * given kwaitq, waiting to be woken up by somedy else or by the given
170  * timeout. It calls the sos_kwaitq_add_entry() and
171  * sos_kwaitq_remove_entry().
172  *
173  * @param timeout The desired timeout (can be NULL => wait for
174  * ever). It is updated by the function to reflect the remaining
175  * timeout in case the thread has been woken-up prior to its
176  * expiration.
177  *
178  * @return -SOS_EINTR when the thread is resumed while it has not be
179  * explicitely woken up by someone calling sos_kwaitq_wakeup() upon
180  * the same waitqueue... This can only happen 1/ if the timeout
181  * expired, or 2/ if the current thread is also in another kwaitq
182  * different to "kwq". Otherwise return the value set by
183  * sos_kwaitq_wakeup(). The timeout remaining is updated in timeout.
184  *
185  * @note This is a BLOCKING FUNCTION
186  */
187 sos_ret_t sos_kwaitq_wait(struct sos_kwaitq *kwq,
188                           struct sos_time *timeout);
189 
190 
191 /**
192  * Wake up as much as nb_thread threads (SOS_KWQ_WAKEUP_ALL to wake
193  * up all threads) in the kwaitq kwq, in FIFO or decreasing priority
194  * order (depends on the ordering scheme selected at kwaitq
195  * initialization time).
196  *
197  * @param wakeup_status The value returned by sos_kwaitq_wait() when
198  * the thread will effectively woken up due to this wakeup.
199  */
200 sos_ret_t sos_kwaitq_wakeup(struct sos_kwaitq *kwq,
201                             unsigned int nb_threads,
202                             sos_ret_t wakeup_status);
203 #define SOS_KWQ_WAKEUP_ALL (~((unsigned int)0))
204 
205 
206 /**
207  * @note INTERNAL function (in particular: interrupts not disabled) !
208  *
209  * @note: The use of this function is RESERVED (to thread.c). Do not
210  * call it directly: use sos_thread_set_priority() for that !
211  */
212 sos_ret_t sos_kwaitq_change_priority(struct sos_kwaitq *kwq,
213                                      struct sos_kwaitq_entry *kwq_entry,
214                                      sos_sched_priority_t priority);
215 
216 #endif /* _SOS_KWAITQ_H_ */

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