Fix: nestable pthread cancelstate
[lttng-ust.git] / liblttng-ust-comm / ust-cancelstate.c
diff --git a/liblttng-ust-comm/ust-cancelstate.c b/liblttng-ust-comm/ust-cancelstate.c
new file mode 100644 (file)
index 0000000..298ffcb
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * Copyright (C) 2021 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <pthread.h>
+#include <errno.h>
+#include <error.h>
+#include <urcu/tls-compat.h>
+#include <lttng/ust-cancelstate.h>
+#include <usterr-signal-safe.h>
+
+struct ust_cancelstate {
+       int nesting;
+       int oldstate;   /* oldstate for outermost nesting */
+};
+
+static DEFINE_URCU_TLS(struct ust_cancelstate, thread_state);
+
+int lttng_ust_cancelstate_disable_push(void)
+{
+       struct ust_cancelstate *state = &URCU_TLS(thread_state);
+       int ret, oldstate;
+
+       if (state->nesting++)
+               goto end;
+       ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
+       if (ret) {
+               ERR("pthread_setcancelstate: %s", strerror(ret));
+               return -1;
+       }
+       state->oldstate = oldstate;
+end:
+       return 0;
+}
+
+int lttng_ust_cancelstate_disable_pop(void)
+{
+       struct ust_cancelstate *state = &URCU_TLS(thread_state);
+       int ret, oldstate;
+
+       if (!state->nesting)
+               return -1;
+       if (--state->nesting)
+               goto end;
+       ret = pthread_setcancelstate(state->oldstate, &oldstate);
+       if (ret) {
+               ERR("pthread_setcancelstate: %s", strerror(ret));
+               return -1;
+       }
+       if (oldstate != PTHREAD_CANCEL_DISABLE) {
+               ERR("pthread_setcancelstate: unexpected oldstate");
+               return -1;
+       }
+end:
+       return 0;
+}
+
+
This page took 0.024599 seconds and 4 git commands to generate.