summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2011-03-30 13:04:55 -0400
committerRich Felker <dalias@aerifal.cx>2011-03-30 13:04:55 -0400
commit3990c5c6a40440cdb14746ac080d0ecf8d5d6733 (patch)
treeb20dd1257972fdbe84202e9b6c913e90c1fa1d54
parentb8be64c43da207a2f497c1c5b5720e4a2027348a (diff)
downloadmusl-3990c5c6a40440cdb14746ac080d0ecf8d5d6733.tar.gz
avoid all malloc/free in timer creation/destruction
instead of allocating a userspace structure for signal-based timers, simply use the kernel timer id. we use the fact that thread pointers will always be zero in the low bit (actually more) to encode integer timerid values as pointers. also, this change ensures that the timer_destroy syscall has completed before the library timer_destroy function returns, in case it matters.
-rwxr-xr-xarch/i386/bits/alltypes.h.sh2
-rwxr-xr-xarch/x86_64/bits/alltypes.h.sh2
-rw-r--r--src/time/timer_create.c24
-rw-r--r--src/time/timer_delete.c13
-rw-r--r--src/time/timer_getoverrun.c4
-rw-r--r--src/time/timer_gettime.c4
-rw-r--r--src/time/timer_settime.c4
7 files changed, 22 insertions, 31 deletions
diff --git a/arch/i386/bits/alltypes.h.sh b/arch/i386/bits/alltypes.h.sh
index 13658cc2..c6201b9d 100755
--- a/arch/i386/bits/alltypes.h.sh
+++ b/arch/i386/bits/alltypes.h.sh
@@ -107,7 +107,7 @@ TYPEDEF long long blkcnt_t;
TYPEDEF unsigned long long fsblkcnt_t;
TYPEDEF unsigned long long fsfilcnt_t;
-TYPEDEF struct __timer * timer_t;
+TYPEDEF void * timer_t;
TYPEDEF int clockid_t;
TYPEDEF unsigned long clock_t;
diff --git a/arch/x86_64/bits/alltypes.h.sh b/arch/x86_64/bits/alltypes.h.sh
index cd84a2da..b0aecd9c 100755
--- a/arch/x86_64/bits/alltypes.h.sh
+++ b/arch/x86_64/bits/alltypes.h.sh
@@ -107,7 +107,7 @@ TYPEDEF long long blkcnt_t;
TYPEDEF unsigned long long fsblkcnt_t;
TYPEDEF unsigned long long fsfilcnt_t;
-TYPEDEF struct __timer * timer_t;
+TYPEDEF void * timer_t;
TYPEDEF int clockid_t;
TYPEDEF long clock_t;
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index 89099dd6..c5894f48 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -11,7 +11,6 @@ struct ksigevent {
struct start_args {
pthread_barrier_t b;
struct sigevent *sev;
- timer_t t;
};
static void sighandler(int sig, siginfo_t *si, void *ctx)
@@ -26,30 +25,21 @@ static void sighandler(int sig, siginfo_t *si, void *ctx)
pthread_setcancelstate(st, 0);
}
-static void killtimer(void *arg)
-{
- timer_t t = arg;
- if (t->timerid >= 0) __syscall(SYS_timer_delete, t->timerid);
-}
-
static void *start(void *arg)
{
pthread_t self = __pthread_self();
struct start_args *args = arg;
- struct __timer t = { .timerid = -1 };
/* Reuse no-longer-needed thread structure fields to avoid
* needing the timer address in the signal handler. */
self->start = (void *(*)(void *))args->sev->sigev_notify_function;
self->start_arg = args->sev->sigev_value.sival_ptr;
- args->t = &t;
+ self->result = (void *)-1;
- pthread_cleanup_push(killtimer, &t);
pthread_barrier_wait(&args->b);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
/* Loop on async-signal-safe cancellation point */
for (;;) sleep(1);
- pthread_cleanup_pop(1);
return 0;
}
@@ -79,11 +69,7 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
ksev.sigev_tid = 0;
if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
return -1;
- if (!(t = calloc(1, sizeof *t))) {
- syscall(SYS_timer_delete, timerid);
- return -1;
- }
- t->timerid = timerid;
+ *res = (void *)(2*timerid+1);
break;
case SIGEV_THREAD:
if (!libc.sigtimer) libc.sigtimer = sighandler;
@@ -105,19 +91,17 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
ksev.sigev_tid = td->tid;
r = syscall(SYS_timer_create, clk, &ksev, &timerid);
pthread_barrier_wait(&args.b);
- t = args.t;
if (r < 0) {
pthread_cancel(td);
return -1;
}
- t->timerid = timerid;
- t->thread = td;
+ td->result = (void *)timerid;
+ *res = td;
break;
default:
errno = EINVAL;
return -1;
}
- *res = t;
return 0;
}
diff --git a/src/time/timer_delete.c b/src/time/timer_delete.c
index caf04895..437de2e0 100644
--- a/src/time/timer_delete.c
+++ b/src/time/timer_delete.c
@@ -3,10 +3,11 @@
int timer_delete(timer_t t)
{
- if (t->thread) pthread_cancel(t->thread);
- else {
- __syscall(SYS_timer_delete, t->timerid);
- free(t);
- }
- return 0;
+ pthread_t td = 0;
+ int r;
+ if ((uintptr_t)t & 1) t = (void *)((unsigned long)t / 2);
+ else td = t, t = td->result;
+ r = __syscall(SYS_timer_delete, (long)t);
+ if (td) pthread_cancel(td);
+ return r;
}
diff --git a/src/time/timer_getoverrun.c b/src/time/timer_getoverrun.c
index 1334e451..fa7715bb 100644
--- a/src/time/timer_getoverrun.c
+++ b/src/time/timer_getoverrun.c
@@ -3,5 +3,7 @@
int timer_getoverrun(timer_t t)
{
- return syscall(SYS_timer_getoverrun, t->timerid);
+ if ((uintptr_t)t & 1) t = (void *)((unsigned long)t / 2);
+ else t = ((pthread_t)t)->result;
+ return syscall(SYS_timer_getoverrun, (long)t);
}
diff --git a/src/time/timer_gettime.c b/src/time/timer_gettime.c
index 3d3156a0..2320873e 100644
--- a/src/time/timer_gettime.c
+++ b/src/time/timer_gettime.c
@@ -3,5 +3,7 @@
int timer_gettime(timer_t t, struct itimerspec *val)
{
- return syscall(SYS_timer_gettime, t->timerid, val);
+ if ((uintptr_t)t & 1) t = (void *)((unsigned long)t / 2);
+ else t = ((pthread_t)t)->result;
+ return syscall(SYS_timer_gettime, (long)t, val);
}
diff --git a/src/time/timer_settime.c b/src/time/timer_settime.c
index d109570b..00708f0e 100644
--- a/src/time/timer_settime.c
+++ b/src/time/timer_settime.c
@@ -3,5 +3,7 @@
int timer_settime(timer_t t, int flags, const struct itimerspec *val, struct itimerspec *old)
{
- return syscall(SYS_timer_settime, t->timerid, flags, val, old);
+ if ((uintptr_t)t & 1) t = (void *)((unsigned long)t / 2);
+ else t = ((pthread_t)t)->result;
+ return syscall(SYS_timer_settime, (long)t, flags, val, old);
}