Home | History | Annotate | Line # | Download | only in include
      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