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