xref: /openbsd/lib/libc/include/cancel.h (revision fe38b55c)
1 /*	$OpenBSD: cancel.h,v 1.1 2016/05/07 19:05:22 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 __BEGIN_HIDDEN_DECLS
25 /* process a cancel request at a cancel point */
26 __dead void	_thread_canceled(void);
27 __END_HIDDEN_DECLS
28 
29 #ifdef LIBC
30 /*
31  * Redirect macros that would use the syscall to instead use our callback
32  */
33 #define __get_tcb()	_thread_cb.tc_tcb()
34 #endif
35 
36 #define PREP_CANCEL_POINT(tib)						\
37 	int _cantcancel = (tib)->tib_cantcancel
38 
39 #define	ENTER_CANCEL_POINT_INNER(tib, can_cancel, delay)		\
40 	if (_cantcancel == 0) {						\
41 		(tib)->tib_cancel_point = (delay) ?			\
42 		    CANCEL_POINT_DELAYED : CANCEL_POINT;		\
43 		if (can_cancel) {					\
44 			__asm volatile("":::"memory");			\
45 			if (__predict_false((tib)->tib_canceled))	\
46 				_thread_canceled();			\
47 		}							\
48 	}
49 
50 #define	LEAVE_CANCEL_POINT_INNER(tib, can_cancel)			\
51 	if (_cantcancel == 0) {						\
52 		(tib)->tib_cancel_point = 0;				\
53 		if (can_cancel) {					\
54 			__asm volatile("":::"memory");			\
55 			if (__predict_false((tib)->tib_canceled))	\
56 				_thread_canceled();			\
57 		}							\
58 	}
59 
60 /*
61  * Enter or leave a cancelation point, optionally processing pending
62  * cancelation requests.  Note that ENTER_CANCEL_POINT opens a block
63  * and LEAVE_CANCEL_POINT must close that same block.
64  */
65 #define	ENTER_CANCEL_POINT(can_cancel)					\
66     {									\
67 	struct tib *_tib = TIB_GET();					\
68 	PREP_CANCEL_POINT(_tib);					\
69 	ENTER_CANCEL_POINT_INNER(_tib, can_cancel, 0)
70 
71 #define	LEAVE_CANCEL_POINT(can_cancel)					\
72 	LEAVE_CANCEL_POINT_INNER(_tib, can_cancel);			\
73     }
74 
75 #endif /* _CANCEL_H_ */
76