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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 511262f27b2SOleksandr Tymoshenko set_user_nice(VCHIQ_THREAD_T thr, int nice) 512262f27b2SOleksandr Tymoshenko { 513262f27b2SOleksandr Tymoshenko /* NOOP */ 514262f27b2SOleksandr Tymoshenko } 515262f27b2SOleksandr Tymoshenko 516262f27b2SOleksandr Tymoshenko void 517262f27b2SOleksandr Tymoshenko wake_up_process(VCHIQ_THREAD_T thr) 518262f27b2SOleksandr Tymoshenko { 519262f27b2SOleksandr Tymoshenko /* NOOP */ 520262f27b2SOleksandr Tymoshenko } 521262f27b2SOleksandr Tymoshenko 522262f27b2SOleksandr Tymoshenko void 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