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