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-29 22:43:13 -0400
committerRich Felker <dalias@aerifal.cx>2011-03-29 22:43:13 -0400
commit680630011d38eb9f96f92b2f080cc60f38f6df21 (patch)
tree4bf5979dc62f53126940caec7d9c44609a6d0ccc /src/time/timer_create.c
parent1c1aa32eea467b2ed43b457b5528713933b32e95 (diff)
downloadmusl-680630011d38eb9f96f92b2f080cc60f38f6df21.tar.gz
musl-680630011d38eb9f96f92b2f080cc60f38f6df21.tar.xz
musl-680630011d38eb9f96f92b2f080cc60f38f6df21.zip
reorder timer initialization so that timer_create does not depend on free
this allows small programs which only create times, but never delete
them, to use simple_malloc instead of the full malloc.
Diffstat (limited to 'src/time/timer_create.c')
-rw-r--r--src/time/timer_create.c24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index 1ac1906b..2abec278 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -61,21 +61,28 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
 	struct start_args args;
 	timer_t t;
 	struct ksigevent ksev;
+	int timerid;
 
 	if (evp) sev = *evp;
 
 	switch (sev.sigev_notify) {
 	case SIGEV_NONE:
 	case SIGEV_SIGNAL:
-		if (!(t = calloc(1, sizeof *t)))
-			return -1;
 		ksev.sigev_value = evp ? sev.sigev_value
 			: (union sigval){.sival_ptr=t};
 		ksev.sigev_signo = sev.sigev_signo;
 		ksev.sigev_notify = sev.sigev_notify;
 		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;
 		break;
 	case SIGEV_THREAD:
+		if (!libc.sigtimer) libc.sigtimer = sighandler;
 		if (sev.sigev_notify_attributes)
 			attr = *sev.sigev_notify_attributes;
 		else
@@ -95,13 +102,14 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
 		ksev.sigev_signo = SIGCANCEL;
 		ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
 		ksev.sigev_tid = td->tid;
-		if (!libc.sigtimer) libc.sigtimer = sighandler;
+		if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {
+			t->timerid = -1;
+			pthread_cancel(td);
+			return -1;
+		}
 		break;
-	}
-
-	t->timerid = -1;
-	if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {
-		timer_delete(t);
+	default:
+		errno = EINVAL;
 		return -1;
 	}