about summary refs log tree commit diff
path: root/src/time/timer_create.c
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 /src/time/timer_create.c
parentb8be64c43da207a2f497c1c5b5720e4a2027348a (diff)
downloadmusl-3990c5c6a40440cdb14746ac080d0ecf8d5d6733.tar.gz
musl-3990c5c6a40440cdb14746ac080d0ecf8d5d6733.tar.xz
musl-3990c5c6a40440cdb14746ac080d0ecf8d5d6733.zip
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.
Diffstat (limited to 'src/time/timer_create.c')
-rw-r--r--src/time/timer_create.c24
1 files changed, 4 insertions, 20 deletions
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;
 }