xref: /unit/src/nxt_port_memory_int.h (revision 2139:99d792169ffb)
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  */
680Smax.romanov@nginx.com 
780Smax.romanov@nginx.com #ifndef _NXT_PORT_MEMORY_INT_H_INCLUDED_
880Smax.romanov@nginx.com #define _NXT_PORT_MEMORY_INT_H_INCLUDED_
980Smax.romanov@nginx.com 
1080Smax.romanov@nginx.com 
1180Smax.romanov@nginx.com #include <stdint.h>
1280Smax.romanov@nginx.com #include <nxt_atomic.h>
1380Smax.romanov@nginx.com 
1480Smax.romanov@nginx.com 
1580Smax.romanov@nginx.com #ifdef NXT_MMAP_TINY_CHUNK
1680Smax.romanov@nginx.com 
1780Smax.romanov@nginx.com #define PORT_MMAP_CHUNK_SIZE    16
1880Smax.romanov@nginx.com #define PORT_MMAP_HEADER_SIZE   1024
1980Smax.romanov@nginx.com #define PORT_MMAP_DATA_SIZE     1024
2080Smax.romanov@nginx.com 
2180Smax.romanov@nginx.com #else
2280Smax.romanov@nginx.com 
2380Smax.romanov@nginx.com #define PORT_MMAP_CHUNK_SIZE    (1024 * 16)
2480Smax.romanov@nginx.com #define PORT_MMAP_HEADER_SIZE   (1024 * 4)
2580Smax.romanov@nginx.com #define PORT_MMAP_DATA_SIZE     (1024 * 1024 * 10)
2680Smax.romanov@nginx.com 
2780Smax.romanov@nginx.com #endif
2880Smax.romanov@nginx.com 
2980Smax.romanov@nginx.com 
3080Smax.romanov@nginx.com #define PORT_MMAP_SIZE          (PORT_MMAP_HEADER_SIZE + PORT_MMAP_DATA_SIZE)
3180Smax.romanov@nginx.com #define PORT_MMAP_CHUNK_COUNT   (PORT_MMAP_DATA_SIZE / PORT_MMAP_CHUNK_SIZE)
3280Smax.romanov@nginx.com 
3380Smax.romanov@nginx.com 
3480Smax.romanov@nginx.com typedef uint32_t  nxt_chunk_id_t;
3580Smax.romanov@nginx.com 
3680Smax.romanov@nginx.com typedef nxt_atomic_uint_t  nxt_free_map_t;
3780Smax.romanov@nginx.com 
3880Smax.romanov@nginx.com #define FREE_BITS (sizeof(nxt_free_map_t) * 8)
3980Smax.romanov@nginx.com 
4080Smax.romanov@nginx.com #define FREE_IDX(nchunk) ((nchunk) / FREE_BITS)
4180Smax.romanov@nginx.com 
4280Smax.romanov@nginx.com #define FREE_MASK(nchunk)                                                     \
4380Smax.romanov@nginx.com     ( 1ULL << ( (nchunk) % FREE_BITS ) )
4480Smax.romanov@nginx.com 
4580Smax.romanov@nginx.com #define MAX_FREE_IDX FREE_IDX(PORT_MMAP_CHUNK_COUNT)
4680Smax.romanov@nginx.com 
4780Smax.romanov@nginx.com 
4880Smax.romanov@nginx.com /* Mapped at the start of shared memory segment. */
4980Smax.romanov@nginx.com struct nxt_port_mmap_header_s {
5080Smax.romanov@nginx.com     uint32_t        id;
51363Smax.romanov@nginx.com     nxt_pid_t       src_pid; /* For sanity check. */
52363Smax.romanov@nginx.com     nxt_pid_t       dst_pid; /* For sanity check. */
53323Smax.romanov@nginx.com     nxt_port_id_t   sent_over;
541321Smax.romanov@nginx.com     nxt_atomic_t    oosm;
5580Smax.romanov@nginx.com     nxt_free_map_t  free_map[MAX_FREE_IDX];
56423Smax.romanov@nginx.com     nxt_free_map_t  free_map_padding;
57423Smax.romanov@nginx.com     nxt_free_map_t  free_tracking_map[MAX_FREE_IDX];
58423Smax.romanov@nginx.com     nxt_free_map_t  free_tracking_map_padding;
59423Smax.romanov@nginx.com     nxt_atomic_t    tracking[PORT_MMAP_CHUNK_COUNT];
6080Smax.romanov@nginx.com };
6180Smax.romanov@nginx.com 
6280Smax.romanov@nginx.com 
63365Smax.romanov@nginx.com struct nxt_port_mmap_handler_s {
64365Smax.romanov@nginx.com     nxt_port_mmap_header_t  *hdr;
65365Smax.romanov@nginx.com     nxt_atomic_t            use_count;
661546Smax.romanov@nginx.com     nxt_fd_t                fd;
67365Smax.romanov@nginx.com };
68365Smax.romanov@nginx.com 
6980Smax.romanov@nginx.com /*
7080Smax.romanov@nginx.com  * Element of nxt_process_t.incoming/outgoing, shared memory segment
7180Smax.romanov@nginx.com  * descriptor.
7280Smax.romanov@nginx.com  */
7380Smax.romanov@nginx.com struct nxt_port_mmap_s {
74365Smax.romanov@nginx.com     nxt_port_mmap_handler_t  *mmap_handler;
7580Smax.romanov@nginx.com };
7680Smax.romanov@nginx.com 
7780Smax.romanov@nginx.com typedef struct nxt_port_mmap_msg_s nxt_port_mmap_msg_t;
7880Smax.romanov@nginx.com 
7980Smax.romanov@nginx.com /* Passed as a second iov chunk when 'mmap' bit in nxt_port_msg_t is 1. */
8080Smax.romanov@nginx.com struct nxt_port_mmap_msg_s {
8180Smax.romanov@nginx.com     uint32_t            mmap_id;    /* Mmap index in nxt_process_t.outgoing. */
8280Smax.romanov@nginx.com     nxt_chunk_id_t      chunk_id;   /* Mmap chunk index. */
8380Smax.romanov@nginx.com     uint32_t            size;       /* Payload data size. */
8480Smax.romanov@nginx.com };
8580Smax.romanov@nginx.com 
8680Smax.romanov@nginx.com 
87723Smax.romanov@nginx.com nxt_inline nxt_bool_t
88423Smax.romanov@nginx.com nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c);
89423Smax.romanov@nginx.com 
90423Smax.romanov@nginx.com #define nxt_port_mmap_get_chunk_busy(m, c)                                    \
91423Smax.romanov@nginx.com     ((m[FREE_IDX(c)] & FREE_MASK(c)) == 0)
9280Smax.romanov@nginx.com 
9380Smax.romanov@nginx.com nxt_inline void
94423Smax.romanov@nginx.com nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c);
9580Smax.romanov@nginx.com 
9680Smax.romanov@nginx.com nxt_inline nxt_bool_t
97423Smax.romanov@nginx.com nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c);
9880Smax.romanov@nginx.com 
9980Smax.romanov@nginx.com nxt_inline void
100423Smax.romanov@nginx.com nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c);
10180Smax.romanov@nginx.com 
10280Smax.romanov@nginx.com nxt_inline nxt_chunk_id_t
nxt_port_mmap_chunk_id(nxt_port_mmap_header_t * hdr,const u_char * p)103*2139Sandrew@digital-domain.net nxt_port_mmap_chunk_id(nxt_port_mmap_header_t *hdr, const u_char *p)
10480Smax.romanov@nginx.com {
10580Smax.romanov@nginx.com     u_char  *mm_start;
10680Smax.romanov@nginx.com 
10780Smax.romanov@nginx.com     mm_start = (u_char *) hdr;
10880Smax.romanov@nginx.com 
10980Smax.romanov@nginx.com     return ((p - mm_start) - PORT_MMAP_HEADER_SIZE) / PORT_MMAP_CHUNK_SIZE;
11080Smax.romanov@nginx.com }
11180Smax.romanov@nginx.com 
11280Smax.romanov@nginx.com 
11380Smax.romanov@nginx.com nxt_inline u_char *
nxt_port_mmap_chunk_start(nxt_port_mmap_header_t * hdr,nxt_chunk_id_t c)11480Smax.romanov@nginx.com nxt_port_mmap_chunk_start(nxt_port_mmap_header_t *hdr, nxt_chunk_id_t c)
11580Smax.romanov@nginx.com {
11680Smax.romanov@nginx.com     u_char  *mm_start;
11780Smax.romanov@nginx.com 
11880Smax.romanov@nginx.com     mm_start = (u_char *) hdr;
11980Smax.romanov@nginx.com 
12080Smax.romanov@nginx.com     return mm_start + PORT_MMAP_HEADER_SIZE + c * PORT_MMAP_CHUNK_SIZE;
12180Smax.romanov@nginx.com }
12280Smax.romanov@nginx.com 
12380Smax.romanov@nginx.com 
124723Smax.romanov@nginx.com nxt_inline nxt_bool_t
nxt_port_mmap_get_free_chunk(nxt_free_map_t * m,nxt_chunk_id_t * c)125423Smax.romanov@nginx.com nxt_port_mmap_get_free_chunk(nxt_free_map_t *m, nxt_chunk_id_t *c)
12680Smax.romanov@nginx.com {
127699Smax.romanov@nginx.com     const nxt_free_map_t  default_mask = (nxt_free_map_t) -1;
128699Smax.romanov@nginx.com 
12980Smax.romanov@nginx.com     int             ffs;
130699Smax.romanov@nginx.com     size_t          i, start;
13180Smax.romanov@nginx.com     nxt_chunk_id_t  chunk;
132699Smax.romanov@nginx.com     nxt_free_map_t  bits, mask;
133699Smax.romanov@nginx.com 
134699Smax.romanov@nginx.com     start = FREE_IDX(*c);
135699Smax.romanov@nginx.com     mask = default_mask << ((*c) % FREE_BITS);
13680Smax.romanov@nginx.com 
137699Smax.romanov@nginx.com     for (i = start; i < MAX_FREE_IDX; i++) {
138699Smax.romanov@nginx.com         bits = m[i] & mask;
139699Smax.romanov@nginx.com         mask = default_mask;
140699Smax.romanov@nginx.com 
14180Smax.romanov@nginx.com         if (bits == 0) {
14280Smax.romanov@nginx.com             continue;
14380Smax.romanov@nginx.com         }
14480Smax.romanov@nginx.com 
14580Smax.romanov@nginx.com         ffs = __builtin_ffsll(bits);
14680Smax.romanov@nginx.com         if (ffs != 0) {
14780Smax.romanov@nginx.com             chunk = i * FREE_BITS + ffs - 1;
14880Smax.romanov@nginx.com 
149423Smax.romanov@nginx.com             if (nxt_port_mmap_chk_set_chunk_busy(m, chunk)) {
15080Smax.romanov@nginx.com                 *c = chunk;
15180Smax.romanov@nginx.com                 return 1;
15280Smax.romanov@nginx.com             }
15380Smax.romanov@nginx.com         }
15480Smax.romanov@nginx.com     }
15580Smax.romanov@nginx.com 
15680Smax.romanov@nginx.com     return 0;
15780Smax.romanov@nginx.com }
15880Smax.romanov@nginx.com 
15980Smax.romanov@nginx.com 
16080Smax.romanov@nginx.com nxt_inline void
nxt_port_mmap_set_chunk_busy(nxt_free_map_t * m,nxt_chunk_id_t c)161423Smax.romanov@nginx.com nxt_port_mmap_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c)
16280Smax.romanov@nginx.com {
163423Smax.romanov@nginx.com     nxt_atomic_and_fetch(m + FREE_IDX(c), ~FREE_MASK(c));
16480Smax.romanov@nginx.com }
16580Smax.romanov@nginx.com 
16680Smax.romanov@nginx.com 
16780Smax.romanov@nginx.com nxt_inline nxt_bool_t
nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t * m,nxt_chunk_id_t c)168423Smax.romanov@nginx.com nxt_port_mmap_chk_set_chunk_busy(nxt_free_map_t *m, nxt_chunk_id_t c)
16980Smax.romanov@nginx.com {
17080Smax.romanov@nginx.com     nxt_free_map_t  *f;
17180Smax.romanov@nginx.com     nxt_free_map_t  free_val, busy_val;
17280Smax.romanov@nginx.com 
173423Smax.romanov@nginx.com     f = m + FREE_IDX(c);
17480Smax.romanov@nginx.com 
17580Smax.romanov@nginx.com     while ( (*f & FREE_MASK(c)) != 0 ) {
17680Smax.romanov@nginx.com 
17780Smax.romanov@nginx.com         free_val = *f | FREE_MASK(c);
17880Smax.romanov@nginx.com         busy_val = free_val & ~FREE_MASK(c);
17980Smax.romanov@nginx.com 
18080Smax.romanov@nginx.com         if (nxt_atomic_cmp_set(f, free_val, busy_val) != 0) {
18180Smax.romanov@nginx.com             return 1;
18280Smax.romanov@nginx.com         }
18380Smax.romanov@nginx.com     }
18480Smax.romanov@nginx.com 
18580Smax.romanov@nginx.com     return 0;
18680Smax.romanov@nginx.com }
18780Smax.romanov@nginx.com 
18880Smax.romanov@nginx.com 
18980Smax.romanov@nginx.com nxt_inline void
nxt_port_mmap_set_chunk_free(nxt_free_map_t * m,nxt_chunk_id_t c)190423Smax.romanov@nginx.com nxt_port_mmap_set_chunk_free(nxt_free_map_t *m, nxt_chunk_id_t c)
19180Smax.romanov@nginx.com {
192423Smax.romanov@nginx.com     nxt_atomic_or_fetch(m + FREE_IDX(c), FREE_MASK(c));
19380Smax.romanov@nginx.com }
19480Smax.romanov@nginx.com 
19580Smax.romanov@nginx.com 
19680Smax.romanov@nginx.com #endif /* _NXT_PORT_MEMORY_INT_H_INCLUDED_ */
197