1 /*****************************************************************************/
3 * \file input/lib/src/emul_wait
4 * \brief L4INPUT: Linux Wait queue emulation
7 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de>
9 * I've no idea if this is really needed.
12 * (c) 2005-2009 Technische Universität Dresden
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU General Public License 2.
15 * Please see the COPYING-GPL-2 file for details.
19 #include <l4/sys/ipc.h>
20 #include <l4/util/util.h>
21 #include <l4/util/l4_macros.h>
22 #include <linux/wait.h>
23 #include <linux/jiffies.h>
26 #include <pthread-l4.h>
28 l4_cap_idx_t wait_thread;
30 //#define dbg(format...) printf(format)
31 #define dbg(format...)
33 /** Enqueue entry into list. */
35 enqueue_entry(wait_queue_head_t *wqh, wait_queue_entry_t *e)
41 wait_queue_entry_t *w;
42 for (w=wqh->first; w->next; w=w->next)
48 /** Enqueue list into main list. */
50 enqueue_head(wait_queue_head_t **wqm, wait_queue_head_t *h)
56 wait_queue_head_t *w = *wqm;
71 /** Dequeue list from main list. */
73 dequeue_head(wait_queue_head_t **wqm, wait_queue_head_t *h)
75 for (; *wqm; *wqm=(*wqm)->next)
85 /** Wakeup all threads enqueued in list. */
87 wakeup(wait_queue_head_t *h)
89 wait_queue_entry_t *e;
95 dbg(" wakeup entry %p\n", e);
96 dbg(" ("l4util_idfmt", next=%p)\n",
97 l4util_idstr(e->tid), e->next);
101 l4_ipc(tid, l4_utcb(), L4_SYSF_SEND, pthread_getl4cap(pthread_self()),
102 l4_msgtag(0, 0, 0, 0), &dummy, L4_IPC_NEVER);
107 /** The waiter thread. */
109 __wait_thread(void *ignore)
112 l4_umword_t dw1, dw2;
115 l4_timeout_t to = l4_timeout(L4_IPC_TIMEOUT_NEVER,
116 l4util_micros2l4to(10000));
118 wait_queue_head_t *main_queue = 0;
120 //l4thread_started(NULL);
124 r = l4_ipc_wait(l4_utcb(), &src, main_queue ? to : L4_IPC_NEVER);
125 dw1 = l4_utcb_mr()->mr[0];
126 dw2 = l4_utcb_mr()->mr[1];
128 error = l4_ipc_error(r, l4_utcb());
135 /* go sleep, append at wait queue */
136 wait_queue_head_t *h = (wait_queue_head_t*)dw1;
137 wait_queue_entry_t *e = (wait_queue_entry_t*)dw2;
139 dbg("enqueue "l4util_idfmt" into queue %p entry %p\n", l4util_idstr(src), (void*)dw1, (void*)dw2);
144 /* append entry to wait queue */
146 /* append wait queue to main queue if necessary */
147 enqueue_head(&main_queue, h);
150 for (e=h->first; e; e=e->next)
157 wait_queue_head_t *h = ((wait_queue_head_t*)dw2);
158 dbg("wakeup queue %p\n", (void*)dw2);
159 /* wakeup waiting threads of wait queue */
161 /* dequeue wait queue from main queue */
162 dequeue_head(&main_queue, h);
163 dbg(" main=%p\n", (void*)main_queue);
164 l4_ipc(src, l4_utcb(), L4_SYSF_SEND,
165 pthread_getl4cap(pthread_self()),
166 l4_msgtag(0, 0, 0, 0), &dummy, L4_IPC_NEVER);
169 else if (error == L4_IPC_RETIMEOUT)
171 /* timeout, wakeup all queues */
172 wait_queue_head_t *h;
173 dbg("wakup all queues\n");
174 for (h=main_queue; h; h=h->next)
176 dbg(" wakeup queue %p\n", h);
189 /** Called if a specific wait queue should be woken up. */
191 wake_up(wait_queue_head_t *wq)
195 l4_utcb_mr()->mr[0] = 0;
196 l4_utcb_mr()->mr[1] = (l4_umword_t)(wq);
197 l4_ipc(wait_thread, l4_utcb(), L4_SYSF_CALL,
198 pthread_getl4cap(pthread_self()),
199 l4_msgtag(0, 2, 0, 0),
200 &dummy, L4_IPC_NEVER);
203 /** Initialization. */
205 l4input_internal_wait_init(void)
209 struct sched_param sp;
211 pthread_attr_init(&a);
212 sp.sched_priority = 255;
213 pthread_attr_setschedpolicy(&a, SCHED_L4);
214 pthread_attr_setschedparam(&a, &sp);
215 pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED);
217 if (pthread_create(&t, &a, __wait_thread, NULL))
220 wait_thread = pthread_getl4cap(t);
222 pthread_attr_destroy(&a);