xref: /freebsd/sys/contrib/vchiq/interface/compat/vchi_bsd.c (revision 262f27b29e964475c0bcc346e9d50f5ebf3c20e8)
1*262f27b2SOleksandr Tymoshenko /*-
2*262f27b2SOleksandr Tymoshenko  * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
3*262f27b2SOleksandr Tymoshenko  * All rights reserved.
4*262f27b2SOleksandr Tymoshenko  *
5*262f27b2SOleksandr Tymoshenko  * This software was developed by Max Khon under sponsorship from
6*262f27b2SOleksandr Tymoshenko  * the FreeBSD Foundation and Ethon Technologies GmbH.
7*262f27b2SOleksandr Tymoshenko  *
8*262f27b2SOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
9*262f27b2SOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
10*262f27b2SOleksandr Tymoshenko  * are met:
11*262f27b2SOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
12*262f27b2SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
13*262f27b2SOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
14*262f27b2SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
15*262f27b2SOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
16*262f27b2SOleksandr Tymoshenko  *
17*262f27b2SOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18*262f27b2SOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*262f27b2SOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*262f27b2SOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21*262f27b2SOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*262f27b2SOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*262f27b2SOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*262f27b2SOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*262f27b2SOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*262f27b2SOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*262f27b2SOleksandr Tymoshenko  * SUCH DAMAGE.
28*262f27b2SOleksandr Tymoshenko  *
29*262f27b2SOleksandr Tymoshenko  * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
30*262f27b2SOleksandr Tymoshenko  */
31*262f27b2SOleksandr Tymoshenko 
32*262f27b2SOleksandr Tymoshenko #include <sys/types.h>
33*262f27b2SOleksandr Tymoshenko #include <sys/limits.h>
34*262f27b2SOleksandr Tymoshenko #include <sys/bus.h>
35*262f27b2SOleksandr Tymoshenko #include <sys/callout.h>
36*262f27b2SOleksandr Tymoshenko #include <sys/firmware.h>
37*262f27b2SOleksandr Tymoshenko #include <sys/param.h>
38*262f27b2SOleksandr Tymoshenko #include <sys/proc.h>
39*262f27b2SOleksandr Tymoshenko #include <sys/syscallsubr.h>
40*262f27b2SOleksandr Tymoshenko #include <sys/systm.h>
41*262f27b2SOleksandr Tymoshenko #include <sys/taskqueue.h>
42*262f27b2SOleksandr Tymoshenko 
43*262f27b2SOleksandr Tymoshenko #include <machine/stdarg.h>
44*262f27b2SOleksandr Tymoshenko 
45*262f27b2SOleksandr Tymoshenko #include "mbox_if.h"
46*262f27b2SOleksandr Tymoshenko 
47*262f27b2SOleksandr Tymoshenko #include <interface/compat/vchi_bsd.h>
48*262f27b2SOleksandr Tymoshenko 
49*262f27b2SOleksandr Tymoshenko MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
50*262f27b2SOleksandr Tymoshenko 
51*262f27b2SOleksandr Tymoshenko /*
52*262f27b2SOleksandr Tymoshenko  * Timer API
53*262f27b2SOleksandr Tymoshenko  */
54*262f27b2SOleksandr Tymoshenko static void
55*262f27b2SOleksandr Tymoshenko run_timer(void *arg)
56*262f27b2SOleksandr Tymoshenko {
57*262f27b2SOleksandr Tymoshenko 	struct timer_list *t = (struct timer_list *) arg;
58*262f27b2SOleksandr Tymoshenko 	void (*function)(unsigned long);
59*262f27b2SOleksandr Tymoshenko 
60*262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
61*262f27b2SOleksandr Tymoshenko 	if (callout_pending(&t->callout)) {
62*262f27b2SOleksandr Tymoshenko 		/* callout was reset */
63*262f27b2SOleksandr Tymoshenko 		mtx_unlock_spin(&t->mtx);
64*262f27b2SOleksandr Tymoshenko 		return;
65*262f27b2SOleksandr Tymoshenko 	}
66*262f27b2SOleksandr Tymoshenko 	if (!callout_active(&t->callout)) {
67*262f27b2SOleksandr Tymoshenko 		/* callout was stopped */
68*262f27b2SOleksandr Tymoshenko 		mtx_unlock_spin(&t->mtx);
69*262f27b2SOleksandr Tymoshenko 		return;
70*262f27b2SOleksandr Tymoshenko 	}
71*262f27b2SOleksandr Tymoshenko 	callout_deactivate(&t->callout);
72*262f27b2SOleksandr Tymoshenko 
73*262f27b2SOleksandr Tymoshenko 	function = t->function;
74*262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
75*262f27b2SOleksandr Tymoshenko 
76*262f27b2SOleksandr Tymoshenko 	function(t->data);
77*262f27b2SOleksandr Tymoshenko }
78*262f27b2SOleksandr Tymoshenko 
79*262f27b2SOleksandr Tymoshenko void
80*262f27b2SOleksandr Tymoshenko init_timer(struct timer_list *t)
81*262f27b2SOleksandr Tymoshenko {
82*262f27b2SOleksandr Tymoshenko 	mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
83*262f27b2SOleksandr Tymoshenko 	callout_init(&t->callout, CALLOUT_MPSAFE);
84*262f27b2SOleksandr Tymoshenko 	t->expires = 0;
85*262f27b2SOleksandr Tymoshenko 	/*
86*262f27b2SOleksandr Tymoshenko 	 * function and data are not initialized intentionally:
87*262f27b2SOleksandr Tymoshenko 	 * they are not initialized by Linux implementation too
88*262f27b2SOleksandr Tymoshenko 	 */
89*262f27b2SOleksandr Tymoshenko }
90*262f27b2SOleksandr Tymoshenko 
91*262f27b2SOleksandr Tymoshenko void
92*262f27b2SOleksandr Tymoshenko setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
93*262f27b2SOleksandr Tymoshenko {
94*262f27b2SOleksandr Tymoshenko 	t->function = function;
95*262f27b2SOleksandr Tymoshenko 	t->data = data;
96*262f27b2SOleksandr Tymoshenko 	init_timer(t);
97*262f27b2SOleksandr Tymoshenko }
98*262f27b2SOleksandr Tymoshenko 
99*262f27b2SOleksandr Tymoshenko void
100*262f27b2SOleksandr Tymoshenko mod_timer(struct timer_list *t, unsigned long expires)
101*262f27b2SOleksandr Tymoshenko {
102*262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
103*262f27b2SOleksandr Tymoshenko 	callout_reset(&t->callout, expires - jiffies, run_timer, t);
104*262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
105*262f27b2SOleksandr Tymoshenko }
106*262f27b2SOleksandr Tymoshenko 
107*262f27b2SOleksandr Tymoshenko void
108*262f27b2SOleksandr Tymoshenko add_timer(struct timer_list *t)
109*262f27b2SOleksandr Tymoshenko {
110*262f27b2SOleksandr Tymoshenko 	mod_timer(t, t->expires);
111*262f27b2SOleksandr Tymoshenko }
112*262f27b2SOleksandr Tymoshenko 
113*262f27b2SOleksandr Tymoshenko int
114*262f27b2SOleksandr Tymoshenko del_timer_sync(struct timer_list *t)
115*262f27b2SOleksandr Tymoshenko {
116*262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
117*262f27b2SOleksandr Tymoshenko 	callout_stop(&t->callout);
118*262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
119*262f27b2SOleksandr Tymoshenko 
120*262f27b2SOleksandr Tymoshenko 	mtx_destroy(&t->mtx);
121*262f27b2SOleksandr Tymoshenko 	return 0;
122*262f27b2SOleksandr Tymoshenko }
123*262f27b2SOleksandr Tymoshenko 
124*262f27b2SOleksandr Tymoshenko int
125*262f27b2SOleksandr Tymoshenko del_timer(struct timer_list *t)
126*262f27b2SOleksandr Tymoshenko {
127*262f27b2SOleksandr Tymoshenko 	del_timer_sync(t);
128*262f27b2SOleksandr Tymoshenko 	return 0;
129*262f27b2SOleksandr Tymoshenko }
130*262f27b2SOleksandr Tymoshenko 
131*262f27b2SOleksandr Tymoshenko /*
132*262f27b2SOleksandr Tymoshenko  * Completion API
133*262f27b2SOleksandr Tymoshenko  */
134*262f27b2SOleksandr Tymoshenko void
135*262f27b2SOleksandr Tymoshenko init_completion(struct completion *c)
136*262f27b2SOleksandr Tymoshenko {
137*262f27b2SOleksandr Tymoshenko 	cv_init(&c->cv, "VCHI completion cv");
138*262f27b2SOleksandr Tymoshenko 	mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
139*262f27b2SOleksandr Tymoshenko 	c->done = 0;
140*262f27b2SOleksandr Tymoshenko }
141*262f27b2SOleksandr Tymoshenko 
142*262f27b2SOleksandr Tymoshenko void
143*262f27b2SOleksandr Tymoshenko destroy_completion(struct completion *c)
144*262f27b2SOleksandr Tymoshenko {
145*262f27b2SOleksandr Tymoshenko 	cv_destroy(&c->cv);
146*262f27b2SOleksandr Tymoshenko 	mtx_destroy(&c->lock);
147*262f27b2SOleksandr Tymoshenko }
148*262f27b2SOleksandr Tymoshenko 
149*262f27b2SOleksandr Tymoshenko void
150*262f27b2SOleksandr Tymoshenko complete(struct completion *c)
151*262f27b2SOleksandr Tymoshenko {
152*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
153*262f27b2SOleksandr Tymoshenko 
154*262f27b2SOleksandr Tymoshenko 	if (c->done >= 0) {
155*262f27b2SOleksandr Tymoshenko 		KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
156*262f27b2SOleksandr Tymoshenko 		c->done++;
157*262f27b2SOleksandr Tymoshenko 		cv_signal(&c->cv);
158*262f27b2SOleksandr Tymoshenko 	} else {
159*262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
160*262f27b2SOleksandr Tymoshenko 	}
161*262f27b2SOleksandr Tymoshenko 
162*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
163*262f27b2SOleksandr Tymoshenko }
164*262f27b2SOleksandr Tymoshenko 
165*262f27b2SOleksandr Tymoshenko void
166*262f27b2SOleksandr Tymoshenko complete_all(struct completion *c)
167*262f27b2SOleksandr Tymoshenko {
168*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
169*262f27b2SOleksandr Tymoshenko 
170*262f27b2SOleksandr Tymoshenko 	if (c->done >= 0) {
171*262f27b2SOleksandr Tymoshenko 		KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
172*262f27b2SOleksandr Tymoshenko 		c->done = -1;
173*262f27b2SOleksandr Tymoshenko 		cv_broadcast(&c->cv);
174*262f27b2SOleksandr Tymoshenko 	} else {
175*262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
176*262f27b2SOleksandr Tymoshenko 	}
177*262f27b2SOleksandr Tymoshenko 
178*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
179*262f27b2SOleksandr Tymoshenko }
180*262f27b2SOleksandr Tymoshenko 
181*262f27b2SOleksandr Tymoshenko void
182*262f27b2SOleksandr Tymoshenko INIT_COMPLETION_locked(struct completion *c)
183*262f27b2SOleksandr Tymoshenko {
184*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
185*262f27b2SOleksandr Tymoshenko 
186*262f27b2SOleksandr Tymoshenko 	c->done = 0;
187*262f27b2SOleksandr Tymoshenko 
188*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
189*262f27b2SOleksandr Tymoshenko }
190*262f27b2SOleksandr Tymoshenko 
191*262f27b2SOleksandr Tymoshenko static void
192*262f27b2SOleksandr Tymoshenko _completion_claim(struct completion *c)
193*262f27b2SOleksandr Tymoshenko {
194*262f27b2SOleksandr Tymoshenko 
195*262f27b2SOleksandr Tymoshenko 	KASSERT(mtx_owned(&c->lock),
196*262f27b2SOleksandr Tymoshenko 	    ("_completion_claim should be called with acquired lock"));
197*262f27b2SOleksandr Tymoshenko 	KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
198*262f27b2SOleksandr Tymoshenko 	if (c->done > 0)
199*262f27b2SOleksandr Tymoshenko 		c->done--;
200*262f27b2SOleksandr Tymoshenko 	else
201*262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
202*262f27b2SOleksandr Tymoshenko }
203*262f27b2SOleksandr Tymoshenko 
204*262f27b2SOleksandr Tymoshenko void
205*262f27b2SOleksandr Tymoshenko wait_for_completion(struct completion *c)
206*262f27b2SOleksandr Tymoshenko {
207*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
208*262f27b2SOleksandr Tymoshenko 	if (!c->done)
209*262f27b2SOleksandr Tymoshenko 		cv_wait(&c->cv, &c->lock);
210*262f27b2SOleksandr Tymoshenko 	c->done--;
211*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
212*262f27b2SOleksandr Tymoshenko }
213*262f27b2SOleksandr Tymoshenko 
214*262f27b2SOleksandr Tymoshenko int
215*262f27b2SOleksandr Tymoshenko try_wait_for_completion(struct completion *c)
216*262f27b2SOleksandr Tymoshenko {
217*262f27b2SOleksandr Tymoshenko 	int res = 0;
218*262f27b2SOleksandr Tymoshenko 
219*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
220*262f27b2SOleksandr Tymoshenko 	if (!c->done)
221*262f27b2SOleksandr Tymoshenko 		res = 1;
222*262f27b2SOleksandr Tymoshenko 	else
223*262f27b2SOleksandr Tymoshenko 		c->done--;
224*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
225*262f27b2SOleksandr Tymoshenko 	return res == 0;
226*262f27b2SOleksandr Tymoshenko }
227*262f27b2SOleksandr Tymoshenko 
228*262f27b2SOleksandr Tymoshenko int
229*262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
230*262f27b2SOleksandr Tymoshenko {
231*262f27b2SOleksandr Tymoshenko 	int res = 0;
232*262f27b2SOleksandr Tymoshenko 	unsigned long start, now;
233*262f27b2SOleksandr Tymoshenko 	start = jiffies;
234*262f27b2SOleksandr Tymoshenko 
235*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
236*262f27b2SOleksandr Tymoshenko 	while (c->done == 0) {
237*262f27b2SOleksandr Tymoshenko 		res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
238*262f27b2SOleksandr Tymoshenko 		if (res)
239*262f27b2SOleksandr Tymoshenko 			goto out;
240*262f27b2SOleksandr Tymoshenko 		now = jiffies;
241*262f27b2SOleksandr Tymoshenko 		if (timeout < (now - start)) {
242*262f27b2SOleksandr Tymoshenko 			res = EWOULDBLOCK;
243*262f27b2SOleksandr Tymoshenko 			goto out;
244*262f27b2SOleksandr Tymoshenko 		}
245*262f27b2SOleksandr Tymoshenko 
246*262f27b2SOleksandr Tymoshenko 		timeout -= (now - start);
247*262f27b2SOleksandr Tymoshenko 		start = now;
248*262f27b2SOleksandr Tymoshenko 	}
249*262f27b2SOleksandr Tymoshenko 
250*262f27b2SOleksandr Tymoshenko 	_completion_claim(c);
251*262f27b2SOleksandr Tymoshenko 	res = 0;
252*262f27b2SOleksandr Tymoshenko 
253*262f27b2SOleksandr Tymoshenko out:
254*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
255*262f27b2SOleksandr Tymoshenko 
256*262f27b2SOleksandr Tymoshenko 	if (res == EWOULDBLOCK) {
257*262f27b2SOleksandr Tymoshenko 		return 0;
258*262f27b2SOleksandr Tymoshenko 	} else if ((res == EINTR) || (res == ERESTART)) {
259*262f27b2SOleksandr Tymoshenko 		return -ERESTART;
260*262f27b2SOleksandr Tymoshenko 	} else {
261*262f27b2SOleksandr Tymoshenko 		KASSERT((res == 0), ("res = %d", res));
262*262f27b2SOleksandr Tymoshenko 		return timeout;
263*262f27b2SOleksandr Tymoshenko 	}
264*262f27b2SOleksandr Tymoshenko }
265*262f27b2SOleksandr Tymoshenko 
266*262f27b2SOleksandr Tymoshenko int
267*262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible(struct completion *c)
268*262f27b2SOleksandr Tymoshenko {
269*262f27b2SOleksandr Tymoshenko 	int res = 0;
270*262f27b2SOleksandr Tymoshenko 
271*262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
272*262f27b2SOleksandr Tymoshenko 	while (c->done == 0) {
273*262f27b2SOleksandr Tymoshenko 		res = cv_wait_sig(&c->cv, &c->lock);
274*262f27b2SOleksandr Tymoshenko 		if (res)
275*262f27b2SOleksandr Tymoshenko 			goto out;
276*262f27b2SOleksandr Tymoshenko 	}
277*262f27b2SOleksandr Tymoshenko 
278*262f27b2SOleksandr Tymoshenko 	_completion_claim(c);
279*262f27b2SOleksandr Tymoshenko 
280*262f27b2SOleksandr Tymoshenko out:
281*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
282*262f27b2SOleksandr Tymoshenko 
283*262f27b2SOleksandr Tymoshenko 	if ((res == EINTR) || (res == ERESTART))
284*262f27b2SOleksandr Tymoshenko 		res = -ERESTART;
285*262f27b2SOleksandr Tymoshenko 	return res;
286*262f27b2SOleksandr Tymoshenko }
287*262f27b2SOleksandr Tymoshenko 
288*262f27b2SOleksandr Tymoshenko int
289*262f27b2SOleksandr Tymoshenko wait_for_completion_killable(struct completion *c)
290*262f27b2SOleksandr Tymoshenko {
291*262f27b2SOleksandr Tymoshenko 
292*262f27b2SOleksandr Tymoshenko 	return wait_for_completion_interruptible(c);
293*262f27b2SOleksandr Tymoshenko }
294*262f27b2SOleksandr Tymoshenko 
295*262f27b2SOleksandr Tymoshenko /*
296*262f27b2SOleksandr Tymoshenko  * Semaphore API
297*262f27b2SOleksandr Tymoshenko  */
298*262f27b2SOleksandr Tymoshenko 
299*262f27b2SOleksandr Tymoshenko void sema_sysinit(void *arg)
300*262f27b2SOleksandr Tymoshenko {
301*262f27b2SOleksandr Tymoshenko 	struct semaphore *s = arg;
302*262f27b2SOleksandr Tymoshenko 
303*262f27b2SOleksandr Tymoshenko 	printf("sema_sysinit\n");
304*262f27b2SOleksandr Tymoshenko 	_sema_init(s, 1);
305*262f27b2SOleksandr Tymoshenko }
306*262f27b2SOleksandr Tymoshenko 
307*262f27b2SOleksandr Tymoshenko void
308*262f27b2SOleksandr Tymoshenko _sema_init(struct semaphore *s, int value)
309*262f27b2SOleksandr Tymoshenko {
310*262f27b2SOleksandr Tymoshenko 	bzero(s, sizeof(*s));
311*262f27b2SOleksandr Tymoshenko 	mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
312*262f27b2SOleksandr Tymoshenko 		MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
313*262f27b2SOleksandr Tymoshenko 	cv_init(&s->cv, "sema cv");
314*262f27b2SOleksandr Tymoshenko 	s->value = value;
315*262f27b2SOleksandr Tymoshenko }
316*262f27b2SOleksandr Tymoshenko 
317*262f27b2SOleksandr Tymoshenko void
318*262f27b2SOleksandr Tymoshenko _sema_destroy(struct semaphore *s)
319*262f27b2SOleksandr Tymoshenko {
320*262f27b2SOleksandr Tymoshenko 	mtx_destroy(&s->mtx);
321*262f27b2SOleksandr Tymoshenko 	cv_destroy(&s->cv);
322*262f27b2SOleksandr Tymoshenko }
323*262f27b2SOleksandr Tymoshenko 
324*262f27b2SOleksandr Tymoshenko void
325*262f27b2SOleksandr Tymoshenko down(struct semaphore *s)
326*262f27b2SOleksandr Tymoshenko {
327*262f27b2SOleksandr Tymoshenko 
328*262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
329*262f27b2SOleksandr Tymoshenko 	while (s->value == 0) {
330*262f27b2SOleksandr Tymoshenko 		s->waiters++;
331*262f27b2SOleksandr Tymoshenko 		cv_wait(&s->cv, &s->mtx);
332*262f27b2SOleksandr Tymoshenko 		s->waiters--;
333*262f27b2SOleksandr Tymoshenko 	}
334*262f27b2SOleksandr Tymoshenko 
335*262f27b2SOleksandr Tymoshenko 	s->value--;
336*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
337*262f27b2SOleksandr Tymoshenko }
338*262f27b2SOleksandr Tymoshenko 
339*262f27b2SOleksandr Tymoshenko int
340*262f27b2SOleksandr Tymoshenko down_interruptible(struct semaphore *s)
341*262f27b2SOleksandr Tymoshenko {
342*262f27b2SOleksandr Tymoshenko 	int ret ;
343*262f27b2SOleksandr Tymoshenko 
344*262f27b2SOleksandr Tymoshenko 	ret = 0;
345*262f27b2SOleksandr Tymoshenko 
346*262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
347*262f27b2SOleksandr Tymoshenko 
348*262f27b2SOleksandr Tymoshenko 	while (s->value == 0) {
349*262f27b2SOleksandr Tymoshenko 		s->waiters++;
350*262f27b2SOleksandr Tymoshenko 		ret = cv_wait_sig(&s->cv, &s->mtx);
351*262f27b2SOleksandr Tymoshenko 		s->waiters--;
352*262f27b2SOleksandr Tymoshenko 
353*262f27b2SOleksandr Tymoshenko 		if (ret == EINTR) {
354*262f27b2SOleksandr Tymoshenko 			mtx_unlock(&s->mtx);
355*262f27b2SOleksandr Tymoshenko 			return (-EINTR);
356*262f27b2SOleksandr Tymoshenko 		}
357*262f27b2SOleksandr Tymoshenko 
358*262f27b2SOleksandr Tymoshenko 		if (ret == ERESTART)
359*262f27b2SOleksandr Tymoshenko 			continue;
360*262f27b2SOleksandr Tymoshenko 	}
361*262f27b2SOleksandr Tymoshenko 
362*262f27b2SOleksandr Tymoshenko 	s->value--;
363*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
364*262f27b2SOleksandr Tymoshenko 
365*262f27b2SOleksandr Tymoshenko 	return (0);
366*262f27b2SOleksandr Tymoshenko }
367*262f27b2SOleksandr Tymoshenko 
368*262f27b2SOleksandr Tymoshenko int
369*262f27b2SOleksandr Tymoshenko down_trylock(struct semaphore *s)
370*262f27b2SOleksandr Tymoshenko {
371*262f27b2SOleksandr Tymoshenko 	int ret;
372*262f27b2SOleksandr Tymoshenko 
373*262f27b2SOleksandr Tymoshenko 	ret = 0;
374*262f27b2SOleksandr Tymoshenko 
375*262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
376*262f27b2SOleksandr Tymoshenko 
377*262f27b2SOleksandr Tymoshenko 	if (s->value > 0) {
378*262f27b2SOleksandr Tymoshenko 		/* Success. */
379*262f27b2SOleksandr Tymoshenko 		s->value--;
380*262f27b2SOleksandr Tymoshenko 		ret = 0;
381*262f27b2SOleksandr Tymoshenko 	} else {
382*262f27b2SOleksandr Tymoshenko 		ret = -EAGAIN;
383*262f27b2SOleksandr Tymoshenko 	}
384*262f27b2SOleksandr Tymoshenko 
385*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
386*262f27b2SOleksandr Tymoshenko 
387*262f27b2SOleksandr Tymoshenko 	return (ret);
388*262f27b2SOleksandr Tymoshenko }
389*262f27b2SOleksandr Tymoshenko 
390*262f27b2SOleksandr Tymoshenko void
391*262f27b2SOleksandr Tymoshenko up(struct semaphore *s)
392*262f27b2SOleksandr Tymoshenko {
393*262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
394*262f27b2SOleksandr Tymoshenko 	s->value++;
395*262f27b2SOleksandr Tymoshenko 	if (s->waiters && s->value > 0)
396*262f27b2SOleksandr Tymoshenko 		cv_signal(&s->cv);
397*262f27b2SOleksandr Tymoshenko 
398*262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
399*262f27b2SOleksandr Tymoshenko }
400*262f27b2SOleksandr Tymoshenko 
401*262f27b2SOleksandr Tymoshenko /*
402*262f27b2SOleksandr Tymoshenko  * Logging API
403*262f27b2SOleksandr Tymoshenko  */
404*262f27b2SOleksandr Tymoshenko void
405*262f27b2SOleksandr Tymoshenko rlprintf(int pps, const char *fmt, ...)
406*262f27b2SOleksandr Tymoshenko {
407*262f27b2SOleksandr Tymoshenko 	va_list ap;
408*262f27b2SOleksandr Tymoshenko 	static struct timeval last_printf;
409*262f27b2SOleksandr Tymoshenko 	static int count;
410*262f27b2SOleksandr Tymoshenko 
411*262f27b2SOleksandr Tymoshenko 	if (ppsratecheck(&last_printf, &count, pps)) {
412*262f27b2SOleksandr Tymoshenko 		va_start(ap, fmt);
413*262f27b2SOleksandr Tymoshenko 		vprintf(fmt, ap);
414*262f27b2SOleksandr Tymoshenko 		va_end(ap);
415*262f27b2SOleksandr Tymoshenko 	}
416*262f27b2SOleksandr Tymoshenko }
417*262f27b2SOleksandr Tymoshenko 
418*262f27b2SOleksandr Tymoshenko void
419*262f27b2SOleksandr Tymoshenko device_rlprintf(int pps, device_t dev, const char *fmt, ...)
420*262f27b2SOleksandr Tymoshenko {
421*262f27b2SOleksandr Tymoshenko 	va_list ap;
422*262f27b2SOleksandr Tymoshenko 	static struct timeval last_printf;
423*262f27b2SOleksandr Tymoshenko 	static int count;
424*262f27b2SOleksandr Tymoshenko 
425*262f27b2SOleksandr Tymoshenko 	if (ppsratecheck(&last_printf, &count, pps)) {
426*262f27b2SOleksandr Tymoshenko 		va_start(ap, fmt);
427*262f27b2SOleksandr Tymoshenko 		device_print_prettyname(dev);
428*262f27b2SOleksandr Tymoshenko 		vprintf(fmt, ap);
429*262f27b2SOleksandr Tymoshenko 		va_end(ap);
430*262f27b2SOleksandr Tymoshenko 	}
431*262f27b2SOleksandr Tymoshenko }
432*262f27b2SOleksandr Tymoshenko 
433*262f27b2SOleksandr Tymoshenko /*
434*262f27b2SOleksandr Tymoshenko  * Signals API
435*262f27b2SOleksandr Tymoshenko  */
436*262f27b2SOleksandr Tymoshenko 
437*262f27b2SOleksandr Tymoshenko void
438*262f27b2SOleksandr Tymoshenko flush_signals(VCHIQ_THREAD_T thr)
439*262f27b2SOleksandr Tymoshenko {
440*262f27b2SOleksandr Tymoshenko 	printf("Implement ME: %s\n", __func__);
441*262f27b2SOleksandr Tymoshenko }
442*262f27b2SOleksandr Tymoshenko 
443*262f27b2SOleksandr Tymoshenko int
444*262f27b2SOleksandr Tymoshenko fatal_signal_pending(VCHIQ_THREAD_T thr)
445*262f27b2SOleksandr Tymoshenko {
446*262f27b2SOleksandr Tymoshenko 	printf("Implement ME: %s\n", __func__);
447*262f27b2SOleksandr Tymoshenko 	return (0);
448*262f27b2SOleksandr Tymoshenko }
449*262f27b2SOleksandr Tymoshenko 
450*262f27b2SOleksandr Tymoshenko /*
451*262f27b2SOleksandr Tymoshenko  * kthread API
452*262f27b2SOleksandr Tymoshenko  */
453*262f27b2SOleksandr Tymoshenko 
454*262f27b2SOleksandr Tymoshenko /*
455*262f27b2SOleksandr Tymoshenko  *  This is a hack to avoid memory leak
456*262f27b2SOleksandr Tymoshenko  */
457*262f27b2SOleksandr Tymoshenko #define MAX_THREAD_DATA_SLOTS	32
458*262f27b2SOleksandr Tymoshenko static int thread_data_slot = 0;
459*262f27b2SOleksandr Tymoshenko 
460*262f27b2SOleksandr Tymoshenko struct thread_data {
461*262f27b2SOleksandr Tymoshenko 	void *data;
462*262f27b2SOleksandr Tymoshenko 	int (*threadfn)(void *);
463*262f27b2SOleksandr Tymoshenko };
464*262f27b2SOleksandr Tymoshenko 
465*262f27b2SOleksandr Tymoshenko static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
466*262f27b2SOleksandr Tymoshenko 
467*262f27b2SOleksandr Tymoshenko static void
468*262f27b2SOleksandr Tymoshenko kthread_wrapper(void *data)
469*262f27b2SOleksandr Tymoshenko {
470*262f27b2SOleksandr Tymoshenko 	struct thread_data *slot;
471*262f27b2SOleksandr Tymoshenko 
472*262f27b2SOleksandr Tymoshenko 	slot = data;
473*262f27b2SOleksandr Tymoshenko 	slot->threadfn(slot->data);
474*262f27b2SOleksandr Tymoshenko }
475*262f27b2SOleksandr Tymoshenko 
476*262f27b2SOleksandr Tymoshenko VCHIQ_THREAD_T
477*262f27b2SOleksandr Tymoshenko vchiq_thread_create(int (*threadfn)(void *data),
478*262f27b2SOleksandr Tymoshenko 	void *data,
479*262f27b2SOleksandr Tymoshenko 	const char namefmt[], ...)
480*262f27b2SOleksandr Tymoshenko {
481*262f27b2SOleksandr Tymoshenko 	VCHIQ_THREAD_T newp;
482*262f27b2SOleksandr Tymoshenko 	va_list ap;
483*262f27b2SOleksandr Tymoshenko 	char name[MAXCOMLEN+1];
484*262f27b2SOleksandr Tymoshenko 	struct thread_data *slot;
485*262f27b2SOleksandr Tymoshenko 
486*262f27b2SOleksandr Tymoshenko 	if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
487*262f27b2SOleksandr Tymoshenko 		printf("kthread_create: out of thread data slots\n");
488*262f27b2SOleksandr Tymoshenko 		return (NULL);
489*262f27b2SOleksandr Tymoshenko 	}
490*262f27b2SOleksandr Tymoshenko 
491*262f27b2SOleksandr Tymoshenko 	slot = &thread_slots[thread_data_slot];
492*262f27b2SOleksandr Tymoshenko 	slot->data = data;
493*262f27b2SOleksandr Tymoshenko 	slot->threadfn = threadfn;
494*262f27b2SOleksandr Tymoshenko 
495*262f27b2SOleksandr Tymoshenko 	va_start(ap, namefmt);
496*262f27b2SOleksandr Tymoshenko 	vsnprintf(name, sizeof(name), namefmt, ap);
497*262f27b2SOleksandr Tymoshenko 	va_end(ap);
498*262f27b2SOleksandr Tymoshenko 
499*262f27b2SOleksandr Tymoshenko 	newp = NULL;
500*262f27b2SOleksandr Tymoshenko 	if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
501*262f27b2SOleksandr Tymoshenko 	    "%s", name) != 0) {
502*262f27b2SOleksandr Tymoshenko 		/* Just to be sure */
503*262f27b2SOleksandr Tymoshenko 		newp = NULL;
504*262f27b2SOleksandr Tymoshenko 	}
505*262f27b2SOleksandr Tymoshenko 	else
506*262f27b2SOleksandr Tymoshenko 		thread_data_slot++;
507*262f27b2SOleksandr Tymoshenko 
508*262f27b2SOleksandr Tymoshenko 	return newp;
509*262f27b2SOleksandr Tymoshenko }
510*262f27b2SOleksandr Tymoshenko 
511*262f27b2SOleksandr Tymoshenko void
512*262f27b2SOleksandr Tymoshenko set_user_nice(VCHIQ_THREAD_T thr, int nice)
513*262f27b2SOleksandr Tymoshenko {
514*262f27b2SOleksandr Tymoshenko 	/* NOOP */
515*262f27b2SOleksandr Tymoshenko }
516*262f27b2SOleksandr Tymoshenko 
517*262f27b2SOleksandr Tymoshenko void
518*262f27b2SOleksandr Tymoshenko wake_up_process(VCHIQ_THREAD_T thr)
519*262f27b2SOleksandr Tymoshenko {
520*262f27b2SOleksandr Tymoshenko 	/* NOOP */
521*262f27b2SOleksandr Tymoshenko }
522*262f27b2SOleksandr Tymoshenko 
523*262f27b2SOleksandr Tymoshenko void
524*262f27b2SOleksandr Tymoshenko bcm_mbox_write(int channel, uint32_t data)
525*262f27b2SOleksandr Tymoshenko {
526*262f27b2SOleksandr Tymoshenko 	device_t mbox;
527*262f27b2SOleksandr Tymoshenko 
528*262f27b2SOleksandr Tymoshenko         mbox = devclass_get_device(devclass_find("mbox"), 0);
529*262f27b2SOleksandr Tymoshenko 
530*262f27b2SOleksandr Tymoshenko         if (mbox)
531*262f27b2SOleksandr Tymoshenko                 MBOX_WRITE(mbox, channel, data);
532*262f27b2SOleksandr Tymoshenko }
533