瀏覽代碼

new framework to inhibit thread cancellation when needed

with these small changes, libc functions which need to call functions
which are cancellation points, but which themselves must not be
cancellation points, can use the CANCELPT_INHIBIT and CANCELPT_RESUME
macros to temporarily inhibit all cancellation.
Rich Felker 14 年之前
父節點
當前提交
729cb49f52
共有 3 個文件被更改,包括 17 次插入5 次删除
  1. 2 0
      src/internal/libc.h
  2. 13 3
      src/thread/pthread_create.c
  3. 2 2
      src/thread/pthread_setcancelstate.c

+ 2 - 0
src/internal/libc.h

@@ -45,6 +45,8 @@ void __lockfile(FILE *);
 #define CANCELPT_BEGIN CANCELPT(1)
 #define CANCELPT_TRY CANCELPT(0)
 #define CANCELPT_END CANCELPT(-1)
+#define CANCELPT_INHIBIT CANCELPT(2)
+#define CANCELPT_RESUME CANCELPT(-2)
 
 extern char **__environ;
 #define environ __environ

+ 13 - 3
src/thread/pthread_create.c

@@ -57,9 +57,19 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
 static void cancelpt(int x)
 {
 	struct pthread *self = __pthread_self();
-	if (self->canceldisable) return;
-	if ((self->cancelpoint+=x)==1 && x>=0 && self->cancel)
-		docancel(self);
+	switch (x) {
+	case 1:
+		self->cancelpoint++;
+	case 0:
+		if (self->cancel && self->cancelpoint==1 && !self->canceldisable)
+			docancel(self);
+		break;
+	case -1:
+		self->cancelpoint--;
+		break;
+	default:
+		self->canceldisable += x;
+	}
 }
 
 /* "rsyscall" is a mechanism by which a thread can synchronously force all

+ 2 - 2
src/thread/pthread_setcancelstate.c

@@ -3,8 +3,8 @@
 int pthread_setcancelstate(int new, int *old)
 {
 	struct pthread *self = pthread_self();
-	if (old) *old = self->canceldisable;
+	if (old) *old = self->canceldisable & 1;
 	if ((unsigned)new > 1) return EINVAL;
-	self->canceldisable = new;
+	self->canceldisable = (self->canceldisable & ~1) | new;
 	return 0;
 }