|
[ source navigation ] [ diff markup ] [ identifier search ] [ general search ] |
|||
|
001 /* Copyright (C) 2004 David Decotigny 001 /* Copyright (C) 2004 David Decotigny 002 002 003 This program is free software; you can redi 003 This program is free software; you can redistribute it and/or 004 modify it under the terms of the GNU Genera 004 modify it under the terms of the GNU General Public License 005 as published by the Free Software Foundatio 005 as published by the Free Software Foundation; either version 2 006 of the License, or (at your option) any lat 006 of the License, or (at your option) any later version. 007 007 008 This program is distributed in the hope tha 008 This program is distributed in the hope that it will be useful, 009 but WITHOUT ANY WARRANTY; without even the 009 but WITHOUT ANY WARRANTY; without even the implied warranty of 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 011 GNU General Public License for more details 011 GNU General Public License for more details. 012 012 013 You should have received a copy of the GNU 013 You should have received a copy of the GNU General Public License 014 along with this program; if not, write to t 014 along with this program; if not, write to the Free Software 015 Foundation, Inc., 59 Temple Place - Suite 3 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 016 USA. 016 USA. 017 */ 017 */ 018 #ifndef _SOS_KWAITQ_H_ 018 #ifndef _SOS_KWAITQ_H_ 019 #define _SOS_KWAITQ_H_ 019 #define _SOS_KWAITQ_H_ 020 020 021 #include <sos/errno.h> 021 #include <sos/errno.h> 022 #include <sos/thread.h> 022 #include <sos/thread.h> 023 #include <sos/time.h> 023 #include <sos/time.h> 024 #include <sos/sched.h> << 025 024 026 025 027 /** 026 /** 028 * @kwaitq.h 027 * @kwaitq.h 029 * 028 * 030 * Low-level functions to manage queues of thr 029 * Low-level functions to manage queues of threads waiting for a 031 * resource. These functions are public. For h !! 030 * resource. These functions are public, except 032 * synchronization primitives such as mutex, s !! 031 * sos_kwaitq_change_priority() that is a callback for the thread 033 * ... prefer looking at the corresponding lib !! 032 * subsystem. However, for higher-level synchronization primitives >> 033 * such as mutex, semaphores, conditions, ... prefer to look at the >> 034 * corresponding libraries. 034 */ 035 */ 035 036 036 037 037 /** 038 /** 038 * Define this if you want to know the names o 039 * Define this if you want to know the names of the kwaitq 039 */ 040 */ 040 // #define SOS_KWQ_DEBUG 041 // #define SOS_KWQ_DEBUG 041 042 042 043 043 /* Forward declaration */ 044 /* Forward declaration */ 044 struct sos_kwaitq_entry; 045 struct sos_kwaitq_entry; 045 046 046 047 047 /** 048 /** 048 * Definition of a waitqueue. In a kwaitq, the !! 049 * The threads in the kwaitqs can be ordered in FIFO or in decreasing 049 * FIFO order. !! 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). 050 */ 072 */ 051 struct sos_kwaitq 073 struct sos_kwaitq 052 { 074 { 053 #ifdef SOS_KWQ_DEBUG 075 #ifdef SOS_KWQ_DEBUG 054 # define SOS_KWQ_DEBUG_MAX_NAMELEN 32 076 # define SOS_KWQ_DEBUG_MAX_NAMELEN 32 055 char name[SOS_KWQ_DEBUG_MAX_NAMELEN]; 077 char name[SOS_KWQ_DEBUG_MAX_NAMELEN]; 056 #endif 078 #endif >> 079 sos_kwaitq_ordering_t ordering; 057 struct sos_kwaitq_entry *waiting_list; 080 struct sos_kwaitq_entry *waiting_list; 058 }; 081 }; 059 082 060 083 061 /** 084 /** 062 * Definition of an entry for a thread waiting 085 * Definition of an entry for a thread waiting in the waitqueue 063 */ 086 */ 064 struct sos_kwaitq_entry 087 struct sos_kwaitq_entry 065 { 088 { 066 /** The thread associted with this entry */ 089 /** The thread associted with this entry */ 067 struct sos_thread *thread; 090 struct sos_thread *thread; 068 091 069 /** The kwaitqueue this entry belongs to */ 092 /** The kwaitqueue this entry belongs to */ 070 struct sos_kwaitq *kwaitq; 093 struct sos_kwaitq *kwaitq; 071 094 072 /** TRUE when somebody woke up this entry */ 095 /** TRUE when somebody woke up this entry */ 073 sos_bool_t wakeup_triggered; 096 sos_bool_t wakeup_triggered; 074 097 075 /** The status of wakeup for this entry. @se 098 /** The status of wakeup for this entry. @see wakeup_status argument 076 of sos_kwaitq_wakeup() */ 099 of sos_kwaitq_wakeup() */ 077 sos_ret_t wakeup_status; 100 sos_ret_t wakeup_status; 078 101 079 /** Other entries in this kwaitqueue */ 102 /** Other entries in this kwaitqueue */ 080 struct sos_kwaitq_entry *prev_entry_in_kwait 103 struct sos_kwaitq_entry *prev_entry_in_kwaitq, *next_entry_in_kwaitq; 081 104 082 /** Other entries for the thread */ 105 /** Other entries for the thread */ 083 struct sos_kwaitq_entry *prev_entry_for_thre 106 struct sos_kwaitq_entry *prev_entry_for_thread, *next_entry_for_thread; 084 }; 107 }; 085 108 086 109 087 /** 110 /** 088 * Initialize an empty waitqueue. 111 * Initialize an empty waitqueue. 089 * 112 * 090 * @param name Used only if SOS_KWQ_DEBUG is d 113 * @param name Used only if SOS_KWQ_DEBUG is defined (safe [deep 091 * copied]) 114 * copied]) 092 */ 115 */ 093 sos_ret_t sos_kwaitq_init(struct sos_kwaitq *k 116 sos_ret_t sos_kwaitq_init(struct sos_kwaitq *kwq, 094 const char *name); !! 117 const char *name, >> 118 sos_kwaitq_ordering_t ordering); 095 119 096 120 097 /** 121 /** 098 * Release a waitqueue, making sure that no th 122 * Release a waitqueue, making sure that no thread is in it. 099 * 123 * 100 * @return -SOS_EBUSY in case a thread is stil 124 * @return -SOS_EBUSY in case a thread is still in the waitqueue. 101 */ 125 */ 102 sos_ret_t sos_kwaitq_dispose(struct sos_kwaitq 126 sos_ret_t sos_kwaitq_dispose(struct sos_kwaitq *kwq); 103 127 104 128 105 /** 129 /** 106 * Return whether there are no threads in the 130 * Return whether there are no threads in the waitq 107 */ 131 */ 108 sos_bool_t sos_kwaitq_is_empty(const struct so 132 sos_bool_t sos_kwaitq_is_empty(const struct sos_kwaitq *kwq); 109 133 110 134 111 /** 135 /** 112 * Initialize a waitqueue entry. Mainly consis 136 * Initialize a waitqueue entry. Mainly consists in updating the 113 * "thread" field of the entry (set to current 137 * "thread" field of the entry (set to current running thread), and 114 * initializing the remaining of the entry as 138 * initializing the remaining of the entry as to indicate it does not 115 * belong to any waitq. 139 * belong to any waitq. 116 */ 140 */ 117 sos_ret_t sos_kwaitq_init_entry(struct sos_kwa 141 sos_ret_t sos_kwaitq_init_entry(struct sos_kwaitq_entry *kwq_entry); 118 142 119 143 120 /** 144 /** 121 * Add an entry (previously initialized with s 145 * Add an entry (previously initialized with sos_kwaitq_init_entry()) 122 * in the given waitqueue. 146 * in the given waitqueue. 123 * 147 * 124 * @note: No state change/context switch can o 148 * @note: No state change/context switch can occur here ! Among other 125 * things: the current executing thread is not 149 * things: the current executing thread is not preempted. 126 */ 150 */ 127 sos_ret_t sos_kwaitq_add_entry(struct sos_kwai 151 sos_ret_t sos_kwaitq_add_entry(struct sos_kwaitq *kwq, 128 struct sos_kwai 152 struct sos_kwaitq_entry *kwq_entry); 129 153 130 154 131 /** 155 /** 132 * Remove the given kwaitq_entry from the kwai 156 * Remove the given kwaitq_entry from the kwaitq. 133 * 157 * 134 * @note: No state change/context switch can o 158 * @note: No state change/context switch can occur here ! Among other 135 * things: the thread associated with the entr 159 * things: the thread associated with the entry is not necessarilly 136 * the same as the one currently running, and 160 * the same as the one currently running, and does not preempt the 137 * current running thread if they are differen 161 * current running thread if they are different. 138 */ 162 */ 139 sos_ret_t sos_kwaitq_remove_entry(struct sos_k 163 sos_ret_t sos_kwaitq_remove_entry(struct sos_kwaitq *kwq, 140 struct sos_k 164 struct sos_kwaitq_entry *kwq_entry); 141 165 142 166 143 /** 167 /** 144 * Helper function to make the current running 168 * Helper function to make the current running thread block in the 145 * given kwaitq, waiting to be woken up by som 169 * given kwaitq, waiting to be woken up by somedy else or by the given 146 * timeout. It calls the sos_kwaitq_add_entry( 170 * timeout. It calls the sos_kwaitq_add_entry() and 147 * sos_kwaitq_remove_entry(). 171 * sos_kwaitq_remove_entry(). 148 * 172 * 149 * @param timeout The desired timeout (can be 173 * @param timeout The desired timeout (can be NULL => wait for 150 * ever). It is updated by the function to ref 174 * ever). It is updated by the function to reflect the remaining 151 * timeout in case the thread has been woken-u 175 * timeout in case the thread has been woken-up prior to its 152 * expiration. 176 * expiration. 153 * 177 * 154 * @return -SOS_EINTR when the thread is resum 178 * @return -SOS_EINTR when the thread is resumed while it has not be 155 * explicitely woken up by someone calling sos 179 * explicitely woken up by someone calling sos_kwaitq_wakeup() upon 156 * the same waitqueue... This can only happen 180 * the same waitqueue... This can only happen 1/ if the timeout 157 * expired, or 2/ if the current thread is als 181 * expired, or 2/ if the current thread is also in another kwaitq 158 * different to "kwq". Otherwise return the va 182 * different to "kwq". Otherwise return the value set by 159 * sos_kwaitq_wakeup(). The timeout remaining 183 * sos_kwaitq_wakeup(). The timeout remaining is updated in timeout. 160 * 184 * 161 * @note This is a BLOCKING FUNCTION 185 * @note This is a BLOCKING FUNCTION 162 */ 186 */ 163 sos_ret_t sos_kwaitq_wait(struct sos_kwaitq *k 187 sos_ret_t sos_kwaitq_wait(struct sos_kwaitq *kwq, 164 struct sos_time *tim 188 struct sos_time *timeout); 165 189 166 190 167 /** 191 /** 168 * Wake up as much as nb_thread threads (SOS_K 192 * Wake up as much as nb_thread threads (SOS_KWQ_WAKEUP_ALL to wake 169 * up all threads) in the kwaitq kwq, in FIFO !! 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). 170 * 196 * 171 * @param wakeup_status The value returned by 197 * @param wakeup_status The value returned by sos_kwaitq_wait() when 172 * the thread will effectively woken up due to 198 * the thread will effectively woken up due to this wakeup. 173 */ 199 */ 174 sos_ret_t sos_kwaitq_wakeup(struct sos_kwaitq 200 sos_ret_t sos_kwaitq_wakeup(struct sos_kwaitq *kwq, 175 unsigned int nb_th 201 unsigned int nb_threads, 176 sos_ret_t wakeup_s 202 sos_ret_t wakeup_status); 177 #define SOS_KWQ_WAKEUP_ALL (~((unsigned int)0) 203 #define SOS_KWQ_WAKEUP_ALL (~((unsigned int)0)) 178 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); 179 215 180 #endif /* _SOS_KWAITQ_H_ */ 216 #endif /* _SOS_KWAITQ_H_ */
[ source navigation ] | [ diff markup ] | [ identifier search ] | [ general search ] |