semaphore.c revision 6304d8b21891fd0cb7b5a4c25159a3d3b1709d62
11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the documentation and/or other materials provided with the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <semaphore.h> 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <errno.h> 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/time.h> 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <sys/atomics.h> 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <time.h> 33fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden#include <cutils/atomic-inline.h> 346304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner#include <bionic_futex.h> 356304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 366304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner/* Use the lower 31-bits for the counter, and the high bit for 376304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner * the shared flag. 386304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner */ 396304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner#define SEM_VALUE_MASK 0x7fffffff 406304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner#define SEM_SHARED_MASK 0x80000000 416304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 426304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner#define SEM_GET_SHARED(sem) ((sem)->count & SEM_SHARED_MASK) 436304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner#define SEM_GET_VALUE(sem) ((sem)->count & SEM_VALUE_MASK) 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_init(sem_t *sem, int pshared, unsigned int value) 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 526304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner /* ensure that 'value' can be stored in the semaphore */ 536304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if ((value & SEM_VALUE_MASK) != value) { 546304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner errno = EINVAL; 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project sem->count = value; 596304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (pshared != 0) 606304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner sem->count |= SEM_SHARED_MASK; 616304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_destroy(sem_t *sem) 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 726304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if ((sem->count & SEM_VALUE_MASK) == 0) { 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EBUSY; 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 766304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner sem->count = 0; 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectsem_t *sem_open(const char *name, int oflag, ...) 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project name=name; 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project oflag=oflag; 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOSYS; 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return SEM_FAILED; 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_close(sem_t *sem) 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 951dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 961dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOSYS; 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_unlink(const char * name) 1031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ENOSYS; 1051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 1061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1096304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner/* Return 0 if a semaphore's value is 0 1106304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner * Otherwise, decrement the value and return the old value. 1116304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner */ 1121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic int 1136304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner__sem_dec_if_positive(volatile unsigned int *pvalue) 1141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1156304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned int shared = (*pvalue & SEM_SHARED_MASK); 1161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int old; 1171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project do { 1196304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner old = (*pvalue & SEM_VALUE_MASK); 1201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1216304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner while ( old != 0 && 1226304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner __atomic_cmpxchg((int)(old|shared), 1236304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner (int)((old-1)|shared), 1246304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner (volatile int*)pvalue) != 0 ); 1256304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 1266304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner return old; 1276304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner} 1286304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 1296304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner/* Increment the value of a semaphore atomically. 1306304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner * NOTE: the value will wrap above SEM_VALUE_MASK 1316304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner */ 1326304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turnerstatic int 1336304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner__sem_inc(volatile unsigned int *pvalue) 1346304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner{ 1356304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned int shared = (*pvalue & SEM_SHARED_MASK); 1366304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned int old; 1371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1386304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner do { 1396304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner old = (*pvalue & SEM_VALUE_MASK); 1406304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner } while ( __atomic_cmpxchg((int)(old|shared), 1416304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner (int)(((old+1)&SEM_VALUE_MASK)|shared), 1426304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner (volatile int*)pvalue) != 0); 1431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return old; 1441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 146fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden/* lock a semaphore */ 1471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_wait(sem_t *sem) 1481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1496304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned shared; 1506304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 1511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 1521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 1531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 1541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1566304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner shared = SEM_GET_SHARED(sem); 1576304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 1581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (;;) { 1596304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (__sem_dec_if_positive(&sem->count)) 1601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 1611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1626304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner __futex_wait_ex(&sem->count, shared, shared, NULL); 1631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 164fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden ANDROID_MEMBAR_FULL(); 1651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 1661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 1671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) 1691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 1701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int ret; 1716304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned int shared; 1721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 1741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 1751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 1761dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* POSIX says we need to try to decrement the semaphore 1791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * before checking the timeout value */ 1806304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (__sem_dec_if_positive(&sem->count)) { 181fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden ANDROID_MEMBAR_FULL(); 1821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 183fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden } 1841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* check it as per Posix */ 1861dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (abs_timeout == NULL || 1871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abs_timeout->tv_sec < 0 || 1881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abs_timeout->tv_nsec < 0 || 1891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project abs_timeout->tv_nsec >= 1000000000) 1901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 1911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 1921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 1931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 1941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1956304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner shared = SEM_GET_SHARED(sem); 1966304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 1971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project for (;;) { 1981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project struct timespec ts; 1991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int ret; 2001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* Posix mandates CLOCK_REALTIME here */ 2021dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project clock_gettime( CLOCK_REALTIME, &ts ); 2031dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ts.tv_sec = abs_timeout->tv_sec - ts.tv_sec; 2041dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ts.tv_nsec = abs_timeout->tv_nsec - ts.tv_nsec; 2051dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ts.tv_nsec < 0) { 2061dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ts.tv_nsec += 1000000000; 2071dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ts.tv_sec -= 1; 2081dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2091dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ts.tv_sec < 0 || ts.tv_nsec < 0) { 2111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = ETIMEDOUT; 2121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 2131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2156304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner ret = __futex_wait_ex(&sem->count, shared, shared, &ts); 2161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* return in case of timeout or interrupt */ 2181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (ret == -ETIMEDOUT || ret == -EINTR) { 2191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = -ret; 2201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 2211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2236304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (__sem_dec_if_positive(&sem->count)) { 224fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden ANDROID_MEMBAR_FULL(); 2251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project break; 226fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden } 2271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 2291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 231fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden/* unlock a semaphore */ 2321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_post(sem_t *sem) 2331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2346304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner unsigned int shared; 2356304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 2361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) 2371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return EINVAL; 2381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2396304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner shared = SEM_GET_SHARED(sem); 2406304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner 241fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden ANDROID_MEMBAR_FULL(); 2426304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (__sem_inc(&sem->count) >= 0) 2436304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner __futex_wake_ex(&sem->count, shared, 1); 2441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 2461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_trywait(sem_t *sem) 2491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL) { 2511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 2521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 2531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2556304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner if (__sem_dec_if_positive(&sem->count) > 0) { 256fcd00ebbdf3e7f4e1e7782a65ae10fb0fc03a1aaAndy McFadden ANDROID_MEMBAR_FULL(); 2571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 2581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } else { 259294dd0b86b1484aec7549663aff5b19c98a4b7fdDavid 'Digit' Turner errno = EAGAIN; 260294dd0b86b1484aec7549663aff5b19c98a4b7fdDavid 'Digit' Turner return -1; 2611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 2631dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2641dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint sem_getvalue(sem_t *sem, int *sval) 2651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 2661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (sem == NULL || sval == NULL) { 2671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project errno = EINVAL; 2681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 2691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 2701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 2716304d8b21891fd0cb7b5a4c25159a3d3b1709d62David 'Digit' Turner *sval = SEM_GET_VALUE(sem); 2721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 2731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 274