• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_queue.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 #ifndef _ink_queue_h_
00025 #define _ink_queue_h_
00026 
00027 /***********************************************************************
00028 
00029     Generic Queue Implementation (for pointer data types only)
00030 
00031     Uses atomic memory operations to avoid blocking.
00032     Intended as a replacement for llqueue.
00033 
00034 
00035 ***********************************************************************/
00036 
00037 #include "ink_platform.h"
00038 #include "ink_defs.h"
00039 #include "ink_apidefs.h"
00040 
00041 /*
00042   For information on the structure of the x86_64 memory map:
00043 
00044   http://en.wikipedia.org/wiki/X86-64#Linux
00045 
00046   Essentially, in the current 48-bit implementations, the
00047   top bit as well as the  lower 47 bits are used, leaving
00048   the upper-but one 16 bits free to be used for the version.
00049   We will use the top-but-one 15 and sign extend when generating
00050   the pointer was required by the standard.
00051 */
00052 
00053 /*
00054 #if defined(POSIX_THREAD)
00055 #include <pthread.h>
00056 #include <stdlib.h>
00057 #endif
00058 */
00059 
00060 #ifdef __cplusplus
00061 extern "C"
00062 {
00063 #endif                          /* __cplusplus */
00064 
00065   void ink_queue_load_64(void *dst, void *src);
00066 
00067 #ifdef __x86_64__
00068 #define INK_QUEUE_LD64(dst,src) *((uint64_t*)&(dst)) = *((uint64_t*)&(src))
00069 #else
00070 #define INK_QUEUE_LD64(dst,src) (ink_queue_load_64((void *)&(dst), (void *)&(src)))
00071 #endif
00072 
00073 #if TS_HAS_128BIT_CAS
00074 #define INK_QUEUE_LD(dst, src) do { \
00075   *(__int128_t*)&(dst) = __sync_val_compare_and_swap((__int128_t*)&(src), 0, 0); \
00076 } while (0)
00077 #else
00078 #define INK_QUEUE_LD(dst,src) INK_QUEUE_LD64(dst,src)
00079 #endif
00080 
00081 /*
00082  * Generic Free List Manager
00083  */
00084   // Warning: head_p is read and written in multiple threads without a
00085   // lock, use INK_QUEUE_LD to read safely.
00086   typedef union
00087   {
00088 #if (defined(__i386__) || defined(__arm__) || defined(__mips__)) && (SIZEOF_VOIDP == 4)
00089     struct
00090     {
00091       void *pointer;
00092       int32_t version;
00093     } s;
00094     int64_t data;
00095 #elif TS_HAS_128BIT_CAS
00096     struct
00097     {
00098       void *pointer;
00099       int64_t version;
00100     } s;
00101     __int128_t data;
00102 #else
00103     int64_t data;
00104 #endif
00105   } head_p;
00106 
00107 /*
00108  * Why is version required? One scenario is described below
00109  * Think of a list like this -> A -> C -> D
00110  * and you are popping from the list
00111  * Between the time you take the ptr(A) and swap the head pointer
00112  * the list could start looking like this
00113  * -> A -> B -> C -> D
00114  * If the version check is not there, the list will look like
00115  * -> C -> D after the pop, which will result in the loss of "B"
00116  */
00117 #define ZERO_HEAD_P(_x)
00118 
00119 #ifdef DEBUG
00120 #define FROM_PTR(_x) (void*)(((uintptr_t)_x)+1)
00121 #define TO_PTR(_x) (void*)(((uintptr_t)_x)-1)
00122 #else
00123 #define FROM_PTR(_x) ((void*)(_x))
00124 #define TO_PTR(_x) ((void*)(_x))
00125 #endif
00126 
00127 #if (defined(__i386__) || defined(__arm__) || defined(__mips__)) && (SIZEOF_VOIDP == 4)
00128 #define FREELIST_POINTER(_x) (_x).s.pointer
00129 #define FREELIST_VERSION(_x) (_x).s.version
00130 #define SET_FREELIST_POINTER_VERSION(_x,_p,_v) \
00131 (_x).s.pointer = _p; (_x).s.version = _v
00132 #elif TS_HAS_128BIT_CAS
00133 #define FREELIST_POINTER(_x) (_x).s.pointer
00134 #define FREELIST_VERSION(_x) (_x).s.version
00135 #define SET_FREELIST_POINTER_VERSION(_x,_p,_v) \
00136 (_x).s.pointer = _p; (_x).s.version = _v
00137 #elif defined(__x86_64__) || defined(__ia64__) || defined(__powerpc64__) || defined(__aarch64__)
00138 #define FREELIST_POINTER(_x) ((void*)(((((intptr_t)(_x).data)<<16)>>16) | \
00139  (((~((((intptr_t)(_x).data)<<16>>63)-1))>>48)<<48)))  // sign extend
00140 #define FREELIST_VERSION(_x) (((intptr_t)(_x).data)>>48)
00141 #define SET_FREELIST_POINTER_VERSION(_x,_p,_v) \
00142   (_x).data = ((((intptr_t)(_p))&0x0000FFFFFFFFFFFFULL) | (((_v)&0xFFFFULL) << 48))
00143 #else
00144 #error "unsupported processor"
00145 #endif
00146 
00147   typedef void *void_p;
00148 
00149 #if TS_USE_RECLAIMABLE_FREELIST
00150   extern float cfg_reclaim_factor;
00151   extern int64_t cfg_max_overage;
00152   extern int64_t cfg_enable_reclaim;
00153   extern int64_t cfg_debug_filter;
00154 #else
00155   struct _InkFreeList
00156   {
00157     volatile head_p head;
00158     const char *name;
00159     uint32_t type_size, chunk_size, used, allocated, alignment;
00160     uint32_t allocated_base, used_base;
00161   };
00162 
00163   inkcoreapi extern volatile int64_t fastalloc_mem_in_use;
00164   inkcoreapi extern volatile int64_t fastalloc_mem_total;
00165   inkcoreapi extern volatile int64_t freelist_allocated_mem;
00166 #endif
00167 
00168   typedef struct _InkFreeList InkFreeList, *PInkFreeList;
00169   typedef struct _ink_freelist_list
00170   {
00171     InkFreeList *fl;
00172     struct _ink_freelist_list *next;
00173   } ink_freelist_list;
00174   extern ink_freelist_list *freelists;
00175 
00176   /*
00177    * alignment must be a power of 2
00178    */
00179   InkFreeList *ink_freelist_create(const char *name, uint32_t type_size,
00180                                    uint32_t chunk_size, uint32_t alignment);
00181 
00182   inkcoreapi void ink_freelist_init(InkFreeList **fl, const char *name,
00183                                     uint32_t type_size, uint32_t chunk_size,
00184                                     uint32_t alignment);
00185   inkcoreapi void *ink_freelist_new(InkFreeList * f);
00186   inkcoreapi void ink_freelist_free(InkFreeList * f, void *item);
00187   void ink_freelists_dump(FILE * f);
00188   void ink_freelists_dump_baselinerel(FILE * f);
00189   void ink_freelists_snap_baseline();
00190 
00191   typedef struct
00192   {
00193     volatile head_p head;
00194     const char *name;
00195     uint32_t offset;
00196   } InkAtomicList;
00197 
00198 #if !defined(INK_QUEUE_NT)
00199 #define INK_ATOMICLIST_EMPTY(_x) (!(TO_PTR(FREELIST_POINTER((_x.head)))))
00200 #else
00201   /* ink_queue_nt.c doesn't do the FROM/TO pointer swizzling */
00202 #define INK_ATOMICLIST_EMPTY(_x) (!(      (FREELIST_POINTER((_x.head)))))
00203 #endif
00204 
00205   inkcoreapi void ink_atomiclist_init(InkAtomicList * l, const char *name, uint32_t offset_to_next);
00206   inkcoreapi void *ink_atomiclist_push(InkAtomicList * l, void *item);
00207   void *ink_atomiclist_pop(InkAtomicList * l);
00208   inkcoreapi void *ink_atomiclist_popall(InkAtomicList * l);
00209 /*
00210  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00211  * only if only one thread is doing pops it is possible to have a "remove"
00212  * which only that thread can use as well.
00213  * WARNING WARNING WARNING WARNING WARNING WARNING WARNING
00214  */
00215   void *ink_atomiclist_remove(InkAtomicList * l, void *item);
00216 
00217 #ifdef __cplusplus
00218 }
00219 #endif /* __cplusplus */
00220 
00221 #endif /* _ink_queue_h_ */

Generated by  doxygen 1.7.1