Annotation of prex-old/sys/sync/cond.c, Revision 1.1
1.1 ! nbrk 1: /*-
! 2: * Copyright (c) 2005-2007, Kohsuke Ohtani
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. Neither the name of the author nor the names of any co-contributors
! 14: * may be used to endorse or promote products derived from this software
! 15: * without specific prior written permission.
! 16: *
! 17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 27: * SUCH DAMAGE.
! 28: */
! 29:
! 30: /*
! 31: * cond.c - condition variable object
! 32: */
! 33:
! 34: #include <kernel.h>
! 35: #include <sched.h>
! 36: #include <kmem.h>
! 37: #include <thread.h>
! 38: #include <sync.h>
! 39:
! 40: /*
! 41: * Create and initialize a condition variable (CV).
! 42: *
! 43: * If an initialized condition variable is reinitialized, undefined
! 44: * behavior results.
! 45: */
! 46: int
! 47: cond_init(cond_t *cond)
! 48: {
! 49: cond_t c;
! 50:
! 51: if ((c = kmem_alloc(sizeof(struct cond))) == NULL)
! 52: return ENOMEM;
! 53:
! 54: event_init(&c->event, "condition");
! 55: c->task = cur_task();
! 56: c->magic = COND_MAGIC;
! 57:
! 58: if (umem_copyout(&c, cond, sizeof(cond_t))) {
! 59: kmem_free(c);
! 60: return EFAULT;
! 61: }
! 62: return 0;
! 63: }
! 64:
! 65: /*
! 66: * cond_copyin - copy a condition variable from user space.
! 67: * @uc: pointer to cv in user space.
! 68: * @kc: pointer to cv in kernel space.
! 69: *
! 70: * It also checks if the passed CV is valid.
! 71: */
! 72: static int
! 73: cond_copyin(cond_t *ucond, cond_t *kcond)
! 74: {
! 75: cond_t c;
! 76:
! 77: if (umem_copyin(ucond, &c, sizeof(cond_t)))
! 78: return EFAULT;
! 79: if (!cond_valid(c))
! 80: return EINVAL;
! 81: *kcond = c;
! 82: return 0;
! 83: }
! 84:
! 85: /*
! 86: * Destroy a condition variable.
! 87: * If there are any blocked thread waiting for the specified CV,
! 88: * it returns EBUSY.
! 89: */
! 90: int
! 91: cond_destroy(cond_t *cond)
! 92: {
! 93: cond_t c;
! 94: int err;
! 95:
! 96: sched_lock();
! 97: if ((err = cond_copyin(cond, &c))) {
! 98: sched_unlock();
! 99: return err;
! 100: }
! 101: if (event_waiting(&c->event)) {
! 102: sched_unlock();
! 103: return EBUSY;
! 104: }
! 105: c->magic = 0;
! 106: kmem_free(c);
! 107: sched_unlock();
! 108: return 0;
! 109: }
! 110:
! 111: /*
! 112: * Wait on a condition.
! 113: *
! 114: * If the thread receives any exception while waiting CV, this
! 115: * routine returns immediately with EINTR in order to invoke
! 116: * exception handler. However, an application assumes this call
! 117: * does NOT return with an error. So, the stub routine in a system
! 118: * call library must call cond_wait() again if it gets EINTR as error.
! 119: */
! 120: int
! 121: cond_wait(cond_t *cond, mutex_t *mtx)
! 122: {
! 123: cond_t c;
! 124: int err, rc;
! 125:
! 126: if (umem_copyin(cond, &c, sizeof(cond_t)))
! 127: return EFAULT;
! 128:
! 129: sched_lock();
! 130: if (c == COND_INITIALIZER) {
! 131: if ((err = cond_init(cond))) {
! 132: sched_unlock();
! 133: return err;
! 134: }
! 135: umem_copyin(cond, &c, sizeof(cond_t));
! 136: } else {
! 137: if (!cond_valid(c)) {
! 138: sched_unlock();
! 139: return EINVAL;
! 140: }
! 141: }
! 142: if ((err = mutex_unlock(mtx))) {
! 143: sched_unlock();
! 144: return err;
! 145: }
! 146:
! 147: rc = sched_sleep(&c->event);
! 148: if (rc == SLP_INTR)
! 149: err = EINTR;
! 150: sched_unlock();
! 151:
! 152: if (err == 0)
! 153: err = mutex_lock(mtx);
! 154: return err;
! 155: }
! 156:
! 157: /*
! 158: * Unblock one thread that is blocked on the specified CV.
! 159: * The thread which has highest priority will be unblocked.
! 160: */
! 161: int
! 162: cond_signal(cond_t *cond)
! 163: {
! 164: cond_t c;
! 165: int err;
! 166:
! 167: sched_lock();
! 168: if ((err = cond_copyin(cond, &c)) == 0)
! 169: sched_wakeone(&c->event);
! 170: sched_unlock();
! 171: return err;
! 172: }
! 173:
! 174: /*
! 175: * Unblock all threads that are blocked on the specified CV.
! 176: */
! 177: int
! 178: cond_broadcast(cond_t *cond)
! 179: {
! 180: cond_t c;
! 181: int err;
! 182:
! 183: sched_lock();
! 184: if ((err = cond_copyin(cond, &c)) == 0)
! 185: sched_wakeup(&c->event);
! 186: sched_unlock();
! 187: return err;
! 188: }
CVSweb