xref: /openbsd/lib/libc/include/cancel.h (revision a5511fa9)
1*a5511fa9Sguenther /*	$OpenBSD: cancel.h,v 1.5 2017/09/05 02:40:54 guenther Exp $ */
2fe38b55cSguenther /*
3fe38b55cSguenther  * Copyright (c) 2015 Philip Guenther <guenther@openbsd.org>
4fe38b55cSguenther  *
5fe38b55cSguenther  * Permission to use, copy, modify, and distribute this software for any
6fe38b55cSguenther  * purpose with or without fee is hereby granted, provided that the above
7fe38b55cSguenther  * copyright notice and this permission notice appear in all copies.
8fe38b55cSguenther  *
9fe38b55cSguenther  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10fe38b55cSguenther  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11fe38b55cSguenther  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12fe38b55cSguenther  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13fe38b55cSguenther  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14fe38b55cSguenther  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15fe38b55cSguenther  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16fe38b55cSguenther  */
17fe38b55cSguenther 
18fe38b55cSguenther #ifndef _CANCEL_H_
19fe38b55cSguenther #define _CANCEL_H_
20fe38b55cSguenther 
21fe38b55cSguenther #include <tib.h>
22fe38b55cSguenther #include "thread_private.h"
23fe38b55cSguenther 
24fe38b55cSguenther /* process a cancel request at a cancel point */
25fe38b55cSguenther __dead void	_thread_canceled(void);
26*a5511fa9Sguenther 
27*a5511fa9Sguenther #ifdef __LIBC__
28*a5511fa9Sguenther PROTO_NORMAL(_thread_canceled);
29*a5511fa9Sguenther #endif
30fe38b55cSguenther 
3191ba2e42Svisa #if defined(__LIBC__) && !defined(TCB_HAVE_MD_GET)
32fe38b55cSguenther /*
3329879bdcSvisa  * Override TIB_GET macro to use the caching callback
34fe38b55cSguenther  */
3529879bdcSvisa #undef TIB_GET
3629879bdcSvisa #define TIB_GET()	TCB_TO_TIB(_thread_cb.tc_tcb())
37fe38b55cSguenther #endif
38fe38b55cSguenther 
39fe38b55cSguenther #define PREP_CANCEL_POINT(tib)						\
40fe38b55cSguenther 	int _cantcancel = (tib)->tib_cantcancel
41fe38b55cSguenther 
42fe38b55cSguenther #define	ENTER_CANCEL_POINT_INNER(tib, can_cancel, delay)		\
43fe38b55cSguenther 	if (_cantcancel == 0) {						\
44fe38b55cSguenther 		(tib)->tib_cancel_point = (delay) ?			\
45fe38b55cSguenther 		    CANCEL_POINT_DELAYED : CANCEL_POINT;		\
46fe38b55cSguenther 		if (can_cancel) {					\
47fe38b55cSguenther 			__asm volatile("":::"memory");			\
48fe38b55cSguenther 			if (__predict_false((tib)->tib_canceled))	\
49fe38b55cSguenther 				_thread_canceled();			\
50fe38b55cSguenther 		}							\
51fe38b55cSguenther 	}
52fe38b55cSguenther 
53fe38b55cSguenther #define	LEAVE_CANCEL_POINT_INNER(tib, can_cancel)			\
54fe38b55cSguenther 	if (_cantcancel == 0) {						\
55fe38b55cSguenther 		(tib)->tib_cancel_point = 0;				\
56fe38b55cSguenther 		if (can_cancel) {					\
57fe38b55cSguenther 			__asm volatile("":::"memory");			\
58fe38b55cSguenther 			if (__predict_false((tib)->tib_canceled))	\
59fe38b55cSguenther 				_thread_canceled();			\
60fe38b55cSguenther 		}							\
61fe38b55cSguenther 	}
62fe38b55cSguenther 
63fe38b55cSguenther /*
64fe38b55cSguenther  * Enter or leave a cancelation point, optionally processing pending
65fe38b55cSguenther  * cancelation requests.  Note that ENTER_CANCEL_POINT opens a block
66fe38b55cSguenther  * and LEAVE_CANCEL_POINT must close that same block.
67fe38b55cSguenther  */
68fe38b55cSguenther #define	ENTER_CANCEL_POINT(can_cancel)					\
69fe38b55cSguenther     {									\
70fe38b55cSguenther 	struct tib *_tib = TIB_GET();					\
71fe38b55cSguenther 	PREP_CANCEL_POINT(_tib);					\
72fe38b55cSguenther 	ENTER_CANCEL_POINT_INNER(_tib, can_cancel, 0)
73fe38b55cSguenther 
74fe38b55cSguenther #define	LEAVE_CANCEL_POINT(can_cancel)					\
75fe38b55cSguenther 	LEAVE_CANCEL_POINT_INNER(_tib, can_cancel);			\
76fe38b55cSguenther     }
77fe38b55cSguenther 
78fe38b55cSguenther #endif /* _CANCEL_H_ */
79