xref: /unit/src/nxt_port_memory.c (revision 141)
180Smax.romanov@nginx.com 
280Smax.romanov@nginx.com /*
380Smax.romanov@nginx.com  * Copyright (C) Max Romanov
480Smax.romanov@nginx.com  * Copyright (C) NGINX, Inc.
580Smax.romanov@nginx.com  */
642Smax.romanov@nginx.com 
742Smax.romanov@nginx.com #include <nxt_main.h>
842Smax.romanov@nginx.com 
942Smax.romanov@nginx.com #if (NXT_HAVE_MEMFD_CREATE)
1042Smax.romanov@nginx.com 
1142Smax.romanov@nginx.com #include <linux/memfd.h>
1242Smax.romanov@nginx.com #include <unistd.h>
1342Smax.romanov@nginx.com #include <sys/syscall.h>
1442Smax.romanov@nginx.com 
1542Smax.romanov@nginx.com #endif
1642Smax.romanov@nginx.com 
1780Smax.romanov@nginx.com #include <nxt_port_memory_int.h>
1842Smax.romanov@nginx.com 
1942Smax.romanov@nginx.com void
2042Smax.romanov@nginx.com nxt_port_mmap_destroy(nxt_port_mmap_t *port_mmap)
2142Smax.romanov@nginx.com {
2280Smax.romanov@nginx.com     if (port_mmap->hdr != NULL) {
2380Smax.romanov@nginx.com         nxt_mem_munmap(port_mmap->hdr, PORT_MMAP_SIZE);
2480Smax.romanov@nginx.com         port_mmap->hdr = NULL;
2542Smax.romanov@nginx.com     }
2642Smax.romanov@nginx.com }
2742Smax.romanov@nginx.com 
2842Smax.romanov@nginx.com 
29*141Smax.romanov@nginx.com static nxt_array_t *
30*141Smax.romanov@nginx.com nxt_port_mmaps_create()
31*141Smax.romanov@nginx.com {
32*141Smax.romanov@nginx.com     nxt_mp_t  *mp;
33*141Smax.romanov@nginx.com 
34*141Smax.romanov@nginx.com     mp = nxt_mp_create(1024, 128, 256, 32);
35*141Smax.romanov@nginx.com 
36*141Smax.romanov@nginx.com     if (nxt_slow_path(mp == NULL)) {
37*141Smax.romanov@nginx.com         return NULL;
38*141Smax.romanov@nginx.com     }
39*141Smax.romanov@nginx.com 
40*141Smax.romanov@nginx.com     return nxt_array_create(mp, 1, sizeof(nxt_port_mmap_t));
41*141Smax.romanov@nginx.com }
42*141Smax.romanov@nginx.com 
43*141Smax.romanov@nginx.com 
44*141Smax.romanov@nginx.com static nxt_port_mmap_t *
45*141Smax.romanov@nginx.com nxt_port_mmap_add(nxt_array_t *port_mmaps)
46*141Smax.romanov@nginx.com {
47*141Smax.romanov@nginx.com     nxt_mp_thread_adopt(port_mmaps->mem_pool);
48*141Smax.romanov@nginx.com 
49*141Smax.romanov@nginx.com     return nxt_array_zero_add(port_mmaps);
50*141Smax.romanov@nginx.com }
51*141Smax.romanov@nginx.com 
52*141Smax.romanov@nginx.com 
53*141Smax.romanov@nginx.com void
54*141Smax.romanov@nginx.com nxt_port_mmaps_destroy(nxt_array_t *port_mmaps, nxt_bool_t destroy_pool)
55*141Smax.romanov@nginx.com {
56*141Smax.romanov@nginx.com     uint32_t         i;
57*141Smax.romanov@nginx.com     nxt_port_mmap_t  *port_mmap;
58*141Smax.romanov@nginx.com 
59*141Smax.romanov@nginx.com     if (port_mmaps == NULL) {
60*141Smax.romanov@nginx.com         return;
61*141Smax.romanov@nginx.com     }
62*141Smax.romanov@nginx.com 
63*141Smax.romanov@nginx.com     nxt_mp_thread_adopt(port_mmaps->mem_pool);
64*141Smax.romanov@nginx.com 
65*141Smax.romanov@nginx.com     port_mmap = port_mmaps->elts;
66*141Smax.romanov@nginx.com 
67*141Smax.romanov@nginx.com     for (i = 0; i < port_mmaps->nelts; i++) {
68*141Smax.romanov@nginx.com         nxt_port_mmap_destroy(port_mmap);
69*141Smax.romanov@nginx.com     }
70*141Smax.romanov@nginx.com 
71*141Smax.romanov@nginx.com     port_mmaps->nelts = 0;
72*141Smax.romanov@nginx.com 
73*141Smax.romanov@nginx.com     if (destroy_pool != 0) {
74*141Smax.romanov@nginx.com         nxt_mp_destroy(port_mmaps->mem_pool);
75*141Smax.romanov@nginx.com     }
76*141Smax.romanov@nginx.com }
77*141Smax.romanov@nginx.com 
78*141Smax.romanov@nginx.com 
7942Smax.romanov@nginx.com static void
8042Smax.romanov@nginx.com nxt_port_mmap_buf_completion(nxt_task_t *task, void *obj, void *data)
8142Smax.romanov@nginx.com {
8242Smax.romanov@nginx.com     u_char                  *p;
8365Sigor@sysoev.ru     nxt_mp_t                *mp;
8442Smax.romanov@nginx.com     nxt_buf_t               *b;
8542Smax.romanov@nginx.com     nxt_chunk_id_t          c;
8642Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
8742Smax.romanov@nginx.com 
88122Smax.romanov@nginx.com     if (nxt_buf_ts_handle(task, obj, data)) {
89122Smax.romanov@nginx.com         return;
90122Smax.romanov@nginx.com     }
91122Smax.romanov@nginx.com 
9242Smax.romanov@nginx.com     b = obj;
9342Smax.romanov@nginx.com 
9442Smax.romanov@nginx.com     nxt_debug(task, "mmap buf completion: %p %p", b, b->mem.start);
9542Smax.romanov@nginx.com 
9642Smax.romanov@nginx.com     mp = b->data;
9742Smax.romanov@nginx.com 
9879Smax.romanov@nginx.com #if (NXT_DEBUG)
9979Smax.romanov@nginx.com     if (nxt_slow_path(data != b->parent)) {
10079Smax.romanov@nginx.com         nxt_log_alert(task->log, "completion data (%p) != b->parent (%p)",
10179Smax.romanov@nginx.com                       data, b->parent);
10279Smax.romanov@nginx.com         nxt_abort();
10379Smax.romanov@nginx.com     }
10479Smax.romanov@nginx.com #endif
10579Smax.romanov@nginx.com 
10680Smax.romanov@nginx.com     hdr = data;
10742Smax.romanov@nginx.com 
10842Smax.romanov@nginx.com     if (b->is_port_mmap_sent && b->mem.pos > b->mem.start) {
10942Smax.romanov@nginx.com         /*
11042Smax.romanov@nginx.com          * Chunks until b->mem.pos has been sent to other side,
11142Smax.romanov@nginx.com          * let's release rest (if any).
11242Smax.romanov@nginx.com          */
11342Smax.romanov@nginx.com         p = b->mem.pos - 1;
11480Smax.romanov@nginx.com         c = nxt_port_mmap_chunk_id(hdr, p) + 1;
11580Smax.romanov@nginx.com         p = nxt_port_mmap_chunk_start(hdr, c);
116*141Smax.romanov@nginx.com 
11742Smax.romanov@nginx.com     } else {
11842Smax.romanov@nginx.com         p = b->mem.start;
11980Smax.romanov@nginx.com         c = nxt_port_mmap_chunk_id(hdr, p);
12042Smax.romanov@nginx.com     }
12142Smax.romanov@nginx.com 
12242Smax.romanov@nginx.com     while (p < b->mem.end) {
12342Smax.romanov@nginx.com         nxt_port_mmap_set_chunk_free(hdr, c);
12442Smax.romanov@nginx.com 
12542Smax.romanov@nginx.com         p += PORT_MMAP_CHUNK_SIZE;
12642Smax.romanov@nginx.com         c++;
12742Smax.romanov@nginx.com     }
12842Smax.romanov@nginx.com 
129122Smax.romanov@nginx.com     nxt_mp_release(mp, b);
13042Smax.romanov@nginx.com }
13142Smax.romanov@nginx.com 
13242Smax.romanov@nginx.com 
13380Smax.romanov@nginx.com nxt_port_mmap_header_t *
13442Smax.romanov@nginx.com nxt_port_incoming_port_mmap(nxt_task_t *task, nxt_process_t *process,
13542Smax.romanov@nginx.com     nxt_fd_t fd)
13642Smax.romanov@nginx.com {
13780Smax.romanov@nginx.com     void                    *mem;
13880Smax.romanov@nginx.com     struct stat             mmap_stat;
13980Smax.romanov@nginx.com     nxt_port_mmap_t         *port_mmap;
14080Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
14142Smax.romanov@nginx.com 
14242Smax.romanov@nginx.com     nxt_debug(task, "got new mmap fd #%FD from process %PI",
14342Smax.romanov@nginx.com               fd, process->pid);
14442Smax.romanov@nginx.com 
14580Smax.romanov@nginx.com     port_mmap = NULL;
14680Smax.romanov@nginx.com     hdr = NULL;
14780Smax.romanov@nginx.com 
14842Smax.romanov@nginx.com     if (fstat(fd, &mmap_stat) == -1) {
14942Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "fstat(%FD) failed %E", fd, nxt_errno);
15042Smax.romanov@nginx.com 
15142Smax.romanov@nginx.com         return NULL;
15242Smax.romanov@nginx.com     }
15342Smax.romanov@nginx.com 
15490Smax.romanov@nginx.com     nxt_thread_mutex_lock(&process->incoming_mutex);
15590Smax.romanov@nginx.com 
15642Smax.romanov@nginx.com     if (process->incoming == NULL) {
157*141Smax.romanov@nginx.com         process->incoming = nxt_port_mmaps_create();
15842Smax.romanov@nginx.com     }
15942Smax.romanov@nginx.com 
16042Smax.romanov@nginx.com     if (nxt_slow_path(process->incoming == NULL)) {
16142Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "failed to allocate incoming array");
16242Smax.romanov@nginx.com 
16380Smax.romanov@nginx.com         goto fail;
16442Smax.romanov@nginx.com     }
16542Smax.romanov@nginx.com 
166*141Smax.romanov@nginx.com     port_mmap = nxt_port_mmap_add(process->incoming);
16742Smax.romanov@nginx.com     if (nxt_slow_path(port_mmap == NULL)) {
16842Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "failed to add mmap to incoming array");
16942Smax.romanov@nginx.com 
17080Smax.romanov@nginx.com         goto fail;
17142Smax.romanov@nginx.com     }
17242Smax.romanov@nginx.com 
17380Smax.romanov@nginx.com     mem = nxt_mem_mmap(NULL, mmap_stat.st_size,
17480Smax.romanov@nginx.com                        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
17542Smax.romanov@nginx.com 
17680Smax.romanov@nginx.com     if (nxt_slow_path(mem == MAP_FAILED)) {
17742Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "mmap() failed %E", nxt_errno);
17842Smax.romanov@nginx.com 
17980Smax.romanov@nginx.com         port_mmap = NULL;
18042Smax.romanov@nginx.com 
18180Smax.romanov@nginx.com         goto fail;
18242Smax.romanov@nginx.com     }
18342Smax.romanov@nginx.com 
18480Smax.romanov@nginx.com     port_mmap->hdr = mem;
18580Smax.romanov@nginx.com     hdr = port_mmap->hdr;
18680Smax.romanov@nginx.com 
18780Smax.romanov@nginx.com     if (nxt_slow_path(port_mmap->hdr->id != process->incoming->nelts - 1)) {
18880Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "port mmap id mismatch (%d != %d)",
18980Smax.romanov@nginx.com                 port_mmap->hdr->id, process->incoming->nelts - 1);
190*141Smax.romanov@nginx.com         nxt_abort();
19180Smax.romanov@nginx.com     }
19280Smax.romanov@nginx.com 
19380Smax.romanov@nginx.com fail:
19480Smax.romanov@nginx.com 
19590Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&process->incoming_mutex);
19690Smax.romanov@nginx.com 
19780Smax.romanov@nginx.com     return hdr;
19842Smax.romanov@nginx.com }
19942Smax.romanov@nginx.com 
20042Smax.romanov@nginx.com 
20142Smax.romanov@nginx.com static void
20242Smax.romanov@nginx.com nxt_port_mmap_send_fd_buf_completion(nxt_task_t *task, void *obj, void *data)
20342Smax.romanov@nginx.com {
20480Smax.romanov@nginx.com     nxt_fd_t   fd;
20580Smax.romanov@nginx.com     nxt_buf_t  *b;
20680Smax.romanov@nginx.com     nxt_mp_t   *mp;
20742Smax.romanov@nginx.com 
208122Smax.romanov@nginx.com     if (nxt_buf_ts_handle(task, obj, data)) {
209122Smax.romanov@nginx.com         return;
210122Smax.romanov@nginx.com     }
211122Smax.romanov@nginx.com 
21242Smax.romanov@nginx.com     b = obj;
21379Smax.romanov@nginx.com     mp = b->data;
21480Smax.romanov@nginx.com     fd = (nxt_fd_t) (intptr_t) data;
21542Smax.romanov@nginx.com 
21679Smax.romanov@nginx.com #if (NXT_DEBUG)
21779Smax.romanov@nginx.com     if (nxt_slow_path(data != b->parent)) {
21879Smax.romanov@nginx.com         nxt_log_alert(task->log, "completion data (%p) != b->parent (%p)",
21979Smax.romanov@nginx.com                       data, b->parent);
22079Smax.romanov@nginx.com         nxt_abort();
22179Smax.romanov@nginx.com     }
22279Smax.romanov@nginx.com #endif
22342Smax.romanov@nginx.com 
22480Smax.romanov@nginx.com     nxt_debug(task, "mmap fd %FD has been sent", fd);
22579Smax.romanov@nginx.com 
22680Smax.romanov@nginx.com     nxt_fd_close(fd);
22742Smax.romanov@nginx.com 
228122Smax.romanov@nginx.com     nxt_mp_release(mp, b);
22942Smax.romanov@nginx.com }
23042Smax.romanov@nginx.com 
23142Smax.romanov@nginx.com 
23280Smax.romanov@nginx.com static nxt_port_mmap_header_t *
23342Smax.romanov@nginx.com nxt_port_new_port_mmap(nxt_task_t *task, nxt_process_t *process,
23442Smax.romanov@nginx.com     nxt_port_t *port)
23542Smax.romanov@nginx.com {
23680Smax.romanov@nginx.com     void                    *mem;
23742Smax.romanov@nginx.com     u_char                  *p, name[64];
23880Smax.romanov@nginx.com     nxt_fd_t                fd;
23942Smax.romanov@nginx.com     nxt_buf_t               *b;
24042Smax.romanov@nginx.com     nxt_port_mmap_t         *port_mmap;
24142Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
24242Smax.romanov@nginx.com 
24380Smax.romanov@nginx.com     port_mmap = NULL;
24480Smax.romanov@nginx.com 
24542Smax.romanov@nginx.com     if (process->outgoing == NULL) {
246*141Smax.romanov@nginx.com         process->outgoing = nxt_port_mmaps_create();
24742Smax.romanov@nginx.com     }
24842Smax.romanov@nginx.com 
24942Smax.romanov@nginx.com     if (nxt_slow_path(process->outgoing == NULL)) {
25042Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "failed to allocate outgoing array");
25142Smax.romanov@nginx.com 
25242Smax.romanov@nginx.com         return NULL;
25342Smax.romanov@nginx.com     }
25442Smax.romanov@nginx.com 
255*141Smax.romanov@nginx.com     port_mmap = nxt_port_mmap_add(process->outgoing);
25642Smax.romanov@nginx.com     if (nxt_slow_path(port_mmap == NULL)) {
25742Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN,
25842Smax.romanov@nginx.com                 "failed to add port mmap to outgoing array");
25942Smax.romanov@nginx.com 
26042Smax.romanov@nginx.com         return NULL;
26142Smax.romanov@nginx.com     }
26242Smax.romanov@nginx.com 
26376Smax.romanov@nginx.com     p = nxt_sprintf(name, name + sizeof(name), "/nginext.%PI.%uxD",
264138Sigor@sysoev.ru                     nxt_pid, nxt_random(&task->thread->random));
26542Smax.romanov@nginx.com     *p = '\0';
26642Smax.romanov@nginx.com 
26742Smax.romanov@nginx.com #if (NXT_HAVE_MEMFD_CREATE)
26880Smax.romanov@nginx.com     fd = syscall(SYS_memfd_create, name, MFD_CLOEXEC);
26942Smax.romanov@nginx.com 
27080Smax.romanov@nginx.com     if (nxt_slow_path(fd == -1)) {
27142Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_CRIT, "memfd_create(%s) failed %E",
27242Smax.romanov@nginx.com                 name, nxt_errno);
27342Smax.romanov@nginx.com 
27442Smax.romanov@nginx.com         goto remove_fail;
27542Smax.romanov@nginx.com     }
27642Smax.romanov@nginx.com 
27780Smax.romanov@nginx.com     nxt_debug(task, "memfd_create(%s): %FD", name, fd);
27842Smax.romanov@nginx.com 
27942Smax.romanov@nginx.com #elif (NXT_HAVE_SHM_OPEN)
28042Smax.romanov@nginx.com     shm_unlink((char *) name); // just in case
28142Smax.romanov@nginx.com 
28280Smax.romanov@nginx.com     fd = shm_open((char *) name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
28342Smax.romanov@nginx.com 
28480Smax.romanov@nginx.com     nxt_debug(task, "shm_open(%s): %FD", name, fd);
28542Smax.romanov@nginx.com 
28680Smax.romanov@nginx.com     if (nxt_slow_path(fd == -1)) {
28742Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_CRIT, "shm_open(%s) failed %E", name, nxt_errno);
28842Smax.romanov@nginx.com 
28942Smax.romanov@nginx.com         goto remove_fail;
29042Smax.romanov@nginx.com     }
29142Smax.romanov@nginx.com 
29242Smax.romanov@nginx.com     if (nxt_slow_path(shm_unlink((char *) name) == -1)) {
29342Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "shm_unlink(%s) failed %E", name,
29442Smax.romanov@nginx.com                 nxt_errno);
29542Smax.romanov@nginx.com     }
29642Smax.romanov@nginx.com #endif
29742Smax.romanov@nginx.com 
29880Smax.romanov@nginx.com     if (nxt_slow_path(ftruncate(fd, PORT_MMAP_SIZE) == -1)) {
29942Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN, "ftruncate() failed %E", nxt_errno);
30042Smax.romanov@nginx.com 
30142Smax.romanov@nginx.com         goto remove_fail;
30242Smax.romanov@nginx.com     }
30342Smax.romanov@nginx.com 
30480Smax.romanov@nginx.com     mem = nxt_mem_mmap(NULL, PORT_MMAP_SIZE,
30580Smax.romanov@nginx.com                        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
30642Smax.romanov@nginx.com 
30780Smax.romanov@nginx.com     if (nxt_slow_path(mem == MAP_FAILED)) {
30842Smax.romanov@nginx.com         goto remove_fail;
30942Smax.romanov@nginx.com     }
31042Smax.romanov@nginx.com 
31180Smax.romanov@nginx.com     port_mmap->hdr = mem;
31280Smax.romanov@nginx.com 
313122Smax.romanov@nginx.com     b = nxt_buf_mem_ts_alloc(task, port->mem_pool, 0);
31479Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
31579Smax.romanov@nginx.com         goto remove_fail;
31679Smax.romanov@nginx.com     }
31779Smax.romanov@nginx.com 
31879Smax.romanov@nginx.com     b->completion_handler = nxt_port_mmap_send_fd_buf_completion;
31980Smax.romanov@nginx.com     b->parent = (void *) (intptr_t) fd;
32079Smax.romanov@nginx.com 
32142Smax.romanov@nginx.com     /* Init segment header. */
32280Smax.romanov@nginx.com     hdr = port_mmap->hdr;
32342Smax.romanov@nginx.com 
32442Smax.romanov@nginx.com     nxt_memset(hdr->free_map, 0xFFU, sizeof(hdr->free_map));
32542Smax.romanov@nginx.com 
32680Smax.romanov@nginx.com     hdr->id = process->outgoing->nelts - 1;
32780Smax.romanov@nginx.com     hdr->pid = process->pid;
32880Smax.romanov@nginx.com 
32980Smax.romanov@nginx.com     /* Mark first chunk as busy */
33080Smax.romanov@nginx.com     nxt_port_mmap_set_chunk_busy(hdr, 0);
33180Smax.romanov@nginx.com 
33242Smax.romanov@nginx.com     /* Mark as busy chunk followed the last available chunk. */
33342Smax.romanov@nginx.com     nxt_port_mmap_set_chunk_busy(hdr, PORT_MMAP_CHUNK_COUNT);
33442Smax.romanov@nginx.com 
33580Smax.romanov@nginx.com     nxt_debug(task, "send mmap fd %FD to process %PI", fd,
33642Smax.romanov@nginx.com               port->pid);
33742Smax.romanov@nginx.com 
33842Smax.romanov@nginx.com     /* TODO handle error */
33980Smax.romanov@nginx.com     (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_MMAP, fd, 0, 0, b);
34042Smax.romanov@nginx.com 
34142Smax.romanov@nginx.com     nxt_log(task, NXT_LOG_DEBUG, "new mmap #%D created for %PI -> %PI",
34280Smax.romanov@nginx.com             hdr->id, nxt_pid, process->pid);
34342Smax.romanov@nginx.com 
34480Smax.romanov@nginx.com     return hdr;
34542Smax.romanov@nginx.com 
34642Smax.romanov@nginx.com remove_fail:
34742Smax.romanov@nginx.com 
34842Smax.romanov@nginx.com     nxt_array_remove(process->outgoing, port_mmap);
34942Smax.romanov@nginx.com 
35042Smax.romanov@nginx.com     return NULL;
35142Smax.romanov@nginx.com }
35242Smax.romanov@nginx.com 
35342Smax.romanov@nginx.com 
35480Smax.romanov@nginx.com static nxt_port_mmap_header_t *
35542Smax.romanov@nginx.com nxt_port_mmap_get(nxt_task_t *task, nxt_port_t *port, nxt_chunk_id_t *c,
35642Smax.romanov@nginx.com     size_t size)
35742Smax.romanov@nginx.com {
35880Smax.romanov@nginx.com     nxt_array_t             *outgoing;
35980Smax.romanov@nginx.com     nxt_process_t           *process;
36080Smax.romanov@nginx.com     nxt_port_mmap_t         *port_mmap;
36180Smax.romanov@nginx.com     nxt_port_mmap_t         *end_port_mmap;
36280Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
36342Smax.romanov@nginx.com 
36480Smax.romanov@nginx.com     process = port->process;
36542Smax.romanov@nginx.com     if (nxt_slow_path(process == NULL)) {
36642Smax.romanov@nginx.com         return NULL;
36742Smax.romanov@nginx.com     }
36842Smax.romanov@nginx.com 
36942Smax.romanov@nginx.com     *c = 0;
37080Smax.romanov@nginx.com     port_mmap = NULL;
37180Smax.romanov@nginx.com     hdr = NULL;
37242Smax.romanov@nginx.com 
37390Smax.romanov@nginx.com     nxt_thread_mutex_lock(&process->outgoing_mutex);
37490Smax.romanov@nginx.com 
37542Smax.romanov@nginx.com     if (process->outgoing == NULL) {
37680Smax.romanov@nginx.com         hdr = nxt_port_new_port_mmap(task, process, port);
37780Smax.romanov@nginx.com 
37880Smax.romanov@nginx.com         goto unlock_return;
37942Smax.romanov@nginx.com     }
38042Smax.romanov@nginx.com 
38142Smax.romanov@nginx.com     outgoing = process->outgoing;
38242Smax.romanov@nginx.com     port_mmap = outgoing->elts;
38342Smax.romanov@nginx.com     end_port_mmap = port_mmap + outgoing->nelts;
38442Smax.romanov@nginx.com 
38542Smax.romanov@nginx.com     while (port_mmap < end_port_mmap) {
38642Smax.romanov@nginx.com 
38780Smax.romanov@nginx.com         if (nxt_port_mmap_get_free_chunk(port_mmap->hdr, c)) {
38880Smax.romanov@nginx.com             hdr = port_mmap->hdr;
38980Smax.romanov@nginx.com 
39080Smax.romanov@nginx.com             goto unlock_return;
39142Smax.romanov@nginx.com         }
39242Smax.romanov@nginx.com 
39342Smax.romanov@nginx.com         port_mmap++;
39442Smax.romanov@nginx.com     }
39542Smax.romanov@nginx.com 
39642Smax.romanov@nginx.com     /* TODO introduce port_mmap limit and release wait. */
39780Smax.romanov@nginx.com 
39880Smax.romanov@nginx.com     hdr = nxt_port_new_port_mmap(task, process, port);
39980Smax.romanov@nginx.com 
40080Smax.romanov@nginx.com unlock_return:
40180Smax.romanov@nginx.com 
40290Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&process->outgoing_mutex);
40390Smax.romanov@nginx.com 
40480Smax.romanov@nginx.com     return hdr;
40542Smax.romanov@nginx.com }
40642Smax.romanov@nginx.com 
40742Smax.romanov@nginx.com 
40880Smax.romanov@nginx.com static nxt_port_mmap_header_t *
40942Smax.romanov@nginx.com nxt_port_get_port_incoming_mmap(nxt_task_t *task, nxt_pid_t spid, uint32_t id)
41042Smax.romanov@nginx.com {
41180Smax.romanov@nginx.com     nxt_array_t             *incoming;
41280Smax.romanov@nginx.com     nxt_process_t           *process;
41380Smax.romanov@nginx.com     nxt_port_mmap_t         *port_mmap;
41480Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
41542Smax.romanov@nginx.com 
41642Smax.romanov@nginx.com     process = nxt_runtime_process_get(task->thread->runtime, spid);
41742Smax.romanov@nginx.com     if (nxt_slow_path(process == NULL)) {
41842Smax.romanov@nginx.com         return NULL;
41942Smax.romanov@nginx.com     }
42042Smax.romanov@nginx.com 
42180Smax.romanov@nginx.com     hdr = NULL;
42280Smax.romanov@nginx.com 
42390Smax.romanov@nginx.com     nxt_thread_mutex_lock(&process->incoming_mutex);
42490Smax.romanov@nginx.com 
42542Smax.romanov@nginx.com     incoming = process->incoming;
42680Smax.romanov@nginx.com 
42780Smax.romanov@nginx.com     if (nxt_fast_path(incoming != NULL && incoming->nelts > id)) {
42880Smax.romanov@nginx.com         port_mmap = incoming->elts;
42980Smax.romanov@nginx.com         hdr = port_mmap[id].hdr;
43080Smax.romanov@nginx.com     } else {
43180Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN,
43280Smax.romanov@nginx.com                 "failed to get incoming mmap #%d for process %PI", id, spid);
43342Smax.romanov@nginx.com     }
43442Smax.romanov@nginx.com 
43590Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&process->incoming_mutex);
43690Smax.romanov@nginx.com 
43780Smax.romanov@nginx.com     return hdr;
43842Smax.romanov@nginx.com }
43942Smax.romanov@nginx.com 
44042Smax.romanov@nginx.com 
44142Smax.romanov@nginx.com nxt_buf_t *
44242Smax.romanov@nginx.com nxt_port_mmap_get_buf(nxt_task_t *task, nxt_port_t *port, size_t size)
44342Smax.romanov@nginx.com {
44442Smax.romanov@nginx.com     size_t                  nchunks;
44542Smax.romanov@nginx.com     nxt_buf_t               *b;
44642Smax.romanov@nginx.com     nxt_chunk_id_t          c;
44742Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
44842Smax.romanov@nginx.com 
44942Smax.romanov@nginx.com     nxt_debug(task, "request %z bytes shm buffer", size);
45042Smax.romanov@nginx.com 
45180Smax.romanov@nginx.com     if (nxt_slow_path(size > PORT_MMAP_DATA_SIZE)) {
45280Smax.romanov@nginx.com         nxt_debug(task, "requested size (%z bytes) too big", size);
45380Smax.romanov@nginx.com         return NULL;
45480Smax.romanov@nginx.com     }
45580Smax.romanov@nginx.com 
456122Smax.romanov@nginx.com     b = nxt_buf_mem_ts_alloc(task, port->mem_pool, 0);
45742Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
45842Smax.romanov@nginx.com         return NULL;
45942Smax.romanov@nginx.com     }
46042Smax.romanov@nginx.com 
46142Smax.romanov@nginx.com     b->completion_handler = nxt_port_mmap_buf_completion;
46242Smax.romanov@nginx.com     nxt_buf_set_port_mmap(b);
46342Smax.romanov@nginx.com 
46480Smax.romanov@nginx.com     hdr = nxt_port_mmap_get(task, port, &c, size);
46580Smax.romanov@nginx.com     if (nxt_slow_path(hdr == NULL)) {
466122Smax.romanov@nginx.com         nxt_mp_release(port->mem_pool, b);
46742Smax.romanov@nginx.com         return NULL;
46842Smax.romanov@nginx.com     }
46942Smax.romanov@nginx.com 
47080Smax.romanov@nginx.com     b->parent = hdr;
471122Smax.romanov@nginx.com 
47280Smax.romanov@nginx.com     b->mem.start = nxt_port_mmap_chunk_start(hdr, c);
47342Smax.romanov@nginx.com     b->mem.pos = b->mem.start;
47442Smax.romanov@nginx.com     b->mem.free = b->mem.start;
47542Smax.romanov@nginx.com     b->mem.end = b->mem.start + PORT_MMAP_CHUNK_SIZE;
47642Smax.romanov@nginx.com 
47742Smax.romanov@nginx.com     nchunks = size / PORT_MMAP_CHUNK_SIZE;
47842Smax.romanov@nginx.com     if ((size % PORT_MMAP_CHUNK_SIZE) != 0 || nchunks == 0) {
47942Smax.romanov@nginx.com         nchunks++;
48042Smax.romanov@nginx.com     }
48142Smax.romanov@nginx.com 
48242Smax.romanov@nginx.com     c++;
48342Smax.romanov@nginx.com     nchunks--;
48442Smax.romanov@nginx.com 
48542Smax.romanov@nginx.com     /* Try to acquire as much chunks as required. */
48642Smax.romanov@nginx.com     while (nchunks > 0) {
48742Smax.romanov@nginx.com 
48880Smax.romanov@nginx.com         if (nxt_port_mmap_chk_set_chunk_busy(hdr, c) == 0) {
48942Smax.romanov@nginx.com             break;
49042Smax.romanov@nginx.com         }
49142Smax.romanov@nginx.com 
49242Smax.romanov@nginx.com         b->mem.end += PORT_MMAP_CHUNK_SIZE;
49342Smax.romanov@nginx.com         c++;
49442Smax.romanov@nginx.com         nchunks--;
49542Smax.romanov@nginx.com     }
49642Smax.romanov@nginx.com 
49742Smax.romanov@nginx.com     return b;
49842Smax.romanov@nginx.com }
49942Smax.romanov@nginx.com 
50042Smax.romanov@nginx.com 
50180Smax.romanov@nginx.com nxt_int_t
50280Smax.romanov@nginx.com nxt_port_mmap_increase_buf(nxt_task_t *task, nxt_buf_t *b, size_t size)
50380Smax.romanov@nginx.com {
50480Smax.romanov@nginx.com     size_t                  nchunks;
50580Smax.romanov@nginx.com     nxt_chunk_id_t          c, start;
50680Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
50780Smax.romanov@nginx.com 
50880Smax.romanov@nginx.com     nxt_debug(task, "request increase %z bytes shm buffer", size);
50980Smax.romanov@nginx.com 
51080Smax.romanov@nginx.com     if (nxt_slow_path(nxt_buf_is_port_mmap(b) == 0)) {
51180Smax.romanov@nginx.com         nxt_log(task, NXT_LOG_WARN,
51280Smax.romanov@nginx.com                 "failed to increase, not a mmap buffer");
51380Smax.romanov@nginx.com         return NXT_ERROR;
51480Smax.romanov@nginx.com     }
51580Smax.romanov@nginx.com 
51680Smax.romanov@nginx.com     if (nxt_slow_path(size <= (size_t) nxt_buf_mem_free_size(&b->mem))) {
51780Smax.romanov@nginx.com         return NXT_OK;
51880Smax.romanov@nginx.com     }
51980Smax.romanov@nginx.com 
52080Smax.romanov@nginx.com     hdr = b->parent;
52180Smax.romanov@nginx.com 
52280Smax.romanov@nginx.com     start = nxt_port_mmap_chunk_id(hdr, b->mem.end);
52380Smax.romanov@nginx.com 
52480Smax.romanov@nginx.com     size -= nxt_buf_mem_free_size(&b->mem);
52580Smax.romanov@nginx.com 
52680Smax.romanov@nginx.com     nchunks = size / PORT_MMAP_CHUNK_SIZE;
52780Smax.romanov@nginx.com     if ((size % PORT_MMAP_CHUNK_SIZE) != 0 || nchunks == 0) {
52880Smax.romanov@nginx.com         nchunks++;
52980Smax.romanov@nginx.com     }
53080Smax.romanov@nginx.com 
53180Smax.romanov@nginx.com     c = start;
53280Smax.romanov@nginx.com 
53380Smax.romanov@nginx.com     /* Try to acquire as much chunks as required. */
53480Smax.romanov@nginx.com     while (nchunks > 0) {
53580Smax.romanov@nginx.com 
53680Smax.romanov@nginx.com         if (nxt_port_mmap_chk_set_chunk_busy(hdr, c) == 0) {
53780Smax.romanov@nginx.com             break;
53880Smax.romanov@nginx.com         }
53980Smax.romanov@nginx.com 
54080Smax.romanov@nginx.com         c++;
54180Smax.romanov@nginx.com         nchunks--;
54280Smax.romanov@nginx.com     }
54380Smax.romanov@nginx.com 
54480Smax.romanov@nginx.com     if (nchunks != 0) {
54580Smax.romanov@nginx.com         c--;
54680Smax.romanov@nginx.com         while (c >= start) {
54780Smax.romanov@nginx.com             nxt_port_mmap_set_chunk_free(hdr, c);
54880Smax.romanov@nginx.com             c--;
54980Smax.romanov@nginx.com         }
55080Smax.romanov@nginx.com 
55180Smax.romanov@nginx.com         nxt_debug(task, "failed to increase, %d chunks busy", nchunks);
55280Smax.romanov@nginx.com 
55380Smax.romanov@nginx.com         return NXT_ERROR;
55480Smax.romanov@nginx.com     } else {
55580Smax.romanov@nginx.com         b->mem.end += PORT_MMAP_CHUNK_SIZE * (c - start);
55680Smax.romanov@nginx.com 
55780Smax.romanov@nginx.com         return NXT_OK;
55880Smax.romanov@nginx.com     }
55980Smax.romanov@nginx.com }
56080Smax.romanov@nginx.com 
56180Smax.romanov@nginx.com 
56242Smax.romanov@nginx.com static nxt_buf_t *
56342Smax.romanov@nginx.com nxt_port_mmap_get_incoming_buf(nxt_task_t *task, nxt_port_t *port,
56442Smax.romanov@nginx.com     nxt_pid_t spid, nxt_port_mmap_msg_t *mmap_msg)
56542Smax.romanov@nginx.com {
56642Smax.romanov@nginx.com     size_t                  nchunks;
56742Smax.romanov@nginx.com     nxt_buf_t               *b;
56880Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
56980Smax.romanov@nginx.com 
57080Smax.romanov@nginx.com     hdr = nxt_port_get_port_incoming_mmap(task, spid, mmap_msg->mmap_id);
57180Smax.romanov@nginx.com     if (nxt_slow_path(hdr == NULL)) {
57280Smax.romanov@nginx.com         return NULL;
57380Smax.romanov@nginx.com     }
57442Smax.romanov@nginx.com 
575122Smax.romanov@nginx.com     b = nxt_buf_mem_ts_alloc(task, port->mem_pool, 0);
57642Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
57742Smax.romanov@nginx.com         return NULL;
57842Smax.romanov@nginx.com     }
57942Smax.romanov@nginx.com 
58042Smax.romanov@nginx.com     b->completion_handler = nxt_port_mmap_buf_completion;
58142Smax.romanov@nginx.com 
58242Smax.romanov@nginx.com     nxt_buf_set_port_mmap(b);
58342Smax.romanov@nginx.com 
58442Smax.romanov@nginx.com     nchunks = mmap_msg->size / PORT_MMAP_CHUNK_SIZE;
58542Smax.romanov@nginx.com     if ((mmap_msg->size % PORT_MMAP_CHUNK_SIZE) != 0) {
58642Smax.romanov@nginx.com         nchunks++;
58742Smax.romanov@nginx.com     }
58842Smax.romanov@nginx.com 
58980Smax.romanov@nginx.com     b->mem.start = nxt_port_mmap_chunk_start(hdr, mmap_msg->chunk_id);
59042Smax.romanov@nginx.com     b->mem.pos = b->mem.start;
59142Smax.romanov@nginx.com     b->mem.free = b->mem.start + mmap_msg->size;
59242Smax.romanov@nginx.com     b->mem.end = b->mem.start + nchunks * PORT_MMAP_CHUNK_SIZE;
59342Smax.romanov@nginx.com 
59480Smax.romanov@nginx.com     b->parent = hdr;
59542Smax.romanov@nginx.com 
59642Smax.romanov@nginx.com     return b;
59742Smax.romanov@nginx.com }
59842Smax.romanov@nginx.com 
59942Smax.romanov@nginx.com 
60042Smax.romanov@nginx.com void
60142Smax.romanov@nginx.com nxt_port_mmap_write(nxt_task_t *task, nxt_port_t *port,
60242Smax.romanov@nginx.com     nxt_port_send_msg_t *msg, nxt_sendbuf_coalesce_t *sb)
60342Smax.romanov@nginx.com {
60480Smax.romanov@nginx.com     size_t                  bsize;
60580Smax.romanov@nginx.com     nxt_buf_t               *b, *bmem;
60680Smax.romanov@nginx.com     nxt_uint_t              i;
60780Smax.romanov@nginx.com     nxt_port_mmap_msg_t     *mmap_msg;
60880Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
60942Smax.romanov@nginx.com 
61042Smax.romanov@nginx.com     nxt_debug(task, "prepare %z bytes message for transfer to process %PI "
61142Smax.romanov@nginx.com               "via shared memory", sb->size, port->pid);
61242Smax.romanov@nginx.com 
61342Smax.romanov@nginx.com     bsize = sb->niov * sizeof(nxt_port_mmap_msg_t);
61442Smax.romanov@nginx.com 
615122Smax.romanov@nginx.com     b = nxt_buf_mem_ts_alloc(task, port->mem_pool, bsize);
61642Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
61742Smax.romanov@nginx.com         return;
61842Smax.romanov@nginx.com     }
61942Smax.romanov@nginx.com 
62042Smax.romanov@nginx.com     mmap_msg = (nxt_port_mmap_msg_t *) b->mem.start;
62142Smax.romanov@nginx.com     bmem = msg->buf;
62242Smax.romanov@nginx.com 
62342Smax.romanov@nginx.com     for (i = 0; i < sb->niov; i++, mmap_msg++) {
62442Smax.romanov@nginx.com 
62542Smax.romanov@nginx.com         /* Lookup buffer which starts current iov_base. */
62642Smax.romanov@nginx.com         while (bmem && sb->iobuf[i].iov_base != bmem->mem.pos) {
62742Smax.romanov@nginx.com             bmem = bmem->next;
62842Smax.romanov@nginx.com         }
62942Smax.romanov@nginx.com 
63042Smax.romanov@nginx.com         if (nxt_slow_path(bmem == NULL)) {
63142Smax.romanov@nginx.com             nxt_log_error(NXT_LOG_ERR, task->log, "failed to find buf for "
63242Smax.romanov@nginx.com                           "iobuf[%d]", i);
63342Smax.romanov@nginx.com             return;
63442Smax.romanov@nginx.com             /* TODO clear b and exit */
63542Smax.romanov@nginx.com         }
63642Smax.romanov@nginx.com 
63780Smax.romanov@nginx.com         hdr = bmem->parent;
63842Smax.romanov@nginx.com 
63980Smax.romanov@nginx.com         mmap_msg->mmap_id = hdr->id;
64080Smax.romanov@nginx.com         mmap_msg->chunk_id = nxt_port_mmap_chunk_id(hdr, bmem->mem.pos);
64142Smax.romanov@nginx.com         mmap_msg->size = sb->iobuf[i].iov_len;
64242Smax.romanov@nginx.com 
64342Smax.romanov@nginx.com         nxt_debug(task, "mmap_msg={%D, %D, %D} to %PI",
64442Smax.romanov@nginx.com                   mmap_msg->mmap_id, mmap_msg->chunk_id, mmap_msg->size,
64542Smax.romanov@nginx.com                   port->pid);
64642Smax.romanov@nginx.com     }
64742Smax.romanov@nginx.com 
64842Smax.romanov@nginx.com     msg->buf = b;
64942Smax.romanov@nginx.com     b->mem.free += bsize;
65042Smax.romanov@nginx.com 
65142Smax.romanov@nginx.com     sb->iobuf[0].iov_base = b->mem.pos;
65242Smax.romanov@nginx.com     sb->iobuf[0].iov_len = bsize;
65342Smax.romanov@nginx.com     sb->niov = 1;
65442Smax.romanov@nginx.com     sb->size = bsize;
65542Smax.romanov@nginx.com 
65642Smax.romanov@nginx.com     msg->port_msg.mmap = 1;
65742Smax.romanov@nginx.com }
65842Smax.romanov@nginx.com 
65942Smax.romanov@nginx.com 
66042Smax.romanov@nginx.com void
66142Smax.romanov@nginx.com nxt_port_mmap_read(nxt_task_t *task, nxt_port_t *port,
66282Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg)
66342Smax.romanov@nginx.com {
66442Smax.romanov@nginx.com     nxt_buf_t            *b, **pb;
66542Smax.romanov@nginx.com     nxt_port_mmap_msg_t  *end, *mmap_msg;
66642Smax.romanov@nginx.com 
66742Smax.romanov@nginx.com     b = msg->buf;
66842Smax.romanov@nginx.com 
66942Smax.romanov@nginx.com     mmap_msg = (nxt_port_mmap_msg_t *) b->mem.pos;
67042Smax.romanov@nginx.com     end = (nxt_port_mmap_msg_t *) b->mem.free;
67142Smax.romanov@nginx.com 
67242Smax.romanov@nginx.com     pb = &msg->buf;
67382Smax.romanov@nginx.com     msg->size = 0;
67442Smax.romanov@nginx.com 
67542Smax.romanov@nginx.com     while (mmap_msg < end) {
67642Smax.romanov@nginx.com         nxt_debug(task, "mmap_msg={%D, %D, %D} from %PI",
67742Smax.romanov@nginx.com                   mmap_msg->mmap_id, mmap_msg->chunk_id, mmap_msg->size,
67842Smax.romanov@nginx.com                   msg->port_msg.pid);
67942Smax.romanov@nginx.com 
68042Smax.romanov@nginx.com         *pb = nxt_port_mmap_get_incoming_buf(task, port, msg->port_msg.pid,
68142Smax.romanov@nginx.com                                              mmap_msg);
68242Smax.romanov@nginx.com         if (nxt_slow_path(*pb == NULL)) {
68342Smax.romanov@nginx.com             nxt_log_error(NXT_LOG_ERR, task->log, "failed to get mmap buffer");
68442Smax.romanov@nginx.com 
68542Smax.romanov@nginx.com             break;
68642Smax.romanov@nginx.com         }
68742Smax.romanov@nginx.com 
68882Smax.romanov@nginx.com         msg->size += mmap_msg->size;
68942Smax.romanov@nginx.com         pb = &(*pb)->next;
69042Smax.romanov@nginx.com         mmap_msg++;
69142Smax.romanov@nginx.com     }
69242Smax.romanov@nginx.com 
69342Smax.romanov@nginx.com     /* Mark original buf as complete. */
69442Smax.romanov@nginx.com     b->mem.pos += nxt_buf_used_size(b);
69542Smax.romanov@nginx.com }
69642Smax.romanov@nginx.com 
69742Smax.romanov@nginx.com 
69842Smax.romanov@nginx.com nxt_port_method_t
69942Smax.romanov@nginx.com nxt_port_mmap_get_method(nxt_task_t *task, nxt_port_t *port, nxt_buf_t *b)
70042Smax.romanov@nginx.com {
70180Smax.romanov@nginx.com     nxt_port_method_t       m;
70280Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
70342Smax.romanov@nginx.com 
70442Smax.romanov@nginx.com     m = NXT_PORT_METHOD_ANY;
70542Smax.romanov@nginx.com 
70642Smax.romanov@nginx.com     for (; b != NULL; b = b->next) {
70742Smax.romanov@nginx.com         if (nxt_buf_used_size(b) == 0) {
70842Smax.romanov@nginx.com             /* empty buffers does not affect method */
70942Smax.romanov@nginx.com             continue;
71042Smax.romanov@nginx.com         }
71142Smax.romanov@nginx.com 
71242Smax.romanov@nginx.com         if (nxt_buf_is_port_mmap(b)) {
71380Smax.romanov@nginx.com             hdr = b->parent;
71442Smax.romanov@nginx.com 
71542Smax.romanov@nginx.com             if (m == NXT_PORT_METHOD_PLAIN) {
71642Smax.romanov@nginx.com                 nxt_log_error(NXT_LOG_ERR, task->log,
71742Smax.romanov@nginx.com                               "mixing plain and mmap buffers, "
71842Smax.romanov@nginx.com                               "using plain mode");
71942Smax.romanov@nginx.com 
72042Smax.romanov@nginx.com                 break;
72142Smax.romanov@nginx.com             }
72242Smax.romanov@nginx.com 
72380Smax.romanov@nginx.com             if (port->pid != hdr->pid) {
72442Smax.romanov@nginx.com                 nxt_log_error(NXT_LOG_ERR, task->log,
72542Smax.romanov@nginx.com                               "send mmap buffer for %PI to %PI, "
72680Smax.romanov@nginx.com                               "using plain mode", hdr->pid, port->pid);
72742Smax.romanov@nginx.com 
72842Smax.romanov@nginx.com                 m = NXT_PORT_METHOD_PLAIN;
72942Smax.romanov@nginx.com 
73042Smax.romanov@nginx.com                 break;
73142Smax.romanov@nginx.com             }
73242Smax.romanov@nginx.com 
73342Smax.romanov@nginx.com             if (m == NXT_PORT_METHOD_ANY) {
73442Smax.romanov@nginx.com                 nxt_debug(task, "using mmap mode");
73542Smax.romanov@nginx.com 
73642Smax.romanov@nginx.com                 m = NXT_PORT_METHOD_MMAP;
73742Smax.romanov@nginx.com             }
73842Smax.romanov@nginx.com         } else {
73942Smax.romanov@nginx.com             if (m == NXT_PORT_METHOD_MMAP) {
74042Smax.romanov@nginx.com                 nxt_log_error(NXT_LOG_ERR, task->log,
74142Smax.romanov@nginx.com                               "mixing mmap and plain buffers, "
74242Smax.romanov@nginx.com                               "switching to plain mode");
74342Smax.romanov@nginx.com 
74442Smax.romanov@nginx.com                 m = NXT_PORT_METHOD_PLAIN;
74542Smax.romanov@nginx.com 
74642Smax.romanov@nginx.com                 break;
74742Smax.romanov@nginx.com             }
74842Smax.romanov@nginx.com 
74942Smax.romanov@nginx.com             if (m == NXT_PORT_METHOD_ANY) {
75042Smax.romanov@nginx.com                 nxt_debug(task, "using plain mode");
75142Smax.romanov@nginx.com 
75242Smax.romanov@nginx.com                 m = NXT_PORT_METHOD_PLAIN;
75342Smax.romanov@nginx.com             }
75442Smax.romanov@nginx.com         }
75542Smax.romanov@nginx.com     }
75642Smax.romanov@nginx.com 
75742Smax.romanov@nginx.com     return m;
75842Smax.romanov@nginx.com }
759