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