summaryrefslogtreecommitdiffstats
path: root/libc/bionic
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:55 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-20 14:03:55 -0800
commitd37527501c85edcb3a6a7c8a0b6297d52d434897 (patch)
treef005d945ce90569b8e63cf42294ab42dddab52c2 /libc/bionic
parente5cc1f386b167b9f7bfdebc7219e89aa9b71e4b2 (diff)
downloadbionic-d37527501c85edcb3a6a7c8a0b6297d52d434897.zip
bionic-d37527501c85edcb3a6a7c8a0b6297d52d434897.tar.gz
bionic-d37527501c85edcb3a6a7c8a0b6297d52d434897.tar.bz2
auto import from //branches/cupcake/...@127101
Diffstat (limited to 'libc/bionic')
-rw-r--r--libc/bionic/pthread-timers.c23
-rw-r--r--libc/bionic/semaphore.c57
2 files changed, 74 insertions, 6 deletions
diff --git a/libc/bionic/pthread-timers.c b/libc/bionic/pthread-timers.c
index a53d04b..b8f7488 100644
--- a/libc/bionic/pthread-timers.c
+++ b/libc/bionic/pthread-timers.c
@@ -144,6 +144,9 @@ thr_timer_table_alloc( thr_timer_table_t* t )
{
thr_timer_t* timer;
+ if (t == NULL)
+ return NULL;
+
pthread_mutex_lock(&t->lock);
timer = t->free_timer;
if (timer != NULL) {
@@ -201,7 +204,7 @@ thr_timer_table_from_id( thr_timer_table_t* t,
unsigned index;
thr_timer_t* timer;
- if (!TIMER_ID_IS_WRAPPED(id))
+ if (t == NULL || !TIMER_ID_IS_WRAPPED(id))
return NULL;
index = (unsigned) TIMER_ID_UNWRAP(id);
@@ -226,15 +229,21 @@ thr_timer_table_from_id( thr_timer_table_t* t,
return timer;
}
-/* the static timer table */
+/* the static timer table - we only create it if the process
+ * really wants to use SIGEV_THREAD timers, which should be
+ * pretty infrequent
+ */
static pthread_once_t __timer_table_once = PTHREAD_ONCE_INIT;
-static thr_timer_table_t __timer_table[1];
+static thr_timer_table_t* __timer_table;
static void
__timer_table_init( void )
{
- thr_timer_table_init( __timer_table );
+ __timer_table = calloc(1,sizeof(*__timer_table));
+
+ if (__timer_table != NULL)
+ thr_timer_table_init( __timer_table );
}
static thr_timer_table_t*
@@ -254,8 +263,10 @@ __timer_table_get(void)
void
__timer_table_start_stop( int stop )
{
- thr_timer_table_t* table = __timer_table_get();
- thr_timer_table_start_stop(table, stop);
+ if (__timer_table != NULL) {
+ thr_timer_table_t* table = __timer_table_get();
+ thr_timer_table_start_stop(table, stop);
+ }
}
static thr_timer_t*
diff --git a/libc/bionic/semaphore.c b/libc/bionic/semaphore.c
index fa9de0e..0c94600 100644
--- a/libc/bionic/semaphore.c
+++ b/libc/bionic/semaphore.c
@@ -29,6 +29,7 @@
#include <errno.h>
#include <sys/time.h>
#include <sys/atomics.h>
+#include <time.h>
int sem_init(sem_t *sem, int pshared, unsigned int value)
{
@@ -118,6 +119,62 @@ int sem_wait(sem_t *sem)
return 0;
}
+int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout)
+{
+ int ret;
+
+ if (sem == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* POSIX says we need to try to decrement the semaphore
+ * before checking the timeout value */
+ if (__atomic_dec_if_positive(&sem->count))
+ return 0;
+
+ /* check it as per Posix */
+ if (abs_timeout == NULL ||
+ abs_timeout->tv_sec < 0 ||
+ abs_timeout->tv_nsec < 0 ||
+ abs_timeout->tv_nsec >= 1000000000)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (;;) {
+ struct timespec ts;
+ int ret;
+
+ /* Posix mandates CLOCK_REALTIME here */
+ clock_gettime( CLOCK_REALTIME, &ts );
+ ts.tv_sec = abs_timeout->tv_sec - ts.tv_sec;
+ ts.tv_nsec = abs_timeout->tv_nsec - ts.tv_nsec;
+ if (ts.tv_nsec < 0) {
+ ts.tv_nsec += 1000000000;
+ ts.tv_sec -= 1;
+ }
+
+ if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
+ errno = ETIMEDOUT;
+ return -1;
+ }
+
+ ret = __futex_wait(&sem->count, 0, &ts);
+
+ /* return in case of timeout or interrupt */
+ if (ret == -ETIMEDOUT || ret == -EINTR) {
+ errno = -ret;
+ return -1;
+ }
+
+ if (__atomic_dec_if_positive(&sem->count))
+ break;
+ }
+ return 0;
+}
+
int sem_post(sem_t *sem)
{
if (sem == NULL)