1262f27b2SOleksandr Tymoshenko /*-
2262f27b2SOleksandr Tymoshenko * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
3262f27b2SOleksandr Tymoshenko * All rights reserved.
4262f27b2SOleksandr Tymoshenko *
5262f27b2SOleksandr Tymoshenko * This software was developed by Max Khon under sponsorship from
6262f27b2SOleksandr Tymoshenko * the FreeBSD Foundation and Ethon Technologies GmbH.
7262f27b2SOleksandr Tymoshenko *
8262f27b2SOleksandr Tymoshenko * Redistribution and use in source and binary forms, with or without
9262f27b2SOleksandr Tymoshenko * modification, are permitted provided that the following conditions
10262f27b2SOleksandr Tymoshenko * are met:
11262f27b2SOleksandr Tymoshenko * 1. Redistributions of source code must retain the above copyright
12262f27b2SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer.
13262f27b2SOleksandr Tymoshenko * 2. Redistributions in binary form must reproduce the above copyright
14262f27b2SOleksandr Tymoshenko * notice, this list of conditions and the following disclaimer in the
15262f27b2SOleksandr Tymoshenko * documentation and/or other materials provided with the distribution.
16262f27b2SOleksandr Tymoshenko *
17262f27b2SOleksandr Tymoshenko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18262f27b2SOleksandr Tymoshenko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19262f27b2SOleksandr Tymoshenko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20262f27b2SOleksandr Tymoshenko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21262f27b2SOleksandr Tymoshenko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22262f27b2SOleksandr Tymoshenko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23262f27b2SOleksandr Tymoshenko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24262f27b2SOleksandr Tymoshenko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25262f27b2SOleksandr Tymoshenko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26262f27b2SOleksandr Tymoshenko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27262f27b2SOleksandr Tymoshenko * SUCH DAMAGE.
28262f27b2SOleksandr Tymoshenko *
29262f27b2SOleksandr Tymoshenko * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
30262f27b2SOleksandr Tymoshenko */
31262f27b2SOleksandr Tymoshenko
32262f27b2SOleksandr Tymoshenko #include <sys/types.h>
33262f27b2SOleksandr Tymoshenko #include <sys/limits.h>
34262f27b2SOleksandr Tymoshenko #include <sys/bus.h>
35262f27b2SOleksandr Tymoshenko #include <sys/callout.h>
36262f27b2SOleksandr Tymoshenko #include <sys/firmware.h>
37262f27b2SOleksandr Tymoshenko #include <sys/param.h>
38262f27b2SOleksandr Tymoshenko #include <sys/proc.h>
39262f27b2SOleksandr Tymoshenko #include <sys/syscallsubr.h>
40262f27b2SOleksandr Tymoshenko #include <sys/systm.h>
41262f27b2SOleksandr Tymoshenko #include <sys/taskqueue.h>
42262f27b2SOleksandr Tymoshenko
43262f27b2SOleksandr Tymoshenko #include <machine/stdarg.h>
44262f27b2SOleksandr Tymoshenko
45262f27b2SOleksandr Tymoshenko #include "mbox_if.h"
46262f27b2SOleksandr Tymoshenko
47262f27b2SOleksandr Tymoshenko #include <interface/compat/vchi_bsd.h>
48262f27b2SOleksandr Tymoshenko
49262f27b2SOleksandr Tymoshenko MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
50262f27b2SOleksandr Tymoshenko
51262f27b2SOleksandr Tymoshenko /*
52262f27b2SOleksandr Tymoshenko * Timer API
53262f27b2SOleksandr Tymoshenko */
54262f27b2SOleksandr Tymoshenko static void
run_timer(void * arg)55262f27b2SOleksandr Tymoshenko run_timer(void *arg)
56262f27b2SOleksandr Tymoshenko {
57262f27b2SOleksandr Tymoshenko struct timer_list *t = (struct timer_list *) arg;
58262f27b2SOleksandr Tymoshenko void (*function)(unsigned long);
59262f27b2SOleksandr Tymoshenko
60262f27b2SOleksandr Tymoshenko mtx_lock_spin(&t->mtx);
61262f27b2SOleksandr Tymoshenko if (callout_pending(&t->callout)) {
62262f27b2SOleksandr Tymoshenko /* callout was reset */
63262f27b2SOleksandr Tymoshenko mtx_unlock_spin(&t->mtx);
64262f27b2SOleksandr Tymoshenko return;
65262f27b2SOleksandr Tymoshenko }
66262f27b2SOleksandr Tymoshenko if (!callout_active(&t->callout)) {
67262f27b2SOleksandr Tymoshenko /* callout was stopped */
68262f27b2SOleksandr Tymoshenko mtx_unlock_spin(&t->mtx);
69262f27b2SOleksandr Tymoshenko return;
70262f27b2SOleksandr Tymoshenko }
71262f27b2SOleksandr Tymoshenko callout_deactivate(&t->callout);
72262f27b2SOleksandr Tymoshenko
73262f27b2SOleksandr Tymoshenko function = t->function;
74262f27b2SOleksandr Tymoshenko mtx_unlock_spin(&t->mtx);
75262f27b2SOleksandr Tymoshenko
76262f27b2SOleksandr Tymoshenko function(t->data);
77262f27b2SOleksandr Tymoshenko }
78262f27b2SOleksandr Tymoshenko
79262f27b2SOleksandr Tymoshenko void
vchiq_init_timer(struct timer_list * t)80*04b8208fSEmmanuel Vadot vchiq_init_timer(struct timer_list *t)
81262f27b2SOleksandr Tymoshenko {
82262f27b2SOleksandr Tymoshenko mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
83fd90e2edSJung-uk Kim callout_init(&t->callout, 1);
84262f27b2SOleksandr Tymoshenko t->expires = 0;
85262f27b2SOleksandr Tymoshenko /*
86262f27b2SOleksandr Tymoshenko * function and data are not initialized intentionally:
87262f27b2SOleksandr Tymoshenko * they are not initialized by Linux implementation too
88262f27b2SOleksandr Tymoshenko */
89262f27b2SOleksandr Tymoshenko }
90262f27b2SOleksandr Tymoshenko
91262f27b2SOleksandr Tymoshenko void
vchiq_setup_timer(struct timer_list * t,void (* function)(unsigned long),unsigned long data)92*04b8208fSEmmanuel Vadot vchiq_setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
93262f27b2SOleksandr Tymoshenko {
94262f27b2SOleksandr Tymoshenko t->function = function;
95262f27b2SOleksandr Tymoshenko t->data = data;
96*04b8208fSEmmanuel Vadot vchiq_init_timer(t);
97262f27b2SOleksandr Tymoshenko }
98262f27b2SOleksandr Tymoshenko
99262f27b2SOleksandr Tymoshenko void
vchiq_mod_timer(struct timer_list * t,unsigned long expires)100*04b8208fSEmmanuel Vadot vchiq_mod_timer(struct timer_list *t, unsigned long expires)
101262f27b2SOleksandr Tymoshenko {
102262f27b2SOleksandr Tymoshenko mtx_lock_spin(&t->mtx);
103262f27b2SOleksandr Tymoshenko callout_reset(&t->callout, expires - jiffies, run_timer, t);
104262f27b2SOleksandr Tymoshenko mtx_unlock_spin(&t->mtx);
105262f27b2SOleksandr Tymoshenko }
106262f27b2SOleksandr Tymoshenko
107262f27b2SOleksandr Tymoshenko void
vchiq_add_timer(struct timer_list * t)108*04b8208fSEmmanuel Vadot vchiq_add_timer(struct timer_list *t)
109262f27b2SOleksandr Tymoshenko {
110*04b8208fSEmmanuel Vadot vchiq_mod_timer(t, t->expires);
111262f27b2SOleksandr Tymoshenko }
112262f27b2SOleksandr Tymoshenko
113262f27b2SOleksandr Tymoshenko int
vchiq_del_timer_sync(struct timer_list * t)114*04b8208fSEmmanuel Vadot vchiq_del_timer_sync(struct timer_list *t)
115262f27b2SOleksandr Tymoshenko {
116262f27b2SOleksandr Tymoshenko mtx_lock_spin(&t->mtx);
117262f27b2SOleksandr Tymoshenko callout_stop(&t->callout);
118262f27b2SOleksandr Tymoshenko mtx_unlock_spin(&t->mtx);
119262f27b2SOleksandr Tymoshenko
120262f27b2SOleksandr Tymoshenko mtx_destroy(&t->mtx);
121262f27b2SOleksandr Tymoshenko return 0;
122262f27b2SOleksandr Tymoshenko }
123262f27b2SOleksandr Tymoshenko
124262f27b2SOleksandr Tymoshenko int
vchiq_del_timer(struct timer_list * t)125*04b8208fSEmmanuel Vadot vchiq_del_timer(struct timer_list *t)
126262f27b2SOleksandr Tymoshenko {
127*04b8208fSEmmanuel Vadot vchiq_del_timer_sync(t);
128262f27b2SOleksandr Tymoshenko return 0;
129262f27b2SOleksandr Tymoshenko }
130262f27b2SOleksandr Tymoshenko
131262f27b2SOleksandr Tymoshenko /*
132262f27b2SOleksandr Tymoshenko * Completion API
133262f27b2SOleksandr Tymoshenko */
134262f27b2SOleksandr Tymoshenko void
init_completion(struct completion * c)135262f27b2SOleksandr Tymoshenko init_completion(struct completion *c)
136262f27b2SOleksandr Tymoshenko {
137262f27b2SOleksandr Tymoshenko cv_init(&c->cv, "VCHI completion cv");
138262f27b2SOleksandr Tymoshenko mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
139262f27b2SOleksandr Tymoshenko c->done = 0;
140262f27b2SOleksandr Tymoshenko }
141262f27b2SOleksandr Tymoshenko
142262f27b2SOleksandr Tymoshenko void
destroy_completion(struct completion * c)143262f27b2SOleksandr Tymoshenko destroy_completion(struct completion *c)
144262f27b2SOleksandr Tymoshenko {
145262f27b2SOleksandr Tymoshenko cv_destroy(&c->cv);
146262f27b2SOleksandr Tymoshenko mtx_destroy(&c->lock);
147262f27b2SOleksandr Tymoshenko }
148262f27b2SOleksandr Tymoshenko
149262f27b2SOleksandr Tymoshenko void
complete(struct completion * c)150262f27b2SOleksandr Tymoshenko complete(struct completion *c)
151262f27b2SOleksandr Tymoshenko {
152262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
153262f27b2SOleksandr Tymoshenko
154262f27b2SOleksandr Tymoshenko if (c->done >= 0) {
155262f27b2SOleksandr Tymoshenko KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
156262f27b2SOleksandr Tymoshenko c->done++;
157262f27b2SOleksandr Tymoshenko cv_signal(&c->cv);
158262f27b2SOleksandr Tymoshenko } else {
159262f27b2SOleksandr Tymoshenko KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
160262f27b2SOleksandr Tymoshenko }
161262f27b2SOleksandr Tymoshenko
162262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
163262f27b2SOleksandr Tymoshenko }
164262f27b2SOleksandr Tymoshenko
165262f27b2SOleksandr Tymoshenko void
complete_all(struct completion * c)166262f27b2SOleksandr Tymoshenko complete_all(struct completion *c)
167262f27b2SOleksandr Tymoshenko {
168262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
169262f27b2SOleksandr Tymoshenko
170262f27b2SOleksandr Tymoshenko if (c->done >= 0) {
171262f27b2SOleksandr Tymoshenko KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
172262f27b2SOleksandr Tymoshenko c->done = -1;
173262f27b2SOleksandr Tymoshenko cv_broadcast(&c->cv);
174262f27b2SOleksandr Tymoshenko } else {
175262f27b2SOleksandr Tymoshenko KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
176262f27b2SOleksandr Tymoshenko }
177262f27b2SOleksandr Tymoshenko
178262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
179262f27b2SOleksandr Tymoshenko }
180262f27b2SOleksandr Tymoshenko
181262f27b2SOleksandr Tymoshenko void
INIT_COMPLETION_locked(struct completion * c)182262f27b2SOleksandr Tymoshenko INIT_COMPLETION_locked(struct completion *c)
183262f27b2SOleksandr Tymoshenko {
184262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
185262f27b2SOleksandr Tymoshenko
186262f27b2SOleksandr Tymoshenko c->done = 0;
187262f27b2SOleksandr Tymoshenko
188262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
189262f27b2SOleksandr Tymoshenko }
190262f27b2SOleksandr Tymoshenko
191262f27b2SOleksandr Tymoshenko static void
_completion_claim(struct completion * c)192262f27b2SOleksandr Tymoshenko _completion_claim(struct completion *c)
193262f27b2SOleksandr Tymoshenko {
194262f27b2SOleksandr Tymoshenko
195262f27b2SOleksandr Tymoshenko KASSERT(mtx_owned(&c->lock),
196262f27b2SOleksandr Tymoshenko ("_completion_claim should be called with acquired lock"));
197262f27b2SOleksandr Tymoshenko KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
198262f27b2SOleksandr Tymoshenko if (c->done > 0)
199262f27b2SOleksandr Tymoshenko c->done--;
200262f27b2SOleksandr Tymoshenko else
201262f27b2SOleksandr Tymoshenko KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
202262f27b2SOleksandr Tymoshenko }
203262f27b2SOleksandr Tymoshenko
204262f27b2SOleksandr Tymoshenko void
wait_for_completion(struct completion * c)205262f27b2SOleksandr Tymoshenko wait_for_completion(struct completion *c)
206262f27b2SOleksandr Tymoshenko {
207262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
208262f27b2SOleksandr Tymoshenko if (!c->done)
209262f27b2SOleksandr Tymoshenko cv_wait(&c->cv, &c->lock);
210262f27b2SOleksandr Tymoshenko c->done--;
211262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
212262f27b2SOleksandr Tymoshenko }
213262f27b2SOleksandr Tymoshenko
214262f27b2SOleksandr Tymoshenko int
try_wait_for_completion(struct completion * c)215262f27b2SOleksandr Tymoshenko try_wait_for_completion(struct completion *c)
216262f27b2SOleksandr Tymoshenko {
217262f27b2SOleksandr Tymoshenko int res = 0;
218262f27b2SOleksandr Tymoshenko
219262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
220262f27b2SOleksandr Tymoshenko if (!c->done)
221262f27b2SOleksandr Tymoshenko res = 1;
222262f27b2SOleksandr Tymoshenko else
223262f27b2SOleksandr Tymoshenko c->done--;
224262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
225262f27b2SOleksandr Tymoshenko return res == 0;
226262f27b2SOleksandr Tymoshenko }
227262f27b2SOleksandr Tymoshenko
228262f27b2SOleksandr Tymoshenko int
wait_for_completion_interruptible_timeout(struct completion * c,unsigned long timeout)229262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
230262f27b2SOleksandr Tymoshenko {
231262f27b2SOleksandr Tymoshenko int res = 0;
232262f27b2SOleksandr Tymoshenko unsigned long start, now;
233262f27b2SOleksandr Tymoshenko start = jiffies;
234262f27b2SOleksandr Tymoshenko
235262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
236262f27b2SOleksandr Tymoshenko while (c->done == 0) {
237262f27b2SOleksandr Tymoshenko res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
238262f27b2SOleksandr Tymoshenko if (res)
239262f27b2SOleksandr Tymoshenko goto out;
240262f27b2SOleksandr Tymoshenko now = jiffies;
241262f27b2SOleksandr Tymoshenko if (timeout < (now - start)) {
242262f27b2SOleksandr Tymoshenko res = EWOULDBLOCK;
243262f27b2SOleksandr Tymoshenko goto out;
244262f27b2SOleksandr Tymoshenko }
245262f27b2SOleksandr Tymoshenko
246262f27b2SOleksandr Tymoshenko timeout -= (now - start);
247262f27b2SOleksandr Tymoshenko start = now;
248262f27b2SOleksandr Tymoshenko }
249262f27b2SOleksandr Tymoshenko
250262f27b2SOleksandr Tymoshenko _completion_claim(c);
251262f27b2SOleksandr Tymoshenko res = 0;
252262f27b2SOleksandr Tymoshenko
253262f27b2SOleksandr Tymoshenko out:
254262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
255262f27b2SOleksandr Tymoshenko
256262f27b2SOleksandr Tymoshenko if (res == EWOULDBLOCK) {
257262f27b2SOleksandr Tymoshenko return 0;
258262f27b2SOleksandr Tymoshenko } else if ((res == EINTR) || (res == ERESTART)) {
259262f27b2SOleksandr Tymoshenko return -ERESTART;
260262f27b2SOleksandr Tymoshenko } else {
261262f27b2SOleksandr Tymoshenko KASSERT((res == 0), ("res = %d", res));
262262f27b2SOleksandr Tymoshenko return timeout;
263262f27b2SOleksandr Tymoshenko }
264262f27b2SOleksandr Tymoshenko }
265262f27b2SOleksandr Tymoshenko
266262f27b2SOleksandr Tymoshenko int
wait_for_completion_interruptible(struct completion * c)267262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible(struct completion *c)
268262f27b2SOleksandr Tymoshenko {
269262f27b2SOleksandr Tymoshenko int res = 0;
270262f27b2SOleksandr Tymoshenko
271262f27b2SOleksandr Tymoshenko mtx_lock(&c->lock);
272262f27b2SOleksandr Tymoshenko while (c->done == 0) {
273262f27b2SOleksandr Tymoshenko res = cv_wait_sig(&c->cv, &c->lock);
274262f27b2SOleksandr Tymoshenko if (res)
275262f27b2SOleksandr Tymoshenko goto out;
276262f27b2SOleksandr Tymoshenko }
277262f27b2SOleksandr Tymoshenko
278262f27b2SOleksandr Tymoshenko _completion_claim(c);
279262f27b2SOleksandr Tymoshenko
280262f27b2SOleksandr Tymoshenko out:
281262f27b2SOleksandr Tymoshenko mtx_unlock(&c->lock);
282262f27b2SOleksandr Tymoshenko
283262f27b2SOleksandr Tymoshenko if ((res == EINTR) || (res == ERESTART))
284262f27b2SOleksandr Tymoshenko res = -ERESTART;
285262f27b2SOleksandr Tymoshenko return res;
286262f27b2SOleksandr Tymoshenko }
287262f27b2SOleksandr Tymoshenko
288262f27b2SOleksandr Tymoshenko int
wait_for_completion_killable(struct completion * c)289262f27b2SOleksandr Tymoshenko wait_for_completion_killable(struct completion *c)
290262f27b2SOleksandr Tymoshenko {
291262f27b2SOleksandr Tymoshenko
292262f27b2SOleksandr Tymoshenko return wait_for_completion_interruptible(c);
293262f27b2SOleksandr Tymoshenko }
294262f27b2SOleksandr Tymoshenko
295262f27b2SOleksandr Tymoshenko /*
296262f27b2SOleksandr Tymoshenko * Semaphore API
297262f27b2SOleksandr Tymoshenko */
298262f27b2SOleksandr Tymoshenko
sema_sysinit(void * arg)299262f27b2SOleksandr Tymoshenko void sema_sysinit(void *arg)
300262f27b2SOleksandr Tymoshenko {
301262f27b2SOleksandr Tymoshenko struct semaphore *s = arg;
302262f27b2SOleksandr Tymoshenko
303262f27b2SOleksandr Tymoshenko _sema_init(s, 1);
304262f27b2SOleksandr Tymoshenko }
305262f27b2SOleksandr Tymoshenko
306262f27b2SOleksandr Tymoshenko void
_sema_init(struct semaphore * s,int value)307262f27b2SOleksandr Tymoshenko _sema_init(struct semaphore *s, int value)
308262f27b2SOleksandr Tymoshenko {
309262f27b2SOleksandr Tymoshenko bzero(s, sizeof(*s));
310262f27b2SOleksandr Tymoshenko mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
311262f27b2SOleksandr Tymoshenko MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
312262f27b2SOleksandr Tymoshenko cv_init(&s->cv, "sema cv");
313262f27b2SOleksandr Tymoshenko s->value = value;
314262f27b2SOleksandr Tymoshenko }
315262f27b2SOleksandr Tymoshenko
316262f27b2SOleksandr Tymoshenko void
_sema_destroy(struct semaphore * s)317262f27b2SOleksandr Tymoshenko _sema_destroy(struct semaphore *s)
318262f27b2SOleksandr Tymoshenko {
319262f27b2SOleksandr Tymoshenko mtx_destroy(&s->mtx);
320262f27b2SOleksandr Tymoshenko cv_destroy(&s->cv);
321262f27b2SOleksandr Tymoshenko }
322262f27b2SOleksandr Tymoshenko
323262f27b2SOleksandr Tymoshenko void
down(struct semaphore * s)324262f27b2SOleksandr Tymoshenko down(struct semaphore *s)
325262f27b2SOleksandr Tymoshenko {
326262f27b2SOleksandr Tymoshenko
327262f27b2SOleksandr Tymoshenko mtx_lock(&s->mtx);
328262f27b2SOleksandr Tymoshenko while (s->value == 0) {
329262f27b2SOleksandr Tymoshenko s->waiters++;
330262f27b2SOleksandr Tymoshenko cv_wait(&s->cv, &s->mtx);
331262f27b2SOleksandr Tymoshenko s->waiters--;
332262f27b2SOleksandr Tymoshenko }
333262f27b2SOleksandr Tymoshenko
334262f27b2SOleksandr Tymoshenko s->value--;
335262f27b2SOleksandr Tymoshenko mtx_unlock(&s->mtx);
336262f27b2SOleksandr Tymoshenko }
337262f27b2SOleksandr Tymoshenko
338262f27b2SOleksandr Tymoshenko int
down_interruptible(struct semaphore * s)339262f27b2SOleksandr Tymoshenko down_interruptible(struct semaphore *s)
340262f27b2SOleksandr Tymoshenko {
341262f27b2SOleksandr Tymoshenko int ret ;
342262f27b2SOleksandr Tymoshenko
343262f27b2SOleksandr Tymoshenko ret = 0;
344262f27b2SOleksandr Tymoshenko
345262f27b2SOleksandr Tymoshenko mtx_lock(&s->mtx);
346262f27b2SOleksandr Tymoshenko
347262f27b2SOleksandr Tymoshenko while (s->value == 0) {
348262f27b2SOleksandr Tymoshenko s->waiters++;
349262f27b2SOleksandr Tymoshenko ret = cv_wait_sig(&s->cv, &s->mtx);
350262f27b2SOleksandr Tymoshenko s->waiters--;
351262f27b2SOleksandr Tymoshenko
352262f27b2SOleksandr Tymoshenko if (ret == EINTR) {
353262f27b2SOleksandr Tymoshenko mtx_unlock(&s->mtx);
354262f27b2SOleksandr Tymoshenko return (-EINTR);
355262f27b2SOleksandr Tymoshenko }
356262f27b2SOleksandr Tymoshenko
357262f27b2SOleksandr Tymoshenko if (ret == ERESTART)
358262f27b2SOleksandr Tymoshenko continue;
359262f27b2SOleksandr Tymoshenko }
360262f27b2SOleksandr Tymoshenko
361262f27b2SOleksandr Tymoshenko s->value--;
362262f27b2SOleksandr Tymoshenko mtx_unlock(&s->mtx);
363262f27b2SOleksandr Tymoshenko
364262f27b2SOleksandr Tymoshenko return (0);
365262f27b2SOleksandr Tymoshenko }
366262f27b2SOleksandr Tymoshenko
367262f27b2SOleksandr Tymoshenko int
down_trylock(struct semaphore * s)368262f27b2SOleksandr Tymoshenko down_trylock(struct semaphore *s)
369262f27b2SOleksandr Tymoshenko {
370262f27b2SOleksandr Tymoshenko int ret;
371262f27b2SOleksandr Tymoshenko
372262f27b2SOleksandr Tymoshenko ret = 0;
373262f27b2SOleksandr Tymoshenko
374262f27b2SOleksandr Tymoshenko mtx_lock(&s->mtx);
375262f27b2SOleksandr Tymoshenko
376262f27b2SOleksandr Tymoshenko if (s->value > 0) {
377262f27b2SOleksandr Tymoshenko /* Success. */
378262f27b2SOleksandr Tymoshenko s->value--;
379262f27b2SOleksandr Tymoshenko ret = 0;
380262f27b2SOleksandr Tymoshenko } else {
381262f27b2SOleksandr Tymoshenko ret = -EAGAIN;
382262f27b2SOleksandr Tymoshenko }
383262f27b2SOleksandr Tymoshenko
384262f27b2SOleksandr Tymoshenko mtx_unlock(&s->mtx);
385262f27b2SOleksandr Tymoshenko
386262f27b2SOleksandr Tymoshenko return (ret);
387262f27b2SOleksandr Tymoshenko }
388262f27b2SOleksandr Tymoshenko
389262f27b2SOleksandr Tymoshenko void
up(struct semaphore * s)390262f27b2SOleksandr Tymoshenko up(struct semaphore *s)
391262f27b2SOleksandr Tymoshenko {
392262f27b2SOleksandr Tymoshenko mtx_lock(&s->mtx);
393262f27b2SOleksandr Tymoshenko s->value++;
394262f27b2SOleksandr Tymoshenko if (s->waiters && s->value > 0)
395262f27b2SOleksandr Tymoshenko cv_signal(&s->cv);
396262f27b2SOleksandr Tymoshenko
397262f27b2SOleksandr Tymoshenko mtx_unlock(&s->mtx);
398262f27b2SOleksandr Tymoshenko }
399262f27b2SOleksandr Tymoshenko
400262f27b2SOleksandr Tymoshenko /*
401262f27b2SOleksandr Tymoshenko * Logging API
402262f27b2SOleksandr Tymoshenko */
403262f27b2SOleksandr Tymoshenko void
rlprintf(int pps,const char * fmt,...)404262f27b2SOleksandr Tymoshenko rlprintf(int pps, const char *fmt, ...)
405262f27b2SOleksandr Tymoshenko {
406262f27b2SOleksandr Tymoshenko va_list ap;
407262f27b2SOleksandr Tymoshenko static struct timeval last_printf;
408262f27b2SOleksandr Tymoshenko static int count;
409262f27b2SOleksandr Tymoshenko
410262f27b2SOleksandr Tymoshenko if (ppsratecheck(&last_printf, &count, pps)) {
411262f27b2SOleksandr Tymoshenko va_start(ap, fmt);
412262f27b2SOleksandr Tymoshenko vprintf(fmt, ap);
413262f27b2SOleksandr Tymoshenko va_end(ap);
414262f27b2SOleksandr Tymoshenko }
415262f27b2SOleksandr Tymoshenko }
416262f27b2SOleksandr Tymoshenko
417262f27b2SOleksandr Tymoshenko void
device_rlprintf(int pps,device_t dev,const char * fmt,...)418262f27b2SOleksandr Tymoshenko device_rlprintf(int pps, device_t dev, const char *fmt, ...)
419262f27b2SOleksandr Tymoshenko {
420262f27b2SOleksandr Tymoshenko va_list ap;
421262f27b2SOleksandr Tymoshenko static struct timeval last_printf;
422262f27b2SOleksandr Tymoshenko static int count;
423262f27b2SOleksandr Tymoshenko
424262f27b2SOleksandr Tymoshenko if (ppsratecheck(&last_printf, &count, pps)) {
425262f27b2SOleksandr Tymoshenko va_start(ap, fmt);
426262f27b2SOleksandr Tymoshenko device_print_prettyname(dev);
427262f27b2SOleksandr Tymoshenko vprintf(fmt, ap);
428262f27b2SOleksandr Tymoshenko va_end(ap);
429262f27b2SOleksandr Tymoshenko }
430262f27b2SOleksandr Tymoshenko }
431262f27b2SOleksandr Tymoshenko
432262f27b2SOleksandr Tymoshenko /*
433262f27b2SOleksandr Tymoshenko * Signals API
434262f27b2SOleksandr Tymoshenko */
435262f27b2SOleksandr Tymoshenko
436262f27b2SOleksandr Tymoshenko void
flush_signals(VCHIQ_THREAD_T thr)437262f27b2SOleksandr Tymoshenko flush_signals(VCHIQ_THREAD_T thr)
438262f27b2SOleksandr Tymoshenko {
439262f27b2SOleksandr Tymoshenko printf("Implement ME: %s\n", __func__);
440262f27b2SOleksandr Tymoshenko }
441262f27b2SOleksandr Tymoshenko
442262f27b2SOleksandr Tymoshenko int
fatal_signal_pending(VCHIQ_THREAD_T thr)443262f27b2SOleksandr Tymoshenko fatal_signal_pending(VCHIQ_THREAD_T thr)
444262f27b2SOleksandr Tymoshenko {
445262f27b2SOleksandr Tymoshenko printf("Implement ME: %s\n", __func__);
446262f27b2SOleksandr Tymoshenko return (0);
447262f27b2SOleksandr Tymoshenko }
448262f27b2SOleksandr Tymoshenko
449262f27b2SOleksandr Tymoshenko /*
450262f27b2SOleksandr Tymoshenko * kthread API
451262f27b2SOleksandr Tymoshenko */
452262f27b2SOleksandr Tymoshenko
453262f27b2SOleksandr Tymoshenko /*
454262f27b2SOleksandr Tymoshenko * This is a hack to avoid memory leak
455262f27b2SOleksandr Tymoshenko */
456262f27b2SOleksandr Tymoshenko #define MAX_THREAD_DATA_SLOTS 32
457262f27b2SOleksandr Tymoshenko static int thread_data_slot = 0;
458262f27b2SOleksandr Tymoshenko
459262f27b2SOleksandr Tymoshenko struct thread_data {
460262f27b2SOleksandr Tymoshenko void *data;
461262f27b2SOleksandr Tymoshenko int (*threadfn)(void *);
462262f27b2SOleksandr Tymoshenko };
463262f27b2SOleksandr Tymoshenko
464262f27b2SOleksandr Tymoshenko static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
465262f27b2SOleksandr Tymoshenko
466262f27b2SOleksandr Tymoshenko static void
kthread_wrapper(void * data)467262f27b2SOleksandr Tymoshenko kthread_wrapper(void *data)
468262f27b2SOleksandr Tymoshenko {
469262f27b2SOleksandr Tymoshenko struct thread_data *slot;
470262f27b2SOleksandr Tymoshenko
471262f27b2SOleksandr Tymoshenko slot = data;
472262f27b2SOleksandr Tymoshenko slot->threadfn(slot->data);
473262f27b2SOleksandr Tymoshenko }
474262f27b2SOleksandr Tymoshenko
475262f27b2SOleksandr Tymoshenko VCHIQ_THREAD_T
vchiq_thread_create(int (* threadfn)(void * data),void * data,const char namefmt[],...)476262f27b2SOleksandr Tymoshenko vchiq_thread_create(int (*threadfn)(void *data),
477262f27b2SOleksandr Tymoshenko void *data,
478262f27b2SOleksandr Tymoshenko const char namefmt[], ...)
479262f27b2SOleksandr Tymoshenko {
480262f27b2SOleksandr Tymoshenko VCHIQ_THREAD_T newp;
481262f27b2SOleksandr Tymoshenko va_list ap;
482262f27b2SOleksandr Tymoshenko char name[MAXCOMLEN+1];
483262f27b2SOleksandr Tymoshenko struct thread_data *slot;
484262f27b2SOleksandr Tymoshenko
485262f27b2SOleksandr Tymoshenko if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
486262f27b2SOleksandr Tymoshenko printf("kthread_create: out of thread data slots\n");
487262f27b2SOleksandr Tymoshenko return (NULL);
488262f27b2SOleksandr Tymoshenko }
489262f27b2SOleksandr Tymoshenko
490262f27b2SOleksandr Tymoshenko slot = &thread_slots[thread_data_slot];
491262f27b2SOleksandr Tymoshenko slot->data = data;
492262f27b2SOleksandr Tymoshenko slot->threadfn = threadfn;
493262f27b2SOleksandr Tymoshenko
494262f27b2SOleksandr Tymoshenko va_start(ap, namefmt);
495262f27b2SOleksandr Tymoshenko vsnprintf(name, sizeof(name), namefmt, ap);
496262f27b2SOleksandr Tymoshenko va_end(ap);
497262f27b2SOleksandr Tymoshenko
498262f27b2SOleksandr Tymoshenko newp = NULL;
499262f27b2SOleksandr Tymoshenko if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
500262f27b2SOleksandr Tymoshenko "%s", name) != 0) {
501262f27b2SOleksandr Tymoshenko /* Just to be sure */
502262f27b2SOleksandr Tymoshenko newp = NULL;
503262f27b2SOleksandr Tymoshenko }
504262f27b2SOleksandr Tymoshenko else
505262f27b2SOleksandr Tymoshenko thread_data_slot++;
506262f27b2SOleksandr Tymoshenko
507262f27b2SOleksandr Tymoshenko return newp;
508262f27b2SOleksandr Tymoshenko }
509262f27b2SOleksandr Tymoshenko
510262f27b2SOleksandr Tymoshenko void
set_user_nice(VCHIQ_THREAD_T thr,int nice)511262f27b2SOleksandr Tymoshenko set_user_nice(VCHIQ_THREAD_T thr, int nice)
512262f27b2SOleksandr Tymoshenko {
513262f27b2SOleksandr Tymoshenko /* NOOP */
514262f27b2SOleksandr Tymoshenko }
515262f27b2SOleksandr Tymoshenko
516262f27b2SOleksandr Tymoshenko void
wake_up_process(VCHIQ_THREAD_T thr)517262f27b2SOleksandr Tymoshenko wake_up_process(VCHIQ_THREAD_T thr)
518262f27b2SOleksandr Tymoshenko {
519262f27b2SOleksandr Tymoshenko /* NOOP */
520262f27b2SOleksandr Tymoshenko }
521262f27b2SOleksandr Tymoshenko
522262f27b2SOleksandr Tymoshenko void
bcm_mbox_write(int channel,uint32_t data)523262f27b2SOleksandr Tymoshenko bcm_mbox_write(int channel, uint32_t data)
524262f27b2SOleksandr Tymoshenko {
525262f27b2SOleksandr Tymoshenko device_t mbox;
526262f27b2SOleksandr Tymoshenko
527262f27b2SOleksandr Tymoshenko mbox = devclass_get_device(devclass_find("mbox"), 0);
528262f27b2SOleksandr Tymoshenko
529262f27b2SOleksandr Tymoshenko if (mbox)
530262f27b2SOleksandr Tymoshenko MBOX_WRITE(mbox, channel, data);
531262f27b2SOleksandr Tymoshenko }
532