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