/* * kcm.h - Kernel Cache Manager definition. * * Authors Alain Greiner (2016,2017,2018,2019,2020) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _KCM_H_ #define _KCM_H_ #include #include #include #include #include #include /**************************************************************************************** * This structure defines a generic Kernel Cache Manager, a fixed size block allocator. * It returns an aligned block whose size is a power of 2, not smaller than a cache line, * but smaller than a small PPM page. It exists in each cluster a specific KCM allocator * for each possible block size. When the cache line contains 64 bytes and the page * contains 4K bytes, the possible block sizes are 64, 128, 256, 512, 1024, 2048 bytes. * These KCM allocators are initialized by the cluster_init() function. * * Each KCM cache is implemented as a set of "kcm_pages": a "kcm_page" is an aligned * buffer in physical memory (allocated by the PPM allocator) such as : * buffer_size = block_size * 64 <=> buffer_order = block_order + 6. * * A kcm_page contains always 64 kcm_blocks, but the first block (that cannot be smaller * than 64 bytes) is used to store the kcm_page descriptor defining the page allocation * status, and cannot be allocated to store data. * * A KCM cache is extensible, as new kcm_pages are dynamically allocated from the PPM * allocator when required. For a given KCM cache the set of kcm_pages is split in two * lists: the list of "full" pages (containing 63 allocated blocks), and the list of * "active" pages (containing at least one free block). An "empty" page (containing * only free blocks) is considered active, and is not released to PPM. * * To allow any thread running in any cluster to directly access the KCM of any cluster, * ALMOS-MKH defines two sets of access functions, for local or remote access. ***************************************************************************************/ typedef struct kcm_s { remote_busylock_t lock; /*! protect KCM allocator */ list_entry_t full_root; /*! root of full pages list */ list_entry_t active_root; /*! root of active pages list */ uint32_t full_pages_nr; /*! number of full pages */ uint32_t active_pages_nr; /*! number of active pages */ uint32_t order; /*! ln( block_size ) */ } kcm_t; /**************************************************************************************** * This structure defines a KCM-page descriptor. * A KCM-page contains (CONFIG_PPM_PAGE_SIZE / block_size) slots. * Each slot contains one block, but the kcm page descriptor is stored in first slot. * The current allocation status is defined by the 64 bits "status" bit vector: each * non zero bit defines an allocated block / "count" is the number of allocated blocks. * Each kcm_page is registered in one of the two following lists, rooted in the kcm: * - full : when count == max * - active : count < max ***************************************************************************************/ typedef struct kcm_page_s { uint64_t status; /*! bit vector: non-zero == allocated */ uint32_t count; /*! number of allocated blocks in page */ list_entry_t list; /*! [active / busy / free] list member */ kcm_t * kcm; /*! pointer on kcm allocator */ page_t * page; /*! pointer on physical page descriptor */ } kcm_page_t; /**************************************************************************************** * This function must be called by a local thread. * It initializes a Kernel Cache Manager, depending on block size. **************************************************************************************** * @ kcm : pointer on KCM to be initialized. * @ order : ln(block_size). ***************************************************************************************/ void kcm_init( kcm_t * kcm, uint32_t order ); /**************************************************************************************** * This function must be called by a local thread. * It releases all memory allocated to a Kernel Cache Manager. **************************************************************************************** * @ kcm : pointer on KCM manager to destroy. ***************************************************************************************/ void kcm_destroy( kcm_t * kcm ); /**************************************************************************************** * This function must be called by a local thread. * It allocates one block from the local Kernel Cache Manager. **************************************************************************************** * @ order : ln( block-size ) == KCM allocator identifier. * @ return pointer on allocated block if success / return NULL if failure ***************************************************************************************/ void * kcm_alloc( uint32_t order ); /**************************************************************************************** * This function must be called by a local thread. * It releases a previouly allocated block to the local Kernel Cache Manager. **************************************************************************************** * @ block_ptr : local pointer on the released block. * @ order : log2( block_size in bytes ). ***************************************************************************************/ void kcm_free( void * block_ptr, uint32_t order ); /**************************************************************************************** * This function can be called by any thread running in any cluster. * It allocates one fixed size block from a remote Kernel Cache Manager. **************************************************************************************** * @ kcm_cxy : remote KCM cluster identifier. * @ order : ln( block-size ) == KCM allocator identifier. * @ return a local pointer on allocated block if success / return NULL if failure ***************************************************************************************/ void * kcm_remote_alloc( cxy_t kcm_cxy, uint32_t order ); /**************************************************************************************** * This function can be called by any thread running in any cluster. * It releases a previouly allocated block to a remote Kernel Cache Manager. **************************************************************************************** * @ kcm_cxy : remote KCM cluster identifier. * @ block_ptr : local pointer on the released buffer in remote cluster. * @ order : log2( block_size in bytes ). ***************************************************************************************/ void kcm_remote_free( cxy_t kcm_cxy, void * block_ptr, uint32_t order ); /**************************************************************************************** * This debug function can be called by any thread running in any cluster. It displays * on TXT0 the state of a KCM, identified by the & arguments. **************************************************************************************** * @ kcm_cxy : remote KCM cluster identifier. * @ kcm_ptr : local pointer on remote KCM. ***************************************************************************************/ void kcm_remote_display( cxy_t kcm_cxy, kcm_t * kcm_ptr ); #endif /* _KCM_H_ */