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