xref: /unit/src/nxt_unit.c (revision 2143:52dda4e05868)
1743Smax.romanov@nginx.com 
2743Smax.romanov@nginx.com /*
3743Smax.romanov@nginx.com  * Copyright (C) NGINX, Inc.
4743Smax.romanov@nginx.com  */
5743Smax.romanov@nginx.com 
6743Smax.romanov@nginx.com #include "nxt_main.h"
7743Smax.romanov@nginx.com #include "nxt_port_memory_int.h"
81996St.nateldemoura@f5.com #include "nxt_socket_msg.h"
91555Smax.romanov@nginx.com #include "nxt_port_queue.h"
101555Smax.romanov@nginx.com #include "nxt_app_queue.h"
11743Smax.romanov@nginx.com 
12743Smax.romanov@nginx.com #include "nxt_unit.h"
13743Smax.romanov@nginx.com #include "nxt_unit_request.h"
14743Smax.romanov@nginx.com #include "nxt_unit_response.h"
151131Smax.romanov@nginx.com #include "nxt_unit_websocket.h"
161131Smax.romanov@nginx.com 
171131Smax.romanov@nginx.com #include "nxt_websocket.h"
18743Smax.romanov@nginx.com 
19743Smax.romanov@nginx.com #if (NXT_HAVE_MEMFD_CREATE)
20743Smax.romanov@nginx.com #include <linux/memfd.h>
21743Smax.romanov@nginx.com #endif
22743Smax.romanov@nginx.com 
231317Smax.romanov@nginx.com #define NXT_UNIT_MAX_PLAIN_SIZE  1024
241317Smax.romanov@nginx.com #define NXT_UNIT_LOCAL_BUF_SIZE  \
251317Smax.romanov@nginx.com     (NXT_UNIT_MAX_PLAIN_SIZE + sizeof(nxt_port_msg_t))
261317Smax.romanov@nginx.com 
271980Smax.romanov@nginx.com enum {
281980Smax.romanov@nginx.com     NXT_QUIT_NORMAL   = 0,
291980Smax.romanov@nginx.com     NXT_QUIT_GRACEFUL = 1,
301980Smax.romanov@nginx.com };
311980Smax.romanov@nginx.com 
321131Smax.romanov@nginx.com typedef struct nxt_unit_impl_s                  nxt_unit_impl_t;
331131Smax.romanov@nginx.com typedef struct nxt_unit_mmap_s                  nxt_unit_mmap_t;
341131Smax.romanov@nginx.com typedef struct nxt_unit_mmaps_s                 nxt_unit_mmaps_t;
351131Smax.romanov@nginx.com typedef struct nxt_unit_process_s               nxt_unit_process_t;
361131Smax.romanov@nginx.com typedef struct nxt_unit_mmap_buf_s              nxt_unit_mmap_buf_t;
371131Smax.romanov@nginx.com typedef struct nxt_unit_recv_msg_s              nxt_unit_recv_msg_t;
381321Smax.romanov@nginx.com typedef struct nxt_unit_read_buf_s              nxt_unit_read_buf_t;
391131Smax.romanov@nginx.com typedef struct nxt_unit_ctx_impl_s              nxt_unit_ctx_impl_t;
401131Smax.romanov@nginx.com typedef struct nxt_unit_port_impl_s             nxt_unit_port_impl_t;
411131Smax.romanov@nginx.com typedef struct nxt_unit_request_info_impl_s     nxt_unit_request_info_impl_t;
421131Smax.romanov@nginx.com typedef struct nxt_unit_websocket_frame_impl_s  nxt_unit_websocket_frame_impl_t;
43743Smax.romanov@nginx.com 
44743Smax.romanov@nginx.com static nxt_unit_impl_t *nxt_unit_create(nxt_unit_init_t *init);
451175Smax.romanov@nginx.com static int nxt_unit_ctx_init(nxt_unit_impl_t *lib,
46743Smax.romanov@nginx.com     nxt_unit_ctx_impl_t *ctx_impl, void *data);
471547Smax.romanov@nginx.com nxt_inline void nxt_unit_ctx_use(nxt_unit_ctx_t *ctx);
481547Smax.romanov@nginx.com nxt_inline void nxt_unit_ctx_release(nxt_unit_ctx_t *ctx);
491543Smax.romanov@nginx.com nxt_inline void nxt_unit_lib_use(nxt_unit_impl_t *lib);
501543Smax.romanov@nginx.com nxt_inline void nxt_unit_lib_release(nxt_unit_impl_t *lib);
511131Smax.romanov@nginx.com nxt_inline void nxt_unit_mmap_buf_insert(nxt_unit_mmap_buf_t **head,
521131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t *mmap_buf);
531131Smax.romanov@nginx.com nxt_inline void nxt_unit_mmap_buf_insert_tail(nxt_unit_mmap_buf_t **prev,
541131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t *mmap_buf);
551319Smax.romanov@nginx.com nxt_inline void nxt_unit_mmap_buf_unlink(nxt_unit_mmap_buf_t *mmap_buf);
56743Smax.romanov@nginx.com static int nxt_unit_read_env(nxt_unit_port_t *ready_port,
571543Smax.romanov@nginx.com     nxt_unit_port_t *router_port, nxt_unit_port_t *read_port,
582014Smax.romanov@nginx.com     int *shared_port_fd, int *shared_queue_fd,
591980Smax.romanov@nginx.com     int *log_fd, uint32_t *stream, uint32_t *shm_limit,
601980Smax.romanov@nginx.com     uint32_t *request_limit);
611555Smax.romanov@nginx.com static int nxt_unit_ready(nxt_unit_ctx_t *ctx, int ready_fd, uint32_t stream,
621555Smax.romanov@nginx.com     int queue_fd);
631713Smax.romanov@nginx.com static int nxt_unit_process_msg(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf,
641713Smax.romanov@nginx.com     nxt_unit_request_info_t **preq);
651131Smax.romanov@nginx.com static int nxt_unit_process_new_port(nxt_unit_ctx_t *ctx,
661131Smax.romanov@nginx.com     nxt_unit_recv_msg_t *recv_msg);
671666Smax.romanov@nginx.com static int nxt_unit_ctx_ready(nxt_unit_ctx_t *ctx);
681131Smax.romanov@nginx.com static int nxt_unit_process_req_headers(nxt_unit_ctx_t *ctx,
691713Smax.romanov@nginx.com     nxt_unit_recv_msg_t *recv_msg, nxt_unit_request_info_t **preq);
701555Smax.romanov@nginx.com static int nxt_unit_process_req_body(nxt_unit_ctx_t *ctx,
711555Smax.romanov@nginx.com     nxt_unit_recv_msg_t *recv_msg);
721545Smax.romanov@nginx.com static int nxt_unit_request_check_response_port(nxt_unit_request_info_t *req,
731545Smax.romanov@nginx.com     nxt_unit_port_id_t *port_id);
741547Smax.romanov@nginx.com static int nxt_unit_send_req_headers_ack(nxt_unit_request_info_t *req);
751131Smax.romanov@nginx.com static int nxt_unit_process_websocket(nxt_unit_ctx_t *ctx,
761131Smax.romanov@nginx.com     nxt_unit_recv_msg_t *recv_msg);
771321Smax.romanov@nginx.com static int nxt_unit_process_shm_ack(nxt_unit_ctx_t *ctx);
78743Smax.romanov@nginx.com static nxt_unit_request_info_impl_t *nxt_unit_request_info_get(
79743Smax.romanov@nginx.com     nxt_unit_ctx_t *ctx);
80743Smax.romanov@nginx.com static void nxt_unit_request_info_release(nxt_unit_request_info_t *req);
81743Smax.romanov@nginx.com static void nxt_unit_request_info_free(nxt_unit_request_info_impl_t *req);
821131Smax.romanov@nginx.com static nxt_unit_websocket_frame_impl_t *nxt_unit_websocket_frame_get(
831131Smax.romanov@nginx.com     nxt_unit_ctx_t *ctx);
841131Smax.romanov@nginx.com static void nxt_unit_websocket_frame_release(nxt_unit_websocket_frame_t *ws);
851623Smax.romanov@nginx.com static void nxt_unit_websocket_frame_free(nxt_unit_ctx_t *ctx,
861623Smax.romanov@nginx.com     nxt_unit_websocket_frame_impl_t *ws);
87743Smax.romanov@nginx.com static nxt_unit_mmap_buf_t *nxt_unit_mmap_buf_get(nxt_unit_ctx_t *ctx);
88743Smax.romanov@nginx.com static void nxt_unit_mmap_buf_release(nxt_unit_mmap_buf_t *mmap_buf);
891544Smax.romanov@nginx.com static int nxt_unit_mmap_buf_send(nxt_unit_request_info_t *req,
90743Smax.romanov@nginx.com     nxt_unit_mmap_buf_t *mmap_buf, int last);
911131Smax.romanov@nginx.com static void nxt_unit_mmap_buf_free(nxt_unit_mmap_buf_t *mmap_buf);
921317Smax.romanov@nginx.com static void nxt_unit_free_outgoing_buf(nxt_unit_mmap_buf_t *mmap_buf);
931321Smax.romanov@nginx.com static nxt_unit_read_buf_t *nxt_unit_read_buf_get(nxt_unit_ctx_t *ctx);
941321Smax.romanov@nginx.com static nxt_unit_read_buf_t *nxt_unit_read_buf_get_impl(
951321Smax.romanov@nginx.com     nxt_unit_ctx_impl_t *ctx_impl);
961321Smax.romanov@nginx.com static void nxt_unit_read_buf_release(nxt_unit_ctx_t *ctx,
971321Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
981403Smax.romanov@nginx.com static nxt_unit_mmap_buf_t *nxt_unit_request_preread(
991403Smax.romanov@nginx.com     nxt_unit_request_info_t *req, size_t size);
1001131Smax.romanov@nginx.com static ssize_t nxt_unit_buf_read(nxt_unit_buf_t **b, uint64_t *len, void *dst,
1011131Smax.romanov@nginx.com     size_t size);
102743Smax.romanov@nginx.com static nxt_port_mmap_header_t *nxt_unit_mmap_get(nxt_unit_ctx_t *ctx,
1031544Smax.romanov@nginx.com     nxt_unit_port_t *port, nxt_chunk_id_t *c, int *n, int min_n);
1041544Smax.romanov@nginx.com static int nxt_unit_send_oosm(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port);
1051321Smax.romanov@nginx.com static int nxt_unit_wait_shm_ack(nxt_unit_ctx_t *ctx);
106743Smax.romanov@nginx.com static nxt_unit_mmap_t *nxt_unit_mmap_at(nxt_unit_mmaps_t *mmaps, uint32_t i);
107743Smax.romanov@nginx.com static nxt_port_mmap_header_t *nxt_unit_new_mmap(nxt_unit_ctx_t *ctx,
1081544Smax.romanov@nginx.com     nxt_unit_port_t *port, int n);
1091555Smax.romanov@nginx.com static int nxt_unit_shm_open(nxt_unit_ctx_t *ctx, size_t size);
1101544Smax.romanov@nginx.com static int nxt_unit_send_mmap(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port,
111743Smax.romanov@nginx.com     int fd);
112743Smax.romanov@nginx.com static int nxt_unit_get_outgoing_buf(nxt_unit_ctx_t *ctx,
1131544Smax.romanov@nginx.com     nxt_unit_port_t *port, uint32_t size,
1141321Smax.romanov@nginx.com     uint32_t min_size, nxt_unit_mmap_buf_t *mmap_buf, char *local_buf);
115743Smax.romanov@nginx.com static int nxt_unit_incoming_mmap(nxt_unit_ctx_t *ctx, pid_t pid, int fd);
116743Smax.romanov@nginx.com 
1171667Smax.romanov@nginx.com static void nxt_unit_awake_ctx(nxt_unit_ctx_t *ctx,
1181667Smax.romanov@nginx.com     nxt_unit_ctx_impl_t *ctx_impl);
119743Smax.romanov@nginx.com static void nxt_unit_mmaps_init(nxt_unit_mmaps_t *mmaps);
1201543Smax.romanov@nginx.com nxt_inline void nxt_unit_process_use(nxt_unit_process_t *process);
1211543Smax.romanov@nginx.com nxt_inline void nxt_unit_process_release(nxt_unit_process_t *process);
122743Smax.romanov@nginx.com static void nxt_unit_mmaps_destroy(nxt_unit_mmaps_t *mmaps);
1231546Smax.romanov@nginx.com static int nxt_unit_check_rbuf_mmap(nxt_unit_ctx_t *ctx,
1241546Smax.romanov@nginx.com     nxt_unit_mmaps_t *mmaps, pid_t pid, uint32_t id,
1251546Smax.romanov@nginx.com     nxt_port_mmap_header_t **hdr, nxt_unit_read_buf_t *rbuf);
126743Smax.romanov@nginx.com static int nxt_unit_mmap_read(nxt_unit_ctx_t *ctx,
1271546Smax.romanov@nginx.com     nxt_unit_recv_msg_t *recv_msg, nxt_unit_read_buf_t *rbuf);
1281546Smax.romanov@nginx.com static int nxt_unit_get_mmap(nxt_unit_ctx_t *ctx, pid_t pid, uint32_t id);
1291321Smax.romanov@nginx.com static void nxt_unit_mmap_release(nxt_unit_ctx_t *ctx,
1301321Smax.romanov@nginx.com     nxt_port_mmap_header_t *hdr, void *start, uint32_t size);
1311321Smax.romanov@nginx.com static int nxt_unit_send_shm_ack(nxt_unit_ctx_t *ctx, pid_t pid);
132743Smax.romanov@nginx.com 
1331623Smax.romanov@nginx.com static nxt_unit_process_t *nxt_unit_process_get(nxt_unit_ctx_t *ctx, pid_t pid);
1341543Smax.romanov@nginx.com static nxt_unit_process_t *nxt_unit_process_find(nxt_unit_impl_t *lib,
135743Smax.romanov@nginx.com     pid_t pid, int remove);
136743Smax.romanov@nginx.com static nxt_unit_process_t *nxt_unit_process_pop_first(nxt_unit_impl_t *lib);
1371547Smax.romanov@nginx.com static int nxt_unit_run_once_impl(nxt_unit_ctx_t *ctx);
1381547Smax.romanov@nginx.com static int nxt_unit_read_buf(nxt_unit_ctx_t *ctx, nxt_unit_read_buf_t *rbuf);
1391980Smax.romanov@nginx.com static int nxt_unit_chk_ready(nxt_unit_ctx_t *ctx);
1401547Smax.romanov@nginx.com static int nxt_unit_process_pending_rbuf(nxt_unit_ctx_t *ctx);
1411547Smax.romanov@nginx.com static void nxt_unit_process_ready_req(nxt_unit_ctx_t *ctx);
1421555Smax.romanov@nginx.com nxt_inline int nxt_unit_is_read_queue(nxt_unit_read_buf_t *rbuf);
1431555Smax.romanov@nginx.com nxt_inline int nxt_unit_is_read_socket(nxt_unit_read_buf_t *rbuf);
1441555Smax.romanov@nginx.com nxt_inline int nxt_unit_is_shm_ack(nxt_unit_read_buf_t *rbuf);
1451555Smax.romanov@nginx.com nxt_inline int nxt_unit_is_quit(nxt_unit_read_buf_t *rbuf);
1461547Smax.romanov@nginx.com static int nxt_unit_process_port_msg_impl(nxt_unit_ctx_t *ctx,
1471547Smax.romanov@nginx.com     nxt_unit_port_t *port);
1481543Smax.romanov@nginx.com static void nxt_unit_ctx_free(nxt_unit_ctx_impl_t *ctx_impl);
1491544Smax.romanov@nginx.com static nxt_unit_port_t *nxt_unit_create_port(nxt_unit_ctx_t *ctx);
1501544Smax.romanov@nginx.com 
1511544Smax.romanov@nginx.com static int nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_t *dst,
1521555Smax.romanov@nginx.com     nxt_unit_port_t *port, int queue_fd);
1531544Smax.romanov@nginx.com 
1541544Smax.romanov@nginx.com nxt_inline void nxt_unit_port_use(nxt_unit_port_t *port);
1551544Smax.romanov@nginx.com nxt_inline void nxt_unit_port_release(nxt_unit_port_t *port);
1561544Smax.romanov@nginx.com static nxt_unit_port_t *nxt_unit_add_port(nxt_unit_ctx_t *ctx,
1571555Smax.romanov@nginx.com     nxt_unit_port_t *port, void *queue);
1581711Smax.romanov@nginx.com static void nxt_unit_process_awaiting_req(nxt_unit_ctx_t *ctx,
1591711Smax.romanov@nginx.com     nxt_queue_t *awaiting_req);
1601980Smax.romanov@nginx.com static void nxt_unit_remove_port(nxt_unit_impl_t *lib, nxt_unit_ctx_t *ctx,
1611543Smax.romanov@nginx.com     nxt_unit_port_id_t *port_id);
1621544Smax.romanov@nginx.com static nxt_unit_port_t *nxt_unit_remove_port_unsafe(nxt_unit_impl_t *lib,
1631544Smax.romanov@nginx.com     nxt_unit_port_id_t *port_id);
1641543Smax.romanov@nginx.com static void nxt_unit_remove_pid(nxt_unit_impl_t *lib, pid_t pid);
1651543Smax.romanov@nginx.com static void nxt_unit_remove_process(nxt_unit_impl_t *lib,
166743Smax.romanov@nginx.com     nxt_unit_process_t *process);
1671980Smax.romanov@nginx.com static void nxt_unit_quit(nxt_unit_ctx_t *ctx, uint8_t quit_param);
1681545Smax.romanov@nginx.com static int nxt_unit_get_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *port_id);
1691543Smax.romanov@nginx.com static ssize_t nxt_unit_port_send(nxt_unit_ctx_t *ctx,
1701544Smax.romanov@nginx.com     nxt_unit_port_t *port, const void *buf, size_t buf_size,
1711996St.nateldemoura@f5.com     const nxt_send_oob_t *oob);
1721543Smax.romanov@nginx.com static ssize_t nxt_unit_sendmsg(nxt_unit_ctx_t *ctx, int fd,
1731996St.nateldemoura@f5.com     const void *buf, size_t buf_size, const nxt_send_oob_t *oob);
1741555Smax.romanov@nginx.com static int nxt_unit_ctx_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port,
1751555Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
1761555Smax.romanov@nginx.com nxt_inline void nxt_unit_rbuf_cpy(nxt_unit_read_buf_t *dst,
1771555Smax.romanov@nginx.com     nxt_unit_read_buf_t *src);
1781555Smax.romanov@nginx.com static int nxt_unit_shared_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port,
1791555Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
1801547Smax.romanov@nginx.com static int nxt_unit_port_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port,
1811547Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
1821555Smax.romanov@nginx.com static int nxt_unit_port_queue_recv(nxt_unit_port_t *port,
1831555Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
1841980Smax.romanov@nginx.com static int nxt_unit_app_queue_recv(nxt_unit_ctx_t *ctx, nxt_unit_port_t *port,
1851555Smax.romanov@nginx.com     nxt_unit_read_buf_t *rbuf);
1861556Smax.romanov@nginx.com nxt_inline int nxt_unit_close(int fd);
1871557Smax.romanov@nginx.com static int nxt_unit_fd_blocking(int fd);
188743Smax.romanov@nginx.com 
189743Smax.romanov@nginx.com static int nxt_unit_port_hash_add(nxt_lvlhsh_t *port_hash,
190743Smax.romanov@nginx.com     nxt_unit_port_t *port);
1911544Smax.romanov@nginx.com static nxt_unit_port_t *nxt_unit_port_hash_find(nxt_lvlhsh_t *port_hash,
192743Smax.romanov@nginx.com     nxt_unit_port_id_t *port_id, int remove);
193743Smax.romanov@nginx.com 
1941555Smax.romanov@nginx.com static int nxt_unit_request_hash_add(nxt_unit_ctx_t *ctx,
1951555Smax.romanov@nginx.com     nxt_unit_request_info_t *req);
1961555Smax.romanov@nginx.com static nxt_unit_request_info_t *nxt_unit_request_hash_find(
1971555Smax.romanov@nginx.com     nxt_unit_ctx_t *ctx, uint32_t stream, int remove);
1981131Smax.romanov@nginx.com 
1992139Sandrew@digital-domain.net static char * nxt_unit_snprint_prefix(char *p, const char *end, pid_t pid,
2002139Sandrew@digital-domain.net     int level);
2011616Smax.romanov@nginx.com static void *nxt_unit_lvlhsh_alloc(void *data, size_t size);
2021616Smax.romanov@nginx.com static void nxt_unit_lvlhsh_free(void *data, void *p);
2031593Smax.romanov@nginx.com static int nxt_unit_memcasecmp(const void *p1, const void *p2, size_t length);
204743Smax.romanov@nginx.com 
205743Smax.romanov@nginx.com 
206743Smax.romanov@nginx.com struct nxt_unit_mmap_buf_s {
207743Smax.romanov@nginx.com     nxt_unit_buf_t           buf;
208743Smax.romanov@nginx.com 
2091131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t      *next;
2101131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t      **prev;
2111131Smax.romanov@nginx.com 
212743Smax.romanov@nginx.com     nxt_port_mmap_header_t   *hdr;
213743Smax.romanov@nginx.com     nxt_unit_request_info_t  *req;
214743Smax.romanov@nginx.com     nxt_unit_ctx_impl_t      *ctx_impl;
2151317Smax.romanov@nginx.com     char                     *free_ptr;
2161317Smax.romanov@nginx.com     char                     *plain_ptr;
217743Smax.romanov@nginx.com };
218743Smax.romanov@nginx.com 
219743Smax.romanov@nginx.com 
220743Smax.romanov@nginx.com struct nxt_unit_recv_msg_s {
2211131Smax.romanov@nginx.com     uint32_t                 stream;
2221131Smax.romanov@nginx.com     nxt_pid_t                pid;
2231131Smax.romanov@nginx.com     nxt_port_id_t            reply_port;
2241131Smax.romanov@nginx.com 
2251131Smax.romanov@nginx.com     uint8_t                  last;      /* 1 bit */
2261131Smax.romanov@nginx.com     uint8_t                  mmap;      /* 1 bit */
227743Smax.romanov@nginx.com 
228743Smax.romanov@nginx.com     void                     *start;
229743Smax.romanov@nginx.com     uint32_t                 size;
230743Smax.romanov@nginx.com 
2311558Smax.romanov@nginx.com     int                      fd[2];
2321131Smax.romanov@nginx.com 
2331131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t      *incoming_buf;
234743Smax.romanov@nginx.com };
235743Smax.romanov@nginx.com 
236743Smax.romanov@nginx.com 
237743Smax.romanov@nginx.com typedef enum {
238743Smax.romanov@nginx.com     NXT_UNIT_RS_START           = 0,
239743Smax.romanov@nginx.com     NXT_UNIT_RS_RESPONSE_INIT,
240743Smax.romanov@nginx.com     NXT_UNIT_RS_RESPONSE_HAS_CONTENT,
241743Smax.romanov@nginx.com     NXT_UNIT_RS_RESPONSE_SENT,
2421131Smax.romanov@nginx.com     NXT_UNIT_RS_RELEASED,
243743Smax.romanov@nginx.com } nxt_unit_req_state_t;
244743Smax.romanov@nginx.com 
245743Smax.romanov@nginx.com 
246743Smax.romanov@nginx.com struct nxt_unit_request_info_impl_s {
247743Smax.romanov@nginx.com     nxt_unit_request_info_t  req;
248743Smax.romanov@nginx.com 
2491131Smax.romanov@nginx.com     uint32_t                 stream;
2501131Smax.romanov@nginx.com 
2511131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t      *outgoing_buf;
2521131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t      *incoming_buf;
253743Smax.romanov@nginx.com 
254743Smax.romanov@nginx.com     nxt_unit_req_state_t     state;
2551131Smax.romanov@nginx.com     uint8_t                  websocket;
2561555Smax.romanov@nginx.com     uint8_t                  in_hash;
257743Smax.romanov@nginx.com 
2581545Smax.romanov@nginx.com     /*  for nxt_unit_ctx_impl_t.free_req or active_req */
259743Smax.romanov@nginx.com     nxt_queue_link_t         link;
2601545Smax.romanov@nginx.com     /*  for nxt_unit_port_impl_t.awaiting_req */
2611545Smax.romanov@nginx.com     nxt_queue_link_t         port_wait_link;
262743Smax.romanov@nginx.com 
263743Smax.romanov@nginx.com     char                     extra_data[];
264743Smax.romanov@nginx.com };
265743Smax.romanov@nginx.com 
266743Smax.romanov@nginx.com 
2671131Smax.romanov@nginx.com struct nxt_unit_websocket_frame_impl_s {
2681131Smax.romanov@nginx.com     nxt_unit_websocket_frame_t  ws;
2691131Smax.romanov@nginx.com 
2701131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t         *buf;
2711131Smax.romanov@nginx.com 
2721131Smax.romanov@nginx.com     nxt_queue_link_t            link;
2731131Smax.romanov@nginx.com 
2741131Smax.romanov@nginx.com     nxt_unit_ctx_impl_t         *ctx_impl;
2751131Smax.romanov@nginx.com };
2761131Smax.romanov@nginx.com 
2771131Smax.romanov@nginx.com 
2781321Smax.romanov@nginx.com struct nxt_unit_read_buf_s {
2791546Smax.romanov@nginx.com     nxt_queue_link_t              link;
2801546Smax.romanov@nginx.com     nxt_unit_ctx_impl_t           *ctx_impl;
2811321Smax.romanov@nginx.com     ssize_t                       size;
2821996St.nateldemoura@f5.com     nxt_recv_oob_t                oob;
2831321Smax.romanov@nginx.com     char                          buf[16384];
2841321Smax.romanov@nginx.com };
2851321Smax.romanov@nginx.com 
2861321Smax.romanov@nginx.com 
287743Smax.romanov@nginx.com struct nxt_unit_ctx_impl_s {
288743Smax.romanov@nginx.com     nxt_unit_ctx_t                ctx;
289743Smax.romanov@nginx.com 
2901543Smax.romanov@nginx.com     nxt_atomic_t                  use_count;
2911545Smax.romanov@nginx.com     nxt_atomic_t                  wait_items;
2921543Smax.romanov@nginx.com 
2931175Smax.romanov@nginx.com     pthread_mutex_t               mutex;
2941175Smax.romanov@nginx.com 
2951544Smax.romanov@nginx.com     nxt_unit_port_t               *read_port;
296743Smax.romanov@nginx.com 
297743Smax.romanov@nginx.com     nxt_queue_link_t              link;
298743Smax.romanov@nginx.com 
2991131Smax.romanov@nginx.com     nxt_unit_mmap_buf_t           *free_buf;
300743Smax.romanov@nginx.com 
301743Smax.romanov@nginx.com     /*  of nxt_unit_request_info_impl_t */
302743Smax.romanov@nginx.com     nxt_queue_t                   free_req;
303743Smax.romanov@nginx.com 
3041131Smax.romanov@nginx.com     /*  of nxt_unit_websocket_frame_impl_t */
3051131Smax.romanov@nginx.com     nxt_queue_t                   free_ws;
3061131Smax.romanov@nginx.com 
307743Smax.romanov@nginx.com     /*  of nxt_unit_request_info_impl_t */
308743Smax.romanov@nginx.com     nxt_queue_t                   active_req;
309743Smax.romanov@nginx.com 
3101131Smax.romanov@nginx.com     /*  of nxt_unit_request_info_impl_t */
3111131Smax.romanov@nginx.com     nxt_lvlhsh_t                  requests;
3121131Smax.romanov@nginx.com 
3131545Smax.romanov@nginx.com     /*  of nxt_unit_request_info_impl_t */
3141545Smax.romanov@nginx.com     nxt_queue_t                   ready_req;
3151545Smax.romanov@nginx.com 
3161546Smax.romanov@nginx.com     /*  of nxt_unit_read_buf_t */
3171546Smax.romanov@nginx.com     nxt_queue_t                   pending_rbuf;
3181546Smax.romanov@nginx.com 
3191546Smax.romanov@nginx.com     /*  of nxt_unit_read_buf_t */
3201546Smax.romanov@nginx.com     nxt_queue_t                   free_rbuf;
3211321Smax.romanov@nginx.com 
3221980Smax.romanov@nginx.com     uint8_t                       online;       /* 1 bit */
3231980Smax.romanov@nginx.com     uint8_t                       ready;        /* 1 bit */
3241980Smax.romanov@nginx.com     uint8_t                       quit_param;
3251663Smax.romanov@nginx.com 
326743Smax.romanov@nginx.com     nxt_unit_mmap_buf_t           ctx_buf[2];
3271321Smax.romanov@nginx.com     nxt_unit_read_buf_t           ctx_read_buf;
328743Smax.romanov@nginx.com 
329743Smax.romanov@nginx.com     nxt_unit_request_info_impl_t  req;
330743Smax.romanov@nginx.com };
331743Smax.romanov@nginx.com 
332743Smax.romanov@nginx.com 
3331548Smax.romanov@nginx.com struct nxt_unit_mmap_s {
3341548Smax.romanov@nginx.com     nxt_port_mmap_header_t   *hdr;
3351659Smax.romanov@nginx.com     pthread_t                src_thread;
3361548Smax.romanov@nginx.com 
3371548Smax.romanov@nginx.com     /*  of nxt_unit_read_buf_t */
3381548Smax.romanov@nginx.com     nxt_queue_t              awaiting_rbuf;
3391548Smax.romanov@nginx.com };
3401548Smax.romanov@nginx.com 
3411548Smax.romanov@nginx.com 
3421548Smax.romanov@nginx.com struct nxt_unit_mmaps_s {
3431548Smax.romanov@nginx.com     pthread_mutex_t          mutex;
3441548Smax.romanov@nginx.com     uint32_t                 size;
3451548Smax.romanov@nginx.com     uint32_t                 cap;
3461548Smax.romanov@nginx.com     nxt_atomic_t             allocated_chunks;
3471548Smax.romanov@nginx.com     nxt_unit_mmap_t          *elts;
3481548Smax.romanov@nginx.com };
3491548Smax.romanov@nginx.com 
3501548Smax.romanov@nginx.com 
351743Smax.romanov@nginx.com struct nxt_unit_impl_s {
352743Smax.romanov@nginx.com     nxt_unit_t               unit;
353743Smax.romanov@nginx.com     nxt_unit_callbacks_t     callbacks;
354743Smax.romanov@nginx.com 
3551543Smax.romanov@nginx.com     nxt_atomic_t             use_count;
3561980Smax.romanov@nginx.com     nxt_atomic_t             request_count;
3571543Smax.romanov@nginx.com 
358743Smax.romanov@nginx.com     uint32_t                 request_data_size;
3591320Smax.romanov@nginx.com     uint32_t                 shm_mmap_limit;
3601980Smax.romanov@nginx.com     uint32_t                 request_limit;
361743Smax.romanov@nginx.com 
362743Smax.romanov@nginx.com     pthread_mutex_t          mutex;
363743Smax.romanov@nginx.com 
364743Smax.romanov@nginx.com     nxt_lvlhsh_t             processes;        /* of nxt_unit_process_t */
365743Smax.romanov@nginx.com     nxt_lvlhsh_t             ports;            /* of nxt_unit_port_impl_t */
366743Smax.romanov@nginx.com 
3671544Smax.romanov@nginx.com     nxt_unit_port_t          *router_port;
3681547Smax.romanov@nginx.com     nxt_unit_port_t          *shared_port;
369743Smax.romanov@nginx.com 
370743Smax.romanov@nginx.com     nxt_queue_t              contexts;         /* of nxt_unit_ctx_impl_t */
371743Smax.romanov@nginx.com 
3721548Smax.romanov@nginx.com     nxt_unit_mmaps_t         incoming;
3731548Smax.romanov@nginx.com     nxt_unit_mmaps_t         outgoing;
3741548Smax.romanov@nginx.com 
375743Smax.romanov@nginx.com     pid_t                    pid;
376743Smax.romanov@nginx.com     int                      log_fd;
377743Smax.romanov@nginx.com 
378743Smax.romanov@nginx.com     nxt_unit_ctx_impl_t      main_ctx;
379743Smax.romanov@nginx.com };
380743Smax.romanov@nginx.com 
381743Smax.romanov@nginx.com 
382743Smax.romanov@nginx.com struct nxt_unit_port_impl_s {
383743Smax.romanov@nginx.com     nxt_unit_port_t          port;
384743Smax.romanov@nginx.com 
3851544Smax.romanov@nginx.com     nxt_atomic_t             use_count;
3861544Smax.romanov@nginx.com 
3871546Smax.romanov@nginx.com     /*  for nxt_unit_process_t.ports */
388743Smax.romanov@nginx.com     nxt_queue_link_t         link;
389743Smax.romanov@nginx.com     nxt_unit_process_t       *process;
3901545Smax.romanov@nginx.com 
3911545Smax.romanov@nginx.com     /*  of nxt_unit_request_info_impl_t */
3921545Smax.romanov@nginx.com     nxt_queue_t              awaiting_req;
3931545Smax.romanov@nginx.com 
3941545Smax.romanov@nginx.com     int                      ready;
3951555Smax.romanov@nginx.com 
3961555Smax.romanov@nginx.com     void                     *queue;
3971555Smax.romanov@nginx.com 
3981555Smax.romanov@nginx.com     int                      from_socket;
3991555Smax.romanov@nginx.com     nxt_unit_read_buf_t      *socket_rbuf;
400743Smax.romanov@nginx.com };
401743Smax.romanov@nginx.com 
402743Smax.romanov@nginx.com 
403743Smax.romanov@nginx.com struct nxt_unit_process_s {
404743Smax.romanov@nginx.com     pid_t                    pid;
405743Smax.romanov@nginx.com 
4061546Smax.romanov@nginx.com     nxt_queue_t              ports;            /* of nxt_unit_port_impl_t */
407743Smax.romanov@nginx.com 
408743Smax.romanov@nginx.com     nxt_unit_impl_t          *lib;
409743Smax.romanov@nginx.com 
410743Smax.romanov@nginx.com     nxt_atomic_t             use_count;
411743Smax.romanov@nginx.com 
412743Smax.romanov@nginx.com     uint32_t                 next_port_id;
413743Smax.romanov@nginx.com };
414743Smax.romanov@nginx.com 
415743Smax.romanov@nginx.com 
416743Smax.romanov@nginx.com /* Explicitly using 32 bit types to avoid possible alignment. */
417743Smax.romanov@nginx.com typedef struct {
418743Smax.romanov@nginx.com     int32_t   pid;
419743Smax.romanov@nginx.com     uint32_t  id;
420743Smax.romanov@nginx.com } nxt_unit_port_hash_id_t;
421743Smax.romanov@nginx.com 
422743Smax.romanov@nginx.com 
4231998St.nateldemoura@f5.com static pid_t  nxt_unit_pid;
4241998St.nateldemoura@f5.com 
4251998St.nateldemoura@f5.com 
426743Smax.romanov@nginx.com nxt_unit_ctx_t *
nxt_unit_init(nxt_unit_init_t * init)427743Smax.romanov@nginx.com nxt_unit_init(nxt_unit_init_t *init)
428743Smax.romanov@nginx.com {
4292014Smax.romanov@nginx.com     int              rc, queue_fd, shared_queue_fd;
4301555Smax.romanov@nginx.com     void             *mem;
4311980Smax.romanov@nginx.com     uint32_t         ready_stream, shm_limit, request_limit;
432743Smax.romanov@nginx.com     nxt_unit_ctx_t   *ctx;
433743Smax.romanov@nginx.com     nxt_unit_impl_t  *lib;
4342014Smax.romanov@nginx.com     nxt_unit_port_t  ready_port, router_port, read_port, shared_port;
435743Smax.romanov@nginx.com 
4361998St.nateldemoura@f5.com     nxt_unit_pid = getpid();
4371998St.nateldemoura@f5.com 
438743Smax.romanov@nginx.com     lib = nxt_unit_create(init);
439743Smax.romanov@nginx.com     if (nxt_slow_path(lib == NULL)) {
440743Smax.romanov@nginx.com         return NULL;
441743Smax.romanov@nginx.com     }
442743Smax.romanov@nginx.com 
4431555Smax.romanov@nginx.com     queue_fd = -1;
4441557Smax.romanov@nginx.com     mem = MAP_FAILED;
4452014Smax.romanov@nginx.com     shared_port.out_fd = -1;
4462024Smax.romanov@nginx.com     shared_port.data = NULL;
4471555Smax.romanov@nginx.com 
448743Smax.romanov@nginx.com     if (init->ready_port.id.pid != 0
449743Smax.romanov@nginx.com         && init->ready_stream != 0
450743Smax.romanov@nginx.com         && init->read_port.id.pid != 0)
451743Smax.romanov@nginx.com     {
452743Smax.romanov@nginx.com         ready_port = init->ready_port;
453743Smax.romanov@nginx.com         ready_stream = init->ready_stream;
4541543Smax.romanov@nginx.com         router_port = init->router_port;
455743Smax.romanov@nginx.com         read_port = init->read_port;
456743Smax.romanov@nginx.com         lib->log_fd = init->log_fd;
457743Smax.romanov@nginx.com 
458743Smax.romanov@nginx.com         nxt_unit_port_id_init(&ready_port.id, ready_port.id.pid,
459743Smax.romanov@nginx.com                               ready_port.id.id);
4601543Smax.romanov@nginx.com         nxt_unit_port_id_init(&router_port.id, router_port.id.pid,
4611543Smax.romanov@nginx.com                               router_port.id.id);
462743Smax.romanov@nginx.com         nxt_unit_port_id_init(&read_port.id, read_port.id.pid,
463743Smax.romanov@nginx.com                               read_port.id.id);
4641320Smax.romanov@nginx.com 
4652014Smax.romanov@nginx.com         shared_port.in_fd = init->shared_port_fd;
4662014Smax.romanov@nginx.com         shared_queue_fd = init->shared_queue_fd;
4672014Smax.romanov@nginx.com 
468743Smax.romanov@nginx.com     } else {
4691543Smax.romanov@nginx.com         rc = nxt_unit_read_env(&ready_port, &router_port, &read_port,
4702014Smax.romanov@nginx.com                                &shared_port.in_fd, &shared_queue_fd,
4711980Smax.romanov@nginx.com                                &lib->log_fd, &ready_stream, &shm_limit,
4721980Smax.romanov@nginx.com                                &request_limit);
473743Smax.romanov@nginx.com         if (nxt_slow_path(rc != NXT_UNIT_OK)) {
474743Smax.romanov@nginx.com             goto fail;
475743Smax.romanov@nginx.com         }
4761320Smax.romanov@nginx.com 
4771320Smax.romanov@nginx.com         lib->shm_mmap_limit = (shm_limit + PORT_MMAP_DATA_SIZE - 1)
4781320Smax.romanov@nginx.com                                 / PORT_MMAP_DATA_SIZE;
4791980Smax.romanov@nginx.com         lib->request_limit = request_limit;
4801320Smax.romanov@nginx.com     }
4811320Smax.romanov@nginx.com 
4821320Smax.romanov@nginx.com     if (nxt_slow_path(lib->shm_mmap_limit < 1)) {
4831320Smax.romanov@nginx.com         lib->shm_mmap_limit = 1;
484743Smax.romanov@nginx.com     }
485743Smax.romanov@nginx.com 
4861182St.nateldemoura@f5.com     lib->pid = read_port.id.pid;
4871998St.nateldemoura@f5.com     nxt_unit_pid = lib->pid;
4881544Smax.romanov@nginx.com 
489743Smax.romanov@nginx.com     ctx = &lib->main_ctx.ctx;
490743Smax.romanov@nginx.com 
4911557Smax.romanov@nginx.com     rc = nxt_unit_fd_blocking(router_port.out_fd);
4921557Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
4931557Smax.romanov@nginx.com         goto fail;
4941557Smax.romanov@nginx.com     }
4951557Smax.romanov@nginx.com 
4961555Smax.romanov@nginx.com     lib->router_port = nxt_unit_add_port(ctx, &router_port, NULL);
4971544Smax.romanov@nginx.com     if (nxt_slow_path(lib->router_port == NULL)) {
4981543Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to add router_port");
499743Smax.romanov@nginx.com 
500743Smax.romanov@nginx.com         goto fail;
501743Smax.romanov@nginx.com     }
502743Smax.romanov@nginx.com 
5031555Smax.romanov@nginx.com     queue_fd = nxt_unit_shm_open(ctx, sizeof(nxt_port_queue_t));
5041555Smax.romanov@nginx.com     if (nxt_slow_path(queue_fd == -1)) {
5051555Smax.romanov@nginx.com         goto fail;
5061555Smax.romanov@nginx.com     }
5071555Smax.romanov@nginx.com 
5081555Smax.romanov@nginx.com     mem = mmap(NULL, sizeof(nxt_port_queue_t),
5091555Smax.romanov@nginx.com                PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
5101555Smax.romanov@nginx.com     if (nxt_slow_path(mem == MAP_FAILED)) {
5111555Smax.romanov@nginx.com         nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", queue_fd,
5121555Smax.romanov@nginx.com                        strerror(errno), errno);
513743Smax.romanov@nginx.com 
514743Smax.romanov@nginx.com         goto fail;
515743Smax.romanov@nginx.com     }
516743Smax.romanov@nginx.com 
5171555Smax.romanov@nginx.com     nxt_port_queue_init(mem);
5181555Smax.romanov@nginx.com 
5191557Smax.romanov@nginx.com     rc = nxt_unit_fd_blocking(read_port.in_fd);
5201557Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
5211557Smax.romanov@nginx.com         goto fail;
5221557Smax.romanov@nginx.com     }
5231557Smax.romanov@nginx.com 
5241555Smax.romanov@nginx.com     lib->main_ctx.read_port = nxt_unit_add_port(ctx, &read_port, mem);
5251555Smax.romanov@nginx.com     if (nxt_slow_path(lib->main_ctx.read_port == NULL)) {
5261555Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to add read_port");
5271555Smax.romanov@nginx.com 
5281557Smax.romanov@nginx.com         goto fail;
5291557Smax.romanov@nginx.com     }
5301557Smax.romanov@nginx.com 
5311557Smax.romanov@nginx.com     rc = nxt_unit_fd_blocking(ready_port.out_fd);
5321557Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
5331555Smax.romanov@nginx.com         goto fail;
5341555Smax.romanov@nginx.com     }
5351555Smax.romanov@nginx.com 
5362014Smax.romanov@nginx.com     nxt_unit_port_id_init(&shared_port.id, read_port.id.pid,
5372014Smax.romanov@nginx.com                           NXT_UNIT_SHARED_PORT_ID);
5382014Smax.romanov@nginx.com 
5392014Smax.romanov@nginx.com     mem = mmap(NULL, sizeof(nxt_app_queue_t), PROT_READ | PROT_WRITE,
5402014Smax.romanov@nginx.com                MAP_SHARED, shared_queue_fd, 0);
5412014Smax.romanov@nginx.com     if (nxt_slow_path(mem == MAP_FAILED)) {
5422014Smax.romanov@nginx.com         nxt_unit_alert(ctx, "mmap(%d) failed: %s (%d)", shared_queue_fd,
5432014Smax.romanov@nginx.com                        strerror(errno), errno);
5442014Smax.romanov@nginx.com 
5452014Smax.romanov@nginx.com         goto fail;
5462014Smax.romanov@nginx.com     }
5472014Smax.romanov@nginx.com 
5482014Smax.romanov@nginx.com     nxt_unit_close(shared_queue_fd);
5492014Smax.romanov@nginx.com 
5502014Smax.romanov@nginx.com     lib->shared_port = nxt_unit_add_port(ctx, &shared_port, mem);
5512014Smax.romanov@nginx.com     if (nxt_slow_path(lib->shared_port == NULL)) {
5522014Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to add shared_port");
5532014Smax.romanov@nginx.com 
5542014Smax.romanov@nginx.com         goto fail;
5552014Smax.romanov@nginx.com     }
5562014Smax.romanov@nginx.com 
5571555Smax.romanov@nginx.com     rc = nxt_unit_ready(ctx, ready_port.out_fd, ready_stream, queue_fd);
558743Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
559743Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to send READY message");
560743Smax.romanov@nginx.com 
561743Smax.romanov@nginx.com         goto fail;
562743Smax.romanov@nginx.com     }
563743Smax.romanov@nginx.com 
5641556Smax.romanov@nginx.com     nxt_unit_close(ready_port.out_fd);
5651556Smax.romanov@nginx.com     nxt_unit_close(queue_fd);
5661543Smax.romanov@nginx.com 
567743Smax.romanov@nginx.com     return ctx;
568743Smax.romanov@nginx.com 
569743Smax.romanov@nginx.com fail:
570743Smax.romanov@nginx.com 
5711557Smax.romanov@nginx.com     if (mem != MAP_FAILED) {
5721557Smax.romanov@nginx.com         munmap(mem, sizeof(nxt_port_queue_t));
5731557Smax.romanov@nginx.com     }
5741557Smax.romanov@nginx.com 
5751555Smax.romanov@nginx.com     if (queue_fd != -1) {
5761556Smax.romanov@nginx.com         nxt_unit_close(queue_fd);
5771555Smax.romanov@nginx.com     }
5781555Smax.romanov@nginx.com 
5791547Smax.romanov@nginx.com     nxt_unit_ctx_release(&lib->main_ctx.ctx);
580743Smax.romanov@nginx.com 
581743Smax.romanov@nginx.com     return NULL;
582743Smax.romanov@nginx.com }
583743Smax.romanov@nginx.com 
584743Smax.romanov@nginx.com 
585743Smax.romanov@nginx.com static nxt_unit_impl_t *
nxt_unit_create(nxt_unit_init_t * init)586743Smax.romanov@nginx.com nxt_unit_create(nxt_unit_init_t *init)
587743Smax.romanov@nginx.com {
588743Smax.romanov@nginx.com     int                   rc;
589743Smax.romanov@nginx.com     nxt_unit_impl_t       *lib;
590743Smax.romanov@nginx.com     nxt_unit_callbacks_t  *cb;
591743Smax.romanov@nginx.com 
5921623Smax.romanov@nginx.com     lib = nxt_unit_malloc(NULL,
5931623Smax.romanov@nginx.com                           sizeof(nxt_unit_impl_t) + init->request_data_size);
594743Smax.romanov@nginx.com     if (nxt_slow_path(lib == NULL)) {
595743Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to allocate unit struct");
596743Smax.romanov@nginx.com 
597743Smax.romanov@nginx.com         return NULL;
598743Smax.romanov@nginx.com     }
599743Smax.romanov@nginx.com 
600743Smax.romanov@nginx.com     rc = pthread_mutex_init(&lib->mutex, NULL);
601743Smax.romanov@nginx.com     if (nxt_slow_path(rc != 0)) {
602743Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc);
603743Smax.romanov@nginx.com 
604743Smax.romanov@nginx.com         goto fail;
605743Smax.romanov@nginx.com     }
606743Smax.romanov@nginx.com 
607743Smax.romanov@nginx.com     lib->unit.data = init->data;
608743Smax.romanov@nginx.com     lib->callbacks = init->callbacks;
609743Smax.romanov@nginx.com 
610743Smax.romanov@nginx.com     lib->request_data_size = init->request_data_size;
6111320Smax.romanov@nginx.com     lib->shm_mmap_limit = (init->shm_limit + PORT_MMAP_DATA_SIZE - 1)
6121320Smax.romanov@nginx.com                             / PORT_MMAP_DATA_SIZE;
6131980Smax.romanov@nginx.com     lib->request_limit = init->request_limit;
614743Smax.romanov@nginx.com 
615743Smax.romanov@nginx.com     lib->processes.slot = NULL;
616743Smax.romanov@nginx.com     lib->ports.slot = NULL;
617743Smax.romanov@nginx.com 
618743Smax.romanov@nginx.com     lib->log_fd = STDERR_FILENO;
619743Smax.romanov@nginx.com 
620743Smax.romanov@nginx.com     nxt_queue_init(&lib->contexts);
621743Smax.romanov@nginx.com 
6221543Smax.romanov@nginx.com     lib->use_count = 0;
6231980Smax.romanov@nginx.com     lib->request_count = 0;
6241544Smax.romanov@nginx.com     lib->router_port = NULL;
6251547Smax.romanov@nginx.com     lib->shared_port = NULL;
6261543Smax.romanov@nginx.com 
6271175Smax.romanov@nginx.com     rc = nxt_unit_ctx_init(lib, &lib->main_ctx, init->ctx_data);
6281175Smax.romanov@nginx.com     if (nxt_slow_path(rc != NXT_UNIT_OK)) {
6291555Smax.romanov@nginx.com         pthread_mutex_destroy(&lib->mutex);
6301175Smax.romanov@nginx.com         goto fail;
6311175Smax.romanov@nginx.com     }
632743Smax.romanov@nginx.com 
633743Smax.romanov@nginx.com     cb = &lib->callbacks;
634743Smax.romanov@nginx.com 
635743Smax.romanov@nginx.com     if (cb->request_handler == NULL) {
636743Smax.romanov@nginx.com         nxt_unit_alert(NULL, "request_handler is NULL");
637743Smax.romanov@nginx.com 
6381555Smax.romanov@nginx.com         pthread_mutex_destroy(&lib->mutex);
639743Smax.romanov@nginx.com         goto fail;
640743Smax.romanov@nginx.com     }
641743Smax.romanov@nginx.com 
6421548Smax.romanov@nginx.com     nxt_unit_mmaps_init(&lib->incoming);
6431548Smax.romanov@nginx.com     nxt_unit_mmaps_init(&lib->outgoing);
6441548Smax.romanov@nginx.com 
645743Smax.romanov@nginx.com     return lib;
646743Smax.romanov@nginx.com 
647743Smax.romanov@nginx.com fail:
648743Smax.romanov@nginx.com 
6491623Smax.romanov@nginx.com     nxt_unit_free(NULL, lib);
650743Smax.romanov@nginx.com 
651743Smax.romanov@nginx.com     return NULL;
652743Smax.romanov@nginx.com }
653743Smax.romanov@nginx.com 
654743Smax.romanov@nginx.com 
6551175Smax.romanov@nginx.com static int
nxt_unit_ctx_init(nxt_unit_impl_t * lib,nxt_unit_ctx_impl_t * ctx_impl,void * data)656743Smax.romanov@nginx.com nxt_unit_ctx_init(nxt_unit_impl_t *lib, nxt_unit_ctx_impl_t *ctx_impl,
657743Smax.romanov@nginx.com     void *data)
658743Smax.romanov@nginx.com {
6591175Smax.romanov@nginx.com     int  rc;
6601175Smax.romanov@nginx.com 
661743Smax.romanov@nginx.com     ctx_impl->ctx.data = data;
662743Smax.romanov@nginx.com     ctx_impl->ctx.unit = &lib->unit;
663743Smax.romanov@nginx.com 
6641175Smax.romanov@nginx.com     rc = pthread_mutex_init(&ctx_impl->mutex, NULL);
6651175Smax.romanov@nginx.com     if (nxt_slow_path(rc != 0)) {
6661175Smax.romanov@nginx.com         nxt_unit_alert(NULL, "failed to initialize mutex (%d)", rc);
6671175Smax.romanov@nginx.com 
6681175Smax.romanov@nginx.com         return NXT_UNIT_ERROR;
6691175Smax.romanov@nginx.com     }
6701175Smax.romanov@nginx.com 
6711543Smax.romanov@nginx.com     nxt_unit_lib_use(lib);
6721543Smax.romanov@nginx.com 
6731663Smax.romanov@nginx.com     pthread_mutex_lock(&lib->mutex);
6741663Smax.romanov@nginx.com 
6751543Smax.romanov@nginx.com     nxt_queue_insert_tail(&lib->contexts, &ctx_impl->link);
6761543Smax.romanov@nginx.com 
6771663Smax.romanov@nginx.com     pthread_mutex_unlock(&lib->mutex);
6781663Smax.romanov@nginx.com 
6791543Smax.romanov@nginx.com     ctx_impl->use_count = 1;
6801545Smax.romanov@nginx.com     ctx_impl->wait_items = 0;
6811663Smax.romanov@nginx.com     ctx_impl->online = 1;
6821666Smax.romanov@nginx.com     ctx_impl->ready = 0;
6831980Smax.romanov@nginx.com     ctx_impl->quit_param = NXT_QUIT_GRACEFUL;
6841543Smax.romanov@nginx.com 
685743Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->free_req);
6861131Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->free_ws);
687743Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->active_req);
6881545Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->ready_req);
6891546Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->pending_rbuf);
6901546Smax.romanov@nginx.com     nxt_queue_init(&ctx_impl->free_rbuf);
691743Smax.romanov@nginx.com 
6921131Smax.romanov@nginx.com     ctx_impl->free_buf = NULL;
6931131Smax.romanov@nginx.com     nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[1]);
6941131Smax.romanov@nginx.com     nxt_unit_mmap_buf_insert(&ctx_impl->free_buf, &ctx_impl->ctx_buf[0]);
6951131Smax.romanov@nginx.com 
696743Smax.romanov@nginx.com     nxt_queue_insert_tail(&ctx_impl->free_req, &ctx_impl->req.link);
6971546Smax.romanov@nginx.com     nxt_queue_insert_tail(&ctx_impl->free_rbuf, &ctx_impl->ctx_read_buf.link);
6981546Smax.romanov@nginx.com 
6991546Smax.romanov@nginx.com     ctx_impl->ctx_read_buf.ctx_impl = ctx_impl;
7001321Smax.romanov@nginx.com 
701743Smax.romanov@nginx.com     ctx_impl->req.req.ctx = &ctx_impl->ctx;
702743Smax.romanov@nginx.com     ctx_impl->req.req.unit = &lib->unit;
703743Smax.romanov@nginx.com 
7041544Smax.romanov@nginx.com     ctx_impl->read_port = NULL;
7051131Smax.romanov@nginx.com     ctx_impl->requests.slot = 0;
7061175Smax.romanov@nginx.com 
7071175Smax.romanov@nginx.com     return NXT_UNIT_OK;
7081131Smax.romanov@nginx.com }
7091131Smax.romanov@nginx.com 
7101131Smax.romanov@nginx.com 
7111131Smax.romanov@nginx.com nxt_inline void
nxt_unit_ctx_use(nxt_unit_ctx_t * ctx)7121547Smax.romanov@nginx.com nxt_unit_ctx_use(nxt_unit_ctx_t *ctx)
7131543Smax.romanov@nginx.com {
7141547Smax.romanov@nginx.com     nxt_unit_ctx_impl_t  *ctx_impl;
7151547Smax.romanov@nginx.com 
7161547Smax.romanov@nginx.com     ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx);
7171547Smax.romanov@nginx.com 
7181543Smax.romanov@nginx.com     nxt_atomic_fetch_add(&ctx_impl->use_count, 1);
7191543Smax.romanov@nginx.com }
7201543Smax.romanov@nginx.com 
7211543Smax.romanov@nginx.com 
7221543Smax.romanov@nginx.com nxt_inline void
nxt_unit_ctx_release(nxt_unit_ctx_t * ctx)7231547Smax.romanov@nginx.com nxt_unit_ctx_release(nxt_unit_ctx_t *ctx)
7241543Smax.romanov@nginx.com {
7251547Smax.romanov@nginx.com     long                 c;
7261547Smax.romanov@nginx.com     nxt_unit_ctx_impl_t  *ctx_impl;
7271547Smax.romanov@nginx.com 
7281547Smax.romanov@nginx.com     ctx_impl = nxt_container_of(ctx, nxt_unit_ctx_impl_t, ctx);
7291543Smax.romanov@nginx.com 
7301543Smax.romanov@nginx.com     c = nxt_atomic_fetch_add(&ctx_impl->use_count, -1);
7311543Smax.romanov@nginx.com 
7321543Smax.romanov@nginx.com     if (c == 1) {
7331543Smax.romanov@nginx.com         nxt_unit_ctx_free(ctx_impl);
7341543Smax.romanov@nginx.com     }
7351543Smax.romanov@nginx.com }
7361543Smax.romanov@nginx.com 
7371543Smax.romanov@nginx.com 
7381543Smax.romanov@nginx.com nxt_inline void
nxt_unit_lib_use(nxt_unit_impl_t * lib)7391543Smax.romanov@nginx.com nxt_unit_lib_use(nxt_unit_impl_t *lib)
7401543Smax.romanov@nginx.com {
7411543Smax.romanov@nginx.com     nxt_atomic_fetch_add(&lib->use_count, 1);
7421543Smax.romanov@nginx.com }
7431543Smax.romanov@nginx.com 
7441543Smax.romanov@nginx.com 
7451543Smax.romanov@nginx.com nxt_inline void
nxt_unit_lib_release(nxt_unit_impl_t * lib)7461543Smax.romanov@nginx.com nxt_unit_lib_release(nxt_unit_impl_t *lib)
7471543Smax.romanov@nginx.com {
7481543Smax.romanov@nginx.com     long                c;
7491543Smax.romanov@nginx.com     nxt_unit_process_t  *process;
7501543Smax.romanov@nginx.com 
7511543Smax.romanov@nginx.com     c = nxt_atomic_fetch_add(&lib->use_count, -1);
7521543Smax.romanov@nginx.com 
7531543Smax.romanov@nginx.com     if (c == 1) {
7541543Smax.romanov@nginx.com         for ( ;; ) {
7551543Smax.romanov@nginx.com             pthread_mutex_lock(&lib->mutex);
7561543Smax.romanov@nginx.com 
7571543Smax.romanov@nginx.com             process = nxt_unit_process_pop_first(lib);
7581543Smax.romanov@nginx.com             if (process == NULL) {
7591543Smax.romanov@nginx.com                 pthread_mutex_unlock(&lib->mutex);
7601543Smax.romanov@nginx.com 
7611543Smax.romanov@nginx.com                 break;
7621543Smax.romanov@nginx.com             }
7631543Smax.romanov@nginx.com 
7641543Smax.romanov@nginx.com             nxt_unit_remove_process(lib, process);
7651543Smax.romanov@nginx.com         }
7661543Smax.romanov@nginx.com 
7671543Smax.romanov@nginx.com         pthread_mutex_destroy(&lib->mutex);
7681543Smax.romanov@nginx.com 
7691544Smax.romanov@nginx.com         if (nxt_fast_path(lib->router_port != NULL)) {
7701544Smax.romanov@nginx.com             nxt_unit_port_release(lib->router_port);
7711544Smax.romanov@nginx.com         }
7721544Smax.romanov@nginx.com 
773