semaphore.c revision a27d2baa0c1a2ec70f47ea9199b1dd6762c8a349
1/* 2 * Copyright (C) 2008 The Android Open Source Project 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 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28#include <semaphore.h> 29#include <errno.h> 30#include <sys/time.h> 31#include <sys/atomics.h> 32 33int sem_init(sem_t *sem, int pshared, unsigned int value) 34{ 35 if (sem == NULL) { 36 errno = EINVAL; 37 return -1; 38 } 39 40 if (pshared != 0) { 41 errno = ENOSYS; 42 return -1; 43 } 44 45 sem->count = value; 46 return 0; 47} 48 49 50int sem_destroy(sem_t *sem) 51{ 52 if (sem == NULL) { 53 errno = EINVAL; 54 return -1; 55 } 56 if (sem->count == 0) { 57 errno = EBUSY; 58 return -1; 59 } 60 return 0; 61} 62 63 64sem_t *sem_open(const char *name, int oflag, ...) 65{ 66 name=name; 67 oflag=oflag; 68 69 errno = ENOSYS; 70 return SEM_FAILED; 71} 72 73 74int sem_close(sem_t *sem) 75{ 76 if (sem == NULL) { 77 errno = EINVAL; 78 return -1; 79 } 80 errno = ENOSYS; 81 return -1; 82} 83 84 85int sem_unlink(const char * name) 86{ 87 errno = ENOSYS; 88 return -1; 89} 90 91 92static int 93__atomic_dec_if_positive( volatile unsigned int* pvalue ) 94{ 95 unsigned int old; 96 97 do { 98 old = *pvalue; 99 } 100 while ( old != 0 && __atomic_cmpxchg( (int)old, (int)old-1, (volatile int*)pvalue ) != 0 ); 101 102 return old; 103} 104 105int sem_wait(sem_t *sem) 106{ 107 if (sem == NULL) { 108 errno = EINVAL; 109 return -1; 110 } 111 112 for (;;) { 113 if (__atomic_dec_if_positive(&sem->count)) 114 break; 115 116 __futex_wait(&sem->count, 0, 0); 117 } 118 return 0; 119} 120 121int sem_post(sem_t *sem) 122{ 123 if (sem == NULL) 124 return EINVAL; 125 126 if (__atomic_inc((volatile int*)&sem->count) == 0) 127 __futex_wake(&sem->count, 1); 128 129 return 0; 130} 131 132int sem_trywait(sem_t *sem) 133{ 134 if (sem == NULL) { 135 errno = EINVAL; 136 return -1; 137 } 138 139 if (__atomic_dec_if_positive(&sem->count) > 0) { 140 return 0; 141 } else { 142 return EAGAIN; 143 } 144} 145 146int sem_getvalue(sem_t *sem, int *sval) 147{ 148 if (sem == NULL || sval == NULL) { 149 errno = EINVAL; 150 return -1; 151 } 152 153 *sval = sem->count; 154 return 0; 155} 156