mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			149 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|     This file is part of KittenDB-Engine Library.
 | |
| 
 | |
|     KittenDB-Engine Library is free software: you can redistribute it and/or modify
 | |
|     it under the terms of the GNU Lesser General Public License as published by
 | |
|     the Free Software Foundation, either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     KittenDB-Engine Library is distributed in the hope that it will be useful,
 | |
|     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|     GNU Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public License
 | |
|     along with KittenDB-Engine Library.  If not, see <http://www.gnu.org/licenses/>.
 | |
| 
 | |
|     Copyright 2014 Telegraph Inc
 | |
|               2014 Nikolai Durov
 | |
|               2014 Andrey Lopatin
 | |
| */
 | |
| 
 | |
| #ifndef __KDB_MP_QUEUE_H__
 | |
| #define __KDB_MP_QUEUE_H__
 | |
| 
 | |
| #define MPQ_USE_POSIX_SEMAPHORES 0
 | |
| 
 | |
| #if MPQ_USE_POSIX_SEMAPHORES
 | |
| #include <semaphore.h>
 | |
| #endif
 | |
| 
 | |
| typedef struct mp_semaphore {
 | |
|   volatile int value;
 | |
|   volatile int waiting;
 | |
| } mp_sem_t;
 | |
| 
 | |
| #define THREAD_HPTRS 21
 | |
| 
 | |
| #define MPQ_SMALL_BLOCK_SIZE 64
 | |
| #define MPQ_BLOCK_SIZE 4096  // must be a power of 2
 | |
| #define MPQ_BLOCK_ALIGNMENT 64
 | |
| 
 | |
| #ifdef _LP64
 | |
| typedef int int128_t __attribute__((__mode__(TI)));
 | |
| #define DLONG int128_t
 | |
| // # define DLONG __int128
 | |
| #define MQN_SAFE (-1LL << 63)
 | |
| #else
 | |
| #define DLONG long long
 | |
| #define MQN_SAFE (-1L << 31)
 | |
| #endif
 | |
| 
 | |
| #define MQN_IDX_MASK (~MQN_SAFE)
 | |
| 
 | |
| typedef void *mqn_value_t;
 | |
| 
 | |
| typedef struct mp_queue_node {
 | |
|   union {
 | |
|     struct {
 | |
|       long idx;
 | |
|       union {
 | |
|         long mqn_value;
 | |
|         void *mqn_ptr;
 | |
|         mqn_value_t val;
 | |
|       };
 | |
|     };
 | |
|     DLONG pair;
 | |
|   };
 | |
| } mpq_node_t;
 | |
| 
 | |
| #define MQ_BLOCK_USED_MAGIC 0x1ebacaef
 | |
| #define MQ_BLOCK_FREE_MAGIC 0x2e4afeda
 | |
| #define MQ_BLOCK_GARBAGE_MAGIC 0x3a04dc7d
 | |
| #define MQ_BLOCK_PREPARED_MAGIC 0x4b9b13cd
 | |
| 
 | |
| #define MQ_MAGIC 0x1aed9b43
 | |
| #define MQ_MAGIC_SEM 0x1aedcd21
 | |
| 
 | |
| struct mp_queue_block {
 | |
|   long mqb_head __attribute__((aligned(64)));
 | |
|   int mqb_magic;
 | |
|   int mqb_align_bytes;
 | |
|   int mqb_size;  // power of 2; one of MPQ_BLOCK_SIZE or MPQ_SMALL_BLOCK_SIZE
 | |
|   long mqb_tail __attribute__((aligned(64)));
 | |
|   struct mp_queue_block *mqb_next;
 | |
|   int mqb_next_allocators;
 | |
|   mpq_node_t mqb_nodes[MPQ_BLOCK_SIZE] __attribute__((aligned(64)));
 | |
| };
 | |
| 
 | |
| struct mp_queue {
 | |
|   struct mp_queue_block *mq_head __attribute__((aligned(64)));
 | |
|   int mq_magic;
 | |
|   struct mp_queue_block *mq_tail __attribute__((aligned(64)));
 | |
| #if MPQ_USE_POSIX_SEMAPHORES
 | |
|   sem_t mq_sem __attribute__((aligned(64)));
 | |
| #else
 | |
|   mp_sem_t mq_sem __attribute__((aligned(64)));
 | |
| #endif
 | |
| };
 | |
| 
 | |
| extern volatile int mpq_blocks_allocated, mpq_blocks_allocated_max, mpq_blocks_allocations, mpq_blocks_true_allocations,
 | |
|     mpq_blocks_wasted, mpq_blocks_prepared;
 | |
| extern volatile int mpq_small_blocks_allocated, mpq_small_blocks_allocated_max;
 | |
| 
 | |
| #define MAX_MPQ_THREADS 22
 | |
| extern __thread int mpq_this_thread_id;
 | |
| extern __thread void **thread_hazard_pointers;
 | |
| extern volatile int mpq_threads;
 | |
| 
 | |
| /* initialize this thread id and return it */
 | |
| void clear_thread_ids(void);
 | |
| int get_this_thread_id(void);
 | |
| 
 | |
| /* functions for one mp_queue_block */
 | |
| struct mp_queue_block *alloc_mpq_block(mqn_value_t first_val, int allow_recursion, int is_small);
 | |
| void free_mpq_block(struct mp_queue_block *QB);
 | |
| 
 | |
| mqn_value_t mpq_block_pop(struct mp_queue_block *QB);
 | |
| long mpq_block_push(struct mp_queue_block *QB, mqn_value_t val);
 | |
| 
 | |
| /* functions for mp_queue = list of mp_queue_block's */
 | |
| void init_mp_queue(struct mp_queue *MQ);
 | |
| struct mp_queue *alloc_mp_queue(void);
 | |
| struct mp_queue *alloc_mp_queue_w(void);
 | |
| void init_mp_queue_w(struct mp_queue *MQ);
 | |
| void clear_mp_queue(struct mp_queue *MQ);  // frees all mpq block chain; invoke only if nobody else is using mp-queue
 | |
| void free_mp_queue(struct mp_queue *MQ);   // same + invoke free()
 | |
| 
 | |
| // flags for mpq_push / mpq_pop functions
 | |
| #define MPQF_RECURSIVE 8192
 | |
| #define MPQF_STORE_PTR 4096
 | |
| #define MPQF_MAX_ITERATIONS (MPQF_STORE_PTR - 1)
 | |
| 
 | |
| long mpq_push(struct mp_queue *MQ, mqn_value_t val, int flags);
 | |
| mqn_value_t mpq_pop(struct mp_queue *MQ, int flags);
 | |
| int mpq_is_empty(struct mp_queue *MQ);
 | |
| 
 | |
| long mpq_push_w(struct mp_queue *MQ, mqn_value_t val, int flags);
 | |
| mqn_value_t mpq_pop_w(struct mp_queue *MQ, int flags);
 | |
| mqn_value_t mpq_pop_nw(struct mp_queue *MQ, int flags);
 | |
| 
 | |
| int mp_sem_post(mp_sem_t *sem);
 | |
| int mp_sem_wait(mp_sem_t *sem);
 | |
| int mp_sem_trywait(mp_sem_t *sem);
 | |
| 
 | |
| #define COMMON_HAZARD_PTR_NUM 3
 | |
| int is_hazard_ptr(void *ptr, int a, int b);
 | |
| extern void *mqb_hazard_ptr[MAX_MPQ_THREADS][THREAD_HPTRS];
 | |
| void *get_ptr_multithread_copy(void **ptr, void (*incref)(void *ptr));
 | |
| #endif
 |