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 1/2] 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. +*/ + From 2b4945e4d4014b46650b1a3a4f2f298a30c9ff70 Mon Sep 17 00:00:00 2001 From: David Crayford Date: Mon, 10 Feb 2020 21:59:25 +0800 Subject: [PATCH 2/2] Improve the performance of indexOfString Signed-off-by: David Crayford --- c/utils.c | 116 +++++++++++++++++++++++++++--------------------------- h/utils.h | 2 +- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/c/utils.c b/c/utils.c index f506e318e..5be7a9aa6 100644 --- a/c/utils.c +++ b/c/utils.c @@ -143,22 +143,24 @@ int lastIndexOf(const char *str, int len, char c) { return -1; } -int indexOfString(char *str, int len, char *searchString, int startPos){ - int searchLen = strlen(searchString); - int lastPossibleStart = len-searchLen; - int pos = startPos; - - if (startPos > lastPossibleStart){ - return -1; - } - while (pos <= lastPossibleStart){ - if (!memcmp(str+pos,searchString,searchLen)){ - return pos; - } - pos++; - } - return -1; -} +int indexOfString(const char *sourceString, size_t sourceLength, const char *searchString, size_t startPos) { + if (sourceString == NULL || sourceLength == 0 || searchString == NULL) return - 1; + size_t searchLength = strlen(searchString); + if (searchLength == 0) return -1; + const char * currPos = sourceString + startPos; + const char * endPos = sourceString + sourceLength - searchLength; + char firstChar = searchString[0]; + while (currPos < endPos) { + size_t bytesRemaining = endPos - currPos + 1; + currPos = memchr(currPos, firstChar, bytesRemaining); + if (currPos == NULL) break; + if (memcmp(currPos, searchString, searchLength) == 0) { + return currPos - sourceString; + } + currPos++; + } + return -1; +} int lastIndexOfString(char *str, int len, char *searchString) { int searchLen = strlen(searchString); @@ -381,10 +383,10 @@ token* tknGetStandard(char *str, int len, int start){ for (i=start; i= '2') && (c <= '7')){ - state = URL_PARM_PERCENT_NUMBER; - numChar = c; + state = URL_PARM_PERCENT_NUMBER; + numChar = c; } else{ - cleanValue[pos++] = '%'; + cleanValue[pos++] = '%'; cleanValue[pos++] = c; - state = URL_PARM_NORMAL; + state = URL_PARM_NORMAL; } break; case URL_PARM_PERCENT_NUMBER: highDigit = (numChar-'0')*0x10; if ((c >= '0') && (c <= '9')){ - cleanValue[pos++] = ascii[highDigit+(c-'0')]; - /* printf("highDigit %x (c-0) %x\n",highDigit,(c-'0')); */ - state = URL_PARM_NORMAL; + cleanValue[pos++] = ascii[highDigit+(c-'0')]; + /* printf("highDigit %x (c-0) %x\n",highDigit,(c-'0')); */ + state = URL_PARM_NORMAL; } else if ((c >= 'a') && (c <= 'f')){ - cleanValue[pos++] = ascii[highDigit+10+(c-'a')]; - state = URL_PARM_NORMAL; + cleanValue[pos++] = ascii[highDigit+10+(c-'a')]; + state = URL_PARM_NORMAL; } else if ((c >= 'A') && (c <= 'F')){ - cleanValue[pos++] = ascii[highDigit+10+(c-'A')]; - state = URL_PARM_NORMAL; + cleanValue[pos++] = ascii[highDigit+10+(c-'A')]; + state = URL_PARM_NORMAL; } else if (c == '%'){ - cleanValue[pos++] = '%'; + cleanValue[pos++] = '%'; cleanValue[pos++] = numChar; - state = URL_PARM_PERCENT; + state = URL_PARM_PERCENT; } else{ - cleanValue[pos++] = '%'; + cleanValue[pos++] = '%'; cleanValue[pos++] = numChar; - cleanValue[pos++] = c; - state = URL_PARM_NORMAL; + cleanValue[pos++] = c; + state = URL_PARM_NORMAL; } break; } @@ -1033,9 +1035,9 @@ int decodeBase64(char *s, char *result){ } static char binToB64[] ={0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, - 0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,0x63,0x64,0x65,0x66, - 0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76, - 0x77,0x78,0x79,0x7A,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2B,0x2F}; + 0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x61,0x62,0x63,0x64,0x65,0x66, + 0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76, + 0x77,0x78,0x79,0x7A,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2B,0x2F}; static char binToEB64[] ={0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7, 0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0x81,0x82,0x83,0x84,0x85,0x86, @@ -1586,7 +1588,7 @@ int stringListContains(StringList *list, char *s){ StringListElt *elt = list->head; while (elt){ if (!strcmp(elt->string,s)){ - return 1; + return 1; } elt = elt->next; } diff --git a/h/utils.h b/h/utils.h index 6d3295ff7..e7906f7cc 100644 --- a/h/utils.h +++ b/h/utils.h @@ -39,7 +39,7 @@ char * strcopy_safe(char * dest, const char * source, int dest_size); int indexOf(char *str, int len, char c, int startPos); int lastIndexOf(const char *str, int len, char c); -int indexOfString(char *str, int len, char *searchString, int startPos); +int indexOfString(const char * sourceString, size_t sourceLength, const char * searchString, size_t startPos); int lastIndexOfString(char *str, int len, char *searchString); int indexOfStringInsensitive(char *str, int len, char *searchString, int startPos);