瀏覽代碼

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.
Rich Felker 14 年之前
父節點
當前提交
3990c5c6a4

+ 1 - 1
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 fsblkcnt_t;
 TYPEDEF unsigned long long fsfilcnt_t;
 TYPEDEF unsigned long long fsfilcnt_t;
 
 
-TYPEDEF struct __timer * timer_t;
+TYPEDEF void * timer_t;
 TYPEDEF int clockid_t;
 TYPEDEF int clockid_t;
 TYPEDEF unsigned long clock_t;
 TYPEDEF unsigned long clock_t;
 
 

+ 1 - 1
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 fsblkcnt_t;
 TYPEDEF unsigned long long fsfilcnt_t;
 TYPEDEF unsigned long long fsfilcnt_t;
 
 
-TYPEDEF struct __timer * timer_t;
+TYPEDEF void * timer_t;
 TYPEDEF int clockid_t;
 TYPEDEF int clockid_t;
 TYPEDEF long clock_t;
 TYPEDEF long clock_t;
 
 

+ 4 - 20
src/time/timer_create.c

@@ -11,7 +11,6 @@ struct ksigevent {
 struct start_args {
 struct start_args {
 	pthread_barrier_t b;
 	pthread_barrier_t b;
 	struct sigevent *sev;
 	struct sigevent *sev;
-	timer_t t;
 };
 };
 
 
 static void sighandler(int sig, siginfo_t *si, void *ctx)
 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);
 	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)
 static void *start(void *arg)
 {
 {
 	pthread_t self = __pthread_self();
 	pthread_t self = __pthread_self();
 	struct start_args *args = arg;
 	struct start_args *args = arg;
-	struct __timer t = { .timerid = -1 };
 
 
 	/* Reuse no-longer-needed thread structure fields to avoid
 	/* Reuse no-longer-needed thread structure fields to avoid
 	 * needing the timer address in the signal handler. */
 	 * needing the timer address in the signal handler. */
 	self->start = (void *(*)(void *))args->sev->sigev_notify_function;
 	self->start = (void *(*)(void *))args->sev->sigev_notify_function;
 	self->start_arg = args->sev->sigev_value.sival_ptr;
 	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_barrier_wait(&args->b);
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
 	/* Loop on async-signal-safe cancellation point */
 	/* Loop on async-signal-safe cancellation point */
 	for (;;) sleep(1);
 	for (;;) sleep(1);
-	pthread_cleanup_pop(1);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -79,11 +69,7 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
 		ksev.sigev_tid = 0;
 		ksev.sigev_tid = 0;
 		if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
 		if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
 			return -1;
 			return -1;
-		if (!(t = calloc(1, sizeof *t))) {
-			syscall(SYS_timer_delete, timerid);
-			return -1;
-		}
-		t->timerid = timerid;
+		*res = (void *)(2*timerid+1);
 		break;
 		break;
 	case SIGEV_THREAD:
 	case SIGEV_THREAD:
 		if (!libc.sigtimer) libc.sigtimer = sighandler;
 		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;
 		ksev.sigev_tid = td->tid;
 		r = syscall(SYS_timer_create, clk, &ksev, &timerid);
 		r = syscall(SYS_timer_create, clk, &ksev, &timerid);
 		pthread_barrier_wait(&args.b);
 		pthread_barrier_wait(&args.b);
-		t = args.t;
 		if (r < 0) {
 		if (r < 0) {
 			pthread_cancel(td);
 			pthread_cancel(td);
 			return -1;
 			return -1;
 		}
 		}
-		t->timerid = timerid;
-		t->thread = td;
+		td->result = (void *)timerid;
+		*res = td;
 		break;
 		break;
 	default:
 	default:
 		errno = EINVAL;
 		errno = EINVAL;
 		return -1;
 		return -1;
 	}
 	}
 
 
-	*res = t;
 	return 0;
 	return 0;
 }
 }

+ 7 - 6
src/time/timer_delete.c

@@ -3,10 +3,11 @@
 
 
 int timer_delete(timer_t t)
 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;
 }
 }

+ 3 - 1
src/time/timer_getoverrun.c

@@ -3,5 +3,7 @@
 
 
 int timer_getoverrun(timer_t t)
 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);
 }
 }

+ 3 - 1
src/time/timer_gettime.c

@@ -3,5 +3,7 @@
 
 
 int timer_gettime(timer_t t, struct itimerspec *val)
 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);
 }
 }

+ 3 - 1
src/time/timer_settime.c

@@ -3,5 +3,7 @@
 
 
 int timer_settime(timer_t t, int flags, const struct itimerspec *val, struct itimerspec *old)
 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);
 }
 }