xref: /netbsd-src/external/bsd/ntp/dist/include/ntp_worker.h (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
1 /*	$NetBSD: ntp_worker.h,v 1.6 2020/05/25 20:47:20 christos Exp $	*/
2 
3 /*
4  * ntp_worker.h
5  */
6 
7 #ifndef NTP_WORKER_H
8 #define NTP_WORKER_H
9 
10 #include "ntp_workimpl.h"
11 
12 #ifdef WORKER
13 # if defined(WORK_THREAD) && defined(WORK_PIPE)
14 #  ifdef HAVE_SEMAPHORE_H
15 #   include <semaphore.h>
16 #  endif
17 # endif
18 #include "ntp_stdlib.h"
19 
20 /* #define TEST_BLOCKING_WORKER */	/* ntp_config.c ntp_intres.c */
21 
22 typedef enum blocking_work_req_tag {
23 	BLOCKING_GETNAMEINFO,
24 	BLOCKING_GETADDRINFO,
25 } blocking_work_req;
26 
27 typedef void (*blocking_work_callback)(blocking_work_req, void *, size_t, void *);
28 
29 typedef enum blocking_magic_sig_e {
30 	BLOCKING_REQ_MAGIC  = 0x510c7ecf,
31 	BLOCKING_RESP_MAGIC = 0x510c7e54,
32 } blocking_magic_sig;
33 
34 /*
35  * The same header is used for both requests to and responses from
36  * the child.  In the child, done_func and context are opaque.
37  */
38 typedef struct blocking_pipe_header_tag {
39 	size_t			octets;
40 	blocking_magic_sig	magic_sig;
41 	blocking_work_req	rtype;
42 	u_int			child_idx;
43 	blocking_work_callback	done_func;
44 	void *			context;
45 } blocking_pipe_header;
46 
47 # ifdef WORK_THREAD
48 #  ifdef SYS_WINNT
49 typedef struct { HANDLE thnd; } thread_type;
50 typedef struct { HANDLE shnd; } sema_type;
51 #  else
52 typedef pthread_t	thread_type;
53 typedef sem_t		sema_type;
54 #  endif
55 typedef thread_type	*thr_ref;
56 typedef sema_type	*sem_ref;
57 # endif
58 
59 /*
60  *
61  */
62 #if defined(WORK_FORK)
63 
64 typedef struct blocking_child_tag {
65 	int		reusable;
66 	int		pid;
67 	int		req_write_pipe;		/* parent */
68 	int		resp_read_pipe;
69 	void *		resp_read_ctx;
70 	int		req_read_pipe;		/* child */
71 	int		resp_write_pipe;
72 	int		ispipe;
73 	volatile u_int	resp_ready_seen;	/* signal/scan */
74 	volatile u_int	resp_ready_done;	/* consumer/mainloop */
75 } blocking_child;
76 
77 #elif defined(WORK_THREAD)
78 
79 typedef struct blocking_child_tag {
80 	/*
81 	 * blocking workitems and blocking_responses are
82 	 * dynamically-sized one-dimensional arrays of pointers to
83 	 * blocking worker requests and responses.
84 	 *
85 	 * IMPORTANT: This structure is shared between threads, and all
86 	 * access that is not atomic (especially queue operations) must
87 	 * hold the 'accesslock' semaphore to avoid data races.
88 	 *
89 	 * The resource management (thread/semaphore
90 	 * creation/destruction) functions and functions just testing a
91 	 * handle are safe because these are only changed by the main
92 	 * thread when no worker is running on the same data structure.
93 	 */
94 	int			reusable;
95 	sem_ref			accesslock;	/* shared access lock */
96 	thr_ref			thread_ref;	/* thread 'handle' */
97 
98 	/* the reuest queue */
99 	blocking_pipe_header ** volatile
100 				workitems;
101 	volatile size_t		workitems_alloc;
102 	size_t			head_workitem;		/* parent */
103 	size_t			tail_workitem;		/* child */
104 	sem_ref			workitems_pending;	/* signalling */
105 
106 	/* the response queue */
107 	blocking_pipe_header ** volatile
108 				responses;
109 	volatile size_t		responses_alloc;
110 	size_t			head_response;		/* child */
111 	size_t			tail_response;		/* parent */
112 
113 	/* event handles / sem_t pointers */
114 	sem_ref			wake_scheduled_sleep;
115 
116 	/* some systems use a pipe for notification, others a semaphore.
117 	 * Both employ the queue above for the actual data transfer.
118 	 */
119 #ifdef WORK_PIPE
120 	int			resp_read_pipe;		/* parent */
121 	int			resp_write_pipe;	/* child */
122 	int			ispipe;
123 	void *			resp_read_ctx;		/* child */
124 #else
125 	sem_ref			responses_pending;	/* signalling */
126 #endif
127 	volatile u_int		resp_ready_seen;	/* signal/scan */
128 	volatile u_int		resp_ready_done;	/* consumer/mainloop */
129 	sema_type		sem_table[4];
130 	thread_type		thr_table[1];
131 } blocking_child;
132 
133 #endif	/* WORK_THREAD */
134 
135 /* we need some global tag to indicate any blocking child may be ready: */
136 extern volatile u_int		blocking_child_ready_seen;/* signal/scan */
137 extern volatile u_int		blocking_child_ready_done;/* consumer/mainloop */
138 
139 extern	blocking_child **	blocking_children;
140 extern	size_t			blocking_children_alloc;
141 extern	int			worker_per_query;	/* boolean */
142 extern	int			intres_req_pending;
143 
144 extern	u_int	available_blocking_child_slot(void);
145 extern	int	queue_blocking_request(blocking_work_req, void *,
146 				       size_t, blocking_work_callback,
147 				       void *);
148 extern	int	queue_blocking_response(blocking_child *,
149 					blocking_pipe_header *, size_t,
150 					const blocking_pipe_header *);
151 extern	void	process_blocking_resp(blocking_child *);
152 extern	void	harvest_blocking_responses(void);
153 extern	int	send_blocking_req_internal(blocking_child *,
154 					   blocking_pipe_header *,
155 					   void *);
156 extern	int	send_blocking_resp_internal(blocking_child *,
157 					    blocking_pipe_header *);
158 extern	blocking_pipe_header *
159 		receive_blocking_req_internal(blocking_child *);
160 extern	blocking_pipe_header *
161 		receive_blocking_resp_internal(blocking_child *);
162 extern	int	blocking_child_common(blocking_child *);
163 extern	void	exit_worker(int)
164 			__attribute__ ((__noreturn__));
165 extern	int	worker_sleep(blocking_child *, time_t);
166 extern	void	worker_idle_timer_fired(void);
167 extern	void	interrupt_worker_sleep(void);
168 extern	int	req_child_exit(blocking_child *);
169 #ifndef HAVE_IO_COMPLETION_PORT
170 extern	int	pipe_socketpair(int fds[2], int *is_pipe);
171 extern	void	close_all_beyond(int);
172 extern	void	close_all_except(int);
173 extern	void	kill_asyncio	(int);
174 #endif
175 
176 extern void worker_global_lock(int inOrOut);
177 
178 # ifdef WORK_PIPE
179 typedef	void	(*addremove_io_fd_func)(int, int, int);
180 extern	addremove_io_fd_func		addremove_io_fd;
181 # else
182 extern	void	handle_blocking_resp_sem(void *);
183 typedef	void	(*addremove_io_semaphore_func)(sem_ref, int);
184 extern	addremove_io_semaphore_func	addremove_io_semaphore;
185 # endif
186 
187 # ifdef WORK_FORK
188 extern	int				worker_process;
189 # endif
190 
191 #endif	/* WORKER */
192 
193 #if defined(HAVE_DROPROOT) && defined(WORK_FORK)
194 extern void	fork_deferred_worker(void);
195 #else
196 # define	fork_deferred_worker()	do {} while (0)
197 #endif
198 
199 #endif	/* !NTP_WORKER_H */
200