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