From 8fb3f19e1ff9ed1c8198a844fed3565cce1dff41 Mon Sep 17 00:00:00 2001 From: Irek Fakhrutdinov <34161978+ifakhrutdinov@users.noreply.github.com> Date: Mon, 10 Feb 2020 08:18:41 +0100 Subject: [PATCH] Expose wrappers for CPOOL (#116) --- c/cellpool.c | 530 +++++++++++++++++++++++++++++++++++++++++++++++++++ c/cmutils.c | 82 ++++---- h/cellpool.h | 116 +++++++++++ 3 files changed, 687 insertions(+), 41 deletions(-) create mode 100644 c/cellpool.c create mode 100644 h/cellpool.h diff --git a/c/cellpool.c b/c/cellpool.c new file mode 100644 index 000000000..026f0abee --- /dev/null +++ b/c/cellpool.c @@ -0,0 +1,530 @@ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + +#ifdef METTLE +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "zowetypes.h" +#include "alloc.h" +#include "cellpool.h" +#include "zos.h" + +unsigned int cellpoolGetDWordAlignedSize(unsigned int size) { + + unsigned rem = size % 8; + + if (rem == 0) { + return size; + } + + return size + 8 - rem; + +} + +CPID cellpoolBuild(unsigned int pCellCount, + unsigned int sCellCount, + unsigned int cellSize, + int subpool, int key, + const CPHeader *header) { + + CPID cpid = CPID_NULL; + + ALLOC_STRUCT31( + STRUCT31_NAME(below2G), + STRUCT31_FIELDS( + char parmList[64]; + CPHeader header; + ) + ); + + if (below2G == NULL) { /* This can only fail in LE 64-bit */ + return cpid; + } + + below2G->header = *header; + + if (isCallerCrossMemory() || isCallerSRB()) { + + __asm( + + ASM_PREFIX + " SYSSTATE PUSH \n" + " SYSSTATE OSREL=ZOSV1R6 \n" + #ifdef _LP64 + " SAM31 \n" + " SYSSTATE AMODE64=NO \n" + #endif + + " CPOOL BUILD" + ",PCELLCT=(%[pcell])" + ",SCELLCT=(%[scell])" + ",CSIZE=(%[csize])" + ",SP=(%[sp])" + ",KEY=(%[key])" + ",TCB=0" + ",LOC=(31,64)" + ",CPID=(%[cpid])" + ",HDR=%[header]" + ",MF=(E,%[parmList])" + " \n" + + #ifdef _LP64 + " SAM64 \n" + #endif + " SYSSTATE POP \n" + + : [cpid]"=NR:r0"(cpid) + + : [pcell]"r"(pCellCount), + [scell]"r"(sCellCount), + [csize]"r"(cellSize), + [sp]"r"(subpool), + [key]"r"(key), + [header]"m"(below2G->header), + [parmList]"m"(below2G->parmList) + + : "r0", "r1", "r14", "r15" + + ); + + } else { + + __asm( + + ASM_PREFIX + " SYSSTATE PUSH \n" + " SYSSTATE OSREL=ZOSV1R6 \n" + #ifdef _LP64 + " SAM31 \n" + " SYSSTATE AMODE64=NO \n" + #endif + + " CPOOL BUILD" + ",PCELLCT=(%[pcell])" + ",SCELLCT=(%[scell])" + ",CSIZE=(%[csize])" + ",SP=(%[sp])" + ",KEY=(%[key])" + ",LOC=(31,64)" + ",CPID=(%[cpid])" + ",HDR=%[header]" + ",MF=(E,%[parmList])" + " \n" + + #ifdef _LP64 + " SAM64 \n" + #endif + " SYSSTATE POP \n" + + : [cpid]"=NR:r0"(cpid) + + : [pcell]"r"(pCellCount), + [scell]"r"(sCellCount), + [csize]"r"(cellSize), + [sp]"r"(subpool), + [key]"r"(key), + [header]"m"(below2G->header), + [parmList]"m"(below2G->parmList) + + : "r0", "r1", "r14", "r15" + + ); + + } + + FREE_STRUCT31( + STRUCT31_NAME(below2G) + ); + + return cpid; +} + +void cellpoolDelete(CPID cellpoolID) { + + __asm( + + ASM_PREFIX + " SYSSTATE PUSH \n" + " SYSSTATE OSREL=ZOSV1R6 \n" +#ifdef _LP64 + " SAM31 \n" + " SYSSTATE AMODE64=NO \n" +#endif + + " CPOOL DELETE,CPID=(%[cpid]) \n" + +#ifdef _LP64 + " SAM64 \n" +#endif + " SYSSTATE POP \n" + + : + : [cpid]"r"(cellpoolID) + : "r0", "r1", "r14", "r15" + ); + +} + +void *cellpoolGet(CPID cellpoolID, bool conditional) { + + uint64_t callerGPRs[12] = {0}; + + void * __ptr32 cell = NULL; + + /* + * Notes about the use of callerGPRs: + * + * - The registers must be saved before switching to AMODE 31 and restored + * after switching back to AMODE 64, because the stack storage containing + * the callerGPRs may be above 2G. + * + * - Register 13 is being saved in callerGPRs, changed to point to callerGPRs, + * and then restored back to its original value when the registers are + * restored. All parameters must be passed in registers on the CPOOL request + * because of R13 being changed. + * + */ + + if (conditional) { + __asm( + + ASM_PREFIX + " STMG 2,13,%[gprs] \n" + " LA 13,%[gprs] \n" + #ifdef _LP64 + " SAM31 \n" + #endif + + " CPOOL GET,C,CPID=(%[cpid]),REGS=USE \n" + + #ifdef _LP64 + " SAM64 \n" + #endif + " LMG 2,13,0(13) \n" + + : [cell]"=NR:r1"(cell) + : [gprs]"m"(callerGPRs), [cpid]"NR:r1"(cellpoolID) + : "r0", "r1", "r14", "r15" + ); + } else { + __asm( + + ASM_PREFIX + " STMG 2,13,%[gprs] \n" + " LA 13,%[gprs] \n" + #ifdef _LP64 + " SAM31 \n" + #endif + + " CPOOL GET,U,CPID=(%[cpid]),REGS=USE \n" + + #ifdef _LP64 + " SAM64 \n" + #endif + " LMG 2,13,0(13) \n" + + : [cell]"=NR:r1"(cell) + : [gprs]"m"(callerGPRs), [cpid]"NR:r1"(cellpoolID) + : "r0", "r1", "r14", "r15" + ); + } + + return cell; +} + +void cellpoolFree(CPID cellpoolID, void *cell) { + + uint64_t callerGPRs[12] = {0}; + + /* + * Notes about the use of callerGPRs: + * + * - The registers must be saved before switching to AMODE 31 and restored + * after switching back to AMODE 64, because the stack storage containing + * the callerGPRs may be above 2G. + * + * - Register 13 is being saved in callerGPRs, changed to point to callerGPRs, + * and then restored back to its original value when the registers are + * restored. All parameters must be passed in registers on the CPOOL request + * because of R13 being changed. + * + */ + + __asm( + + ASM_PREFIX + " STMG 2,13,%[gprs] \n" + " LA 13,%[gprs] \n" +#ifdef _LP64 + " SAM31 \n" +#endif + + " CPOOL FREE,CPID=(%[cpid]),CELL=(%[cell]),REGS=USE \n" + +#ifdef _LP64 + " SAM64 \n" +#endif + " LMG 2,13,0(13) \n" + + : + : [gprs]"m"(callerGPRs), [cpid]"NR:r1"(cellpoolID), [cell]"NR:r0"(cell) + : "r0", "r1", "r14", "r15" + ); + +} + +/* Tests (TODO move to a designated place) + +LE: + +xlc "-Wa,goff" \ +"-Wc,LANGLVL(EXTC99),FLOAT(HEX),agg,exp,list(),so(),goff,xref,gonum,roconst,gonum,ASM,ASMLIB('SYS1.MACLIB'),LP64,XPLINK" \ +-DCELLPOOL_TEST -I ../h -o cellpool \ +alloc.c \ +cellpool.c \ +timeutls.c \ +utils.c \ +zos.c \ + +Metal: + +CFLAGS=(-S -M -qmetal -q64 -DSUBPOOL=132 -DMETTLE=1 -DMSGPREFIX='"IDX"' +-qreserved_reg=r12 +-Wc,"arch(8),agg,exp,list(),so(),off,xref,roconst,longname,lp64" +-I ../h ) + +ASFLAGS=(-mgoff -mobject -mflag=nocont --TERM --RENT) + +LDFLAGS=(-V -b ac=1 -b rent -b case=mixed -b map -b xref -b reus) + +xlc "${CFLAGS[@]}" -DCELLPOOL_TEST \ +alloc.c \ +cellpool.c \ +metalio.c \ +qsam.c \ +timeutls.c \ +utils.c \ +zos.c \ + +as "${ASFLAGS[@]}" -aegimrsx=alloc.asm alloc.s +as "${ASFLAGS[@]}" -aegimrsx=cellpool.asm cellpool.s +as "${ASFLAGS[@]}" -aegimrsx=metalio.asm metalio.s +as "${ASFLAGS[@]}" -aegimrsx=qsam.asm qsam.s +as "${ASFLAGS[@]}" -aegimrsx=timeutls.asm timeutls.s +as "${ASFLAGS[@]}" -aegimrsx=utils.asm utils.s +as "${ASFLAGS[@]}" -aegimrsx=zos.asm zos.s + +ld "${LDFLAGS[@]}" -e main \ +-o "//'$USER.DEV.LOADLIB(CELLPOOL)'" \ +alloc.o \ +cellpool.o \ +metalio.o \ +qsam.o \ +timeutls.o \ +utils.o \ +zos.o \ +> CELLPOOL.link + +*/ + +#define CELLPOOL_TEST_STATUS_OK 0 +#define CELLPOOL_TEST_STATUS_FAILURE 8 + +#define CELLPOOL_TEST_PRIMARY_SIZE 10 +#define CELLPOOL_TEST_SECONDARY_SIZE 2 +#define CELLPOOL_TEST_CELL_SIZE 512 +#define CELLPOOL_TEST_SUBPOOL 132 +#define CELLPOOL_TEST_KEY 8 +#define CELLPOOL_TEST_HEADER_STR "TEST-CP-HEADER" + +static int testUnconditionalCellPoolGet(void) { + + unsigned psize = CELLPOOL_TEST_PRIMARY_SIZE; + unsigned ssize = CELLPOOL_TEST_SECONDARY_SIZE; + unsigned cellSize = CELLPOOL_TEST_CELL_SIZE; + const int sp = CELLPOOL_TEST_SUBPOOL; + const int key = CELLPOOL_TEST_KEY; + const CPHeader header = {CELLPOOL_TEST_HEADER_STR}; + const bool isConditional = false; + + const int testGetCount = 100; + + CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + if (id == CPID_NULL) { + printf("error: cellpoolBuild failed\n"); + return CELLPOOL_TEST_STATUS_FAILURE; + } + + int status = CELLPOOL_TEST_STATUS_OK; + + for (int i = 0; i < testGetCount; i++) { + void *cell = cellpoolGet(id, isConditional); + if (cell == NULL) { + printf("error: cellpoolGet(unconditional) test failed, cell #%d\n", i); + status = CELLPOOL_TEST_STATUS_FAILURE; + break; + } + } + + cellpoolDelete(id); + + return status; +} + +static int testConditionalCellPoolGet(void) { + + unsigned psize = CELLPOOL_TEST_PRIMARY_SIZE; + unsigned ssize = CELLPOOL_TEST_SECONDARY_SIZE; + unsigned cellSize = CELLPOOL_TEST_CELL_SIZE; + const int sp = CELLPOOL_TEST_SUBPOOL; + const int key = CELLPOOL_TEST_KEY; + const CPHeader header = {CELLPOOL_TEST_HEADER_STR}; + const bool isConditional = true; + + CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + if (id == CPID_NULL) { + printf("error: cellpoolBuild failed\n"); + return CELLPOOL_TEST_STATUS_FAILURE; + } + + int status = CELLPOOL_TEST_STATUS_FAILURE; + + for (int i = 0; i < psize + 1; i++) { + void *cell = cellpoolGet(id, isConditional); + if (cell == NULL && i == psize) { + status = CELLPOOL_TEST_STATUS_OK; + break; + } + } + + if (status != CELLPOOL_TEST_STATUS_OK) { + printf("error: cellpoolGet(conditional) test failed\n"); + } + + cellpoolDelete(id); + + return status; +} + +static int testCellPoolFree(void) { + + unsigned psize = CELLPOOL_TEST_PRIMARY_SIZE; + unsigned ssize = CELLPOOL_TEST_SECONDARY_SIZE; + unsigned cellSize = CELLPOOL_TEST_CELL_SIZE; + const int sp = CELLPOOL_TEST_SUBPOOL; + const int key = CELLPOOL_TEST_KEY; + const CPHeader header = {CELLPOOL_TEST_HEADER_STR}; + const bool isConditional = true; + + void *cells[10] = {0}; + + CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + if (id == CPID_NULL) { + printf("error: cellpoolBuild failed\n"); + return CELLPOOL_TEST_STATUS_FAILURE; + } + + int status = CELLPOOL_TEST_STATUS_OK; + + for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { + cells[i] = cellpoolGet(id, isConditional); + if (cells[i] == NULL) { + printf("error: cellpoolFree test failed (alloc 1), cell #%d\n", i); + status = CELLPOOL_TEST_STATUS_FAILURE; + break; + } + } + + if (status == CELLPOOL_TEST_STATUS_OK) { + + for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { + cellpoolFree(id, cells[i]); + cells[i] = NULL; + } + + for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { + cells[i] = cellpoolGet(id, isConditional); + if (cells[i] == NULL) { + printf("error: cellpoolFree test failed (alloc 2), cell #%d\n", i); + status = CELLPOOL_TEST_STATUS_FAILURE; + break; + } + } + + } + + cellpoolDelete(id); + + return status; +} + + +static int testCellPool(void) { + + int status = CELLPOOL_TEST_STATUS_OK; + + if (status == CELLPOOL_TEST_STATUS_OK) { + status = testUnconditionalCellPoolGet(); + } + + if (status == CELLPOOL_TEST_STATUS_OK) { + status = testConditionalCellPoolGet(); + } + + if (status == CELLPOOL_TEST_STATUS_OK) { + status = testCellPoolFree(); + } + + return status; +} + +#ifdef CELLPOOL_TEST +int main() { +#else +static int notMain() { +#endif + + printf("info: starting cellpool test\n"); + + int status = CELLPOOL_TEST_STATUS_OK; + + status = testCellPool(); + + if (status == CELLPOOL_TEST_STATUS_OK) { + printf("info: SUCCESS, tests have passed\n"); + } else { + printf("error: FAILURE, some tests have failed\n"); + } + + return status; +} + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + diff --git a/c/cmutils.c b/c/cmutils.c index e9531c9a8..57bafe0db 100644 --- a/c/cmutils.c +++ b/c/cmutils.c @@ -369,17 +369,17 @@ ZOWE_PRAGMA_PACK typedef int32_t CPID; -typedef struct CPHeader_tag { +typedef struct CMCPHeader_tag { char text[24]; -} CPHeader; +} CMCPHeader; ZOWE_PRAGMA_PACK_RESET -static CPID cellpoolBuild(unsigned int pCellCount, - unsigned int sCellCount, - unsigned int cellSize, - int subpool, int key, - const CPHeader *header) { +static CPID cmCellPoolBuild(unsigned int pCellCount, + unsigned int sCellCount, + unsigned int cellSize, + int subpool, int key, + const CMCPHeader *header) { CPID cpid = -1; @@ -387,7 +387,7 @@ static CPID cellpoolBuild(unsigned int pCellCount, STRUCT31_NAME(below2G), STRUCT31_FIELDS( char parmList[64]; - CPHeader header; + CMCPHeader header; ) ); @@ -438,7 +438,7 @@ static CPID cellpoolBuild(unsigned int pCellCount, return cpid; } -static void cellpoolDelete(CPID cellpoolID) { +static void cmCellPoolDelete(CPID cellpoolID) { __asm( @@ -464,7 +464,7 @@ static void cellpoolDelete(CPID cellpoolID) { } -static void *cellpoolGet(CPID cellpoolID, bool conditional) { +static void *cmCellPoolGet(CPID cellpoolID, bool conditional) { uint64 callerGPRs[12] = {0}; @@ -531,7 +531,7 @@ static void *cellpoolGet(CPID cellpoolID, bool conditional) { return cell; } -static void cellpoolFree(CPID cellpoolID, void *cell) { +static void cmCellPoolFree(CPID cellpoolID, void *cell) { uint64 callerGPRs[12] = {0}; @@ -635,7 +635,7 @@ CrossMemoryMap *makeCrossMemoryMap(unsigned int keySize) { map->keySize = keySize; map->bucketCount = CM_MAP_BUCKET_COUNT; - CPHeader header = { + CMCPHeader header = { .text = CM_MAP_HEADER, }; @@ -644,11 +644,11 @@ CrossMemoryMap *makeCrossMemoryMap(unsigned int keySize) { } map->entrySize = sizeof(CrossMemoryMapEntry) + keySize; - map->entryCellpool = cellpoolBuild(CM_MAP_PRIMARY_CELL_COUNT, - CM_MAP_SECONDARY_CELL_COUNT, - map->entrySize, - CM_MAP_SUBPOOL, CM_MAP_KEY, - &header); + map->entryCellpool = cmCellPoolBuild(CM_MAP_PRIMARY_CELL_COUNT, + CM_MAP_SECONDARY_CELL_COUNT, + map->entrySize, + CM_MAP_SUBPOOL, CM_MAP_KEY, + &header); return map; } @@ -659,7 +659,7 @@ void removeCrossMemoryMap(CrossMemoryMap **mapAddr) { CPID cellpoolToDelete = map->entryCellpool; map->entryCellpool = -1; if (cellpoolToDelete != -1) { - cellpoolDelete(cellpoolToDelete); + cmCellPoolDelete(cellpoolToDelete); } #ifndef CMUTILS_TEST cmFree2((void **)mapAddr, map->size, CM_MAP_SUBPOOL, CM_MAP_KEY); @@ -695,7 +695,7 @@ static CrossMemoryMapEntry *makeEntry(CrossMemoryMap *map, const void *key, void *value) { - CrossMemoryMapEntry *entry = cellpoolGet(map->entryCellpool, FALSE); + CrossMemoryMapEntry *entry = cmCellPoolGet(map->entryCellpool, FALSE); if (entry == NULL) { return NULL; } @@ -710,7 +710,7 @@ static CrossMemoryMapEntry *makeEntry(CrossMemoryMap *map, } static void removeEntry(CrossMemoryMap *map, CrossMemoryMapEntry *entry) { - cellpoolFree(map->entryCellpool, entry); + cmCellPoolFree(map->entryCellpool, entry); } /* Put a new key-value into the map: @@ -860,27 +860,27 @@ static int testUnconditionalCellPoolGet(void) { unsigned ssize = 2; unsigned cellSize = 512; int sp = 132, key = 8; - CPHeader header = {"TEST-CP-HEADER"}; + CMCPHeader header = {"TEST-CP-HEADER"}; bool isConditional = false; - CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + CPID id = cmCellPoolBuild(psize, ssize, cellSize, sp, key, &header); if (id == -1) { - printf("error: cellpoolBuild failed\n"); + printf("error: cmCellPoolBuild failed\n"); return CMUTILS_TEST_STATUS_FAILURE; } int status = CMUTILS_TEST_STATUS_OK; for (int i = 0; i < 100; i++) { - void *cell = cellpoolGet(id, isConditional); + void *cell = cmCellPoolGet(id, isConditional); if (cell == NULL) { - printf("error: cellpoolGet(unconditional) test failed, cell #%d\n", i); + printf("error: cmCellPoolGet(unconditional) test failed, cell #%d\n", i); status = CMUTILS_TEST_STATUS_FAILURE; break; } } - cellpoolDelete(id); + cmCellPoolDelete(id); return status; } @@ -891,19 +891,19 @@ static int testConditionalCellPoolGet(void) { unsigned ssize = 2; unsigned cellSize = 512; int sp = 132, key = 8; - CPHeader header = {"TEST-CP-HEADER"}; + CMCPHeader header = {"TEST-CP-HEADER"}; bool isConditional = true; - CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + CPID id = cmCellPoolBuild(psize, ssize, cellSize, sp, key, &header); if (id == -1) { - printf("error: cellpoolBuild failed\n"); + printf("error: cmCellPoolBuild failed\n"); return CMUTILS_TEST_STATUS_FAILURE; } int status = CMUTILS_TEST_STATUS_FAILURE; for (int i = 0; i < psize + 1; i++) { - void *cell = cellpoolGet(id, isConditional); + void *cell = cmCellPoolGet(id, isConditional); if (cell == NULL && i == psize) { status = CMUTILS_TEST_STATUS_OK; break; @@ -911,10 +911,10 @@ static int testConditionalCellPoolGet(void) { } if (status != CMUTILS_TEST_STATUS_OK) { - printf("error: cellpoolGet(conditional) test failed\n"); + printf("error: cmCellPoolGet(conditional) test failed\n"); } - cellpoolDelete(id); + cmCellPoolDelete(id); return status; } @@ -925,23 +925,23 @@ static int testCellPoolFree(void) { unsigned ssize = 2; unsigned cellSize = 512; int sp = 132, key = 8; - CPHeader header = {"TEST-CP-HEADER"}; + CMCPHeader header = {"TEST-CP-HEADER"}; bool isConditional = true; void *cells[10] = {0}; - CPID id = cellpoolBuild(psize, ssize, cellSize, sp, key, &header); + CPID id = cmCellPoolBuild(psize, ssize, cellSize, sp, key, &header); if (id == -1) { - printf("error: cellpoolBuild failed\n"); + printf("error: cmCellPoolBuild failed\n"); return CMUTILS_TEST_STATUS_FAILURE; } int status = CMUTILS_TEST_STATUS_OK; for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { - cells[i] = cellpoolGet(id, isConditional); + cells[i] = cmCellPoolGet(id, isConditional); if (cells[i] == NULL) { - printf("error: cellpoolFree test failed (alloc 1), cell #%d\n", i); + printf("error: cmCellPoolFree test failed (alloc 1), cell #%d\n", i); status = CMUTILS_TEST_STATUS_FAILURE; break; } @@ -950,14 +950,14 @@ static int testCellPoolFree(void) { if (status == CMUTILS_TEST_STATUS_OK) { for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { - cellpoolFree(id, cells[i]); + cmCellPoolFree(id, cells[i]); cells[i] = NULL; } for (int i = 0; i < sizeof(cells) / sizeof(cells[0]); i++) { - cells[i] = cellpoolGet(id, isConditional); + cells[i] = cmCellPoolGet(id, isConditional); if (cells[i] == NULL) { - printf("error: cellpoolFree test failed (alloc 2), cell #%d\n", i); + printf("error: cmCellPoolFree test failed (alloc 2), cell #%d\n", i); status = CMUTILS_TEST_STATUS_FAILURE; break; } @@ -965,7 +965,7 @@ static int testCellPoolFree(void) { } - cellpoolDelete(id); + cmCellPoolDelete(id); return status; } diff --git a/h/cellpool.h b/h/cellpool.h new file mode 100644 index 000000000..7e2a5db39 --- /dev/null +++ b/h/cellpool.h @@ -0,0 +1,116 @@ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ + +#ifndef H_CELLPOOL_H_ +#define H_CELLPOOL_H_ + +#ifdef METTLE +#include +#include +#include +#else +#include +#include +#endif + +#include "zos.h" +#include "zowetypes.h" + +#ifndef __LONGNAME__ + +#define cellpoolGetDWordAlignedSize CPASIZE +#define cellpoolBuild CPBUILD +#define cellpoolDelete CPDELETE +#define cellpoolGet CPGET +#define cellpoolFree CPFREE + +#endif + +ZOWE_PRAGMA_PACK + +typedef int32_t CPID; + +typedef struct CPHeader_tag { + char text[24]; +} CPHeader; + +ZOWE_PRAGMA_PACK_RESET + +#define CPID_NULL 0 + +/** + * @brief Helper function to convert a size to its next 8-byte aligned value. + * This function can be used to ensure that the cells are aligned properly. + * @param size The value to be converted. + * @return 8-byte aligned value. + */ +unsigned int cellpoolGetDWordAlignedSize(unsigned int size); + +/** + * @brief Build a 31-bit cell pool. + * @details + * - When the function is called in SRB or cross-memory mode, the cell + * pool storage belongs to the TCB from ASCBXTCB, otherwise the storage will be + * owned by the TCB from PSATOLD. + * - In SRB and cross-memory modes the call requires elevated privileges + * (key 0-7, SUP state or APF). + * - The storage is aligned on the default CPOOL boundary, i.e. if the cell size + * is not a multiple of 4 or 8, cells do not reside on a particular boundary, + * otherwise the cells will reside on 4 and 8 byte boundaries respectively. + * @param pCellCount Primary cell count. + * @param sCellCount Secondary cell count. + * @param cellSize Cell size. + * @param subpool The subpool of the cell pool storage. + * @param key The key of the cell pool storage. + * @param header The cell pool header. + * @return The cell pool ID on success, CPID_NULL on failure. + */ +CPID cellpoolBuild(unsigned int pCellCount, + unsigned int sCellCount, + unsigned int cellSize, + int subpool, int key, + const CPHeader *header); + +/** + * @brief Delete a cell pool. + * @param cellpoolID The ID of the cell pool to be deleted. + */ +void cellpoolDelete(CPID cellpoolID); + +/** + * @brief Get a cell pool cell. + * @param cellpoolID The ID of the cell pool to get a cell from. + * @param conditional If true and the cell pool cannon get more storage, NULL is + * returned, otherwise the request will ABEND. + */ +void *cellpoolGet(CPID cellpoolID, bool conditional); + +/** + * @brief Release a cell pool cell. + * @param cellpoolID The ID of the cell pool to return the cell to. + * @param cell The cell to be returned. + */ +void cellpoolFree(CPID cellpoolID, void *cell); + +#endif /* H_CELLPOOL_H_ */ + + +/* + This program and the accompanying materials are + made available under the terms of the Eclipse Public License v2.0 which accompanies + this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html + + SPDX-License-Identifier: EPL-2.0 + + Copyright Contributors to the Zowe Project. +*/ +