From 833892caf77db14d8d999116dd1c01863d060f5d Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Fri, 19 Jul 2024 11:44:10 -0400 Subject: [PATCH] update missed file --- .gitignore | 398 ++++++++ sr_alpha/axp.h | 133 +++ sr_alpha/cacheflush.m64 | 27 + sr_alpha/double2s.c | 158 ++++ sr_alpha/emit_code_sp.c | 278 ++++++ sr_alpha/emit_code_sp.h | 206 ++++ sr_alpha/follow.m64 | 32 + sr_alpha/gtm_dump.c | 17 + sr_alpha/inst_flush.m64 | 24 + sr_alpha/mint2mval.m64 | 51 + sr_alpha/movq.m64 | 21 + sr_alpha/mval2bool.m64 | 39 + sr_alpha/mval2mint.m64 | 39 + sr_alpha/objlangdefs.h | 457 +++++++++ sr_alpha/op_call.m64 | 51 + sr_alpha/op_equnul.m64 | 61 ++ sr_alpha/op_forlcldo.m64 | 51 + sr_alpha/op_linestart.m64 | 24 + sr_alpha/op_pattern.m64 | 51 + sr_alpha/op_sorts_after.m64 | 41 + sr_alpha/pseudo_ret.m64 | 37 + sr_alpha/zbreaksp.h | 28 + sr_i386/merrors_ansi.h | 1364 +++++++++++++++++++++++++++ sr_i386/opp_indsavglvn.s | 39 + sr_i386/opp_indsavlvn.s | 39 + sr_linux/hugetlbfs_overrides.c | 112 +++ sr_linux/hugetlbfs_overrides.h | 25 + sr_linux/platform.cmake | 59 ++ sr_port/anticipatory_freeze.h | 344 +++++++ sr_port/create_temporaries.c | 125 +++ sr_port/dsewrap.mpt | 249 +++++ sr_port/f_get1.c | 70 ++ sr_port/f_zpeek.c | 78 ++ sr_port/f_zwrite.c | 60 ++ sr_port/glvn_pool.c | 99 ++ sr_port/glvn_pool.h | 139 +++ sr_port/gtm_common_defs.h | 146 +++ sr_port/gtm_ipv6.h | 134 +++ sr_port/iosocket_destroy.c | 51 + sr_port/lock_str_to_buff.c | 35 + sr_port/lock_str_to_buff.h | 17 + sr_port/mpiece.mpt | 38 + sr_port/mtables.h | 16 + sr_port/mu_put_gvn_fragment.c | 36 + sr_port/mupip_put_gvn_fragment.h | 17 + sr_port/op_fnget1.c | 28 + sr_port/op_fnzwrite.c | 44 + sr_port/op_glvnpop.c | 43 + sr_port/op_glvnslot.c | 68 ++ sr_port/op_igetdst.c | 21 + sr_port/op_indfnname2.c | 62 ++ sr_port/op_indget1.c | 54 ++ sr_port/op_indget2.c | 44 + sr_port/op_indmerge2.c | 54 ++ sr_port/op_indsavglvn.c | 121 +++ sr_port/op_indsavlvn.c | 93 ++ sr_port/op_litc.c | 34 + sr_port/op_rfrshgvn.c | 47 + sr_port/op_rfrshlvn.c | 86 ++ sr_port/op_savgvn.c | 68 ++ sr_port/op_savlvn.c | 79 ++ sr_port/op_shareslot.c | 43 + sr_port/op_stoglvn.c | 52 + sr_port/op_stolitc.c | 32 + sr_port/preemptive_db_clnup.c | 145 +++ sr_port/preemptive_db_clnup.h | 17 + sr_port/reorg_funcs.c | 184 ++++ sr_port/trim.mpt | 24 + sr_port/underr_strict.c | 33 + sr_unix/CMakeLists.txt | 788 ++++++++++++++++ sr_unix/anticipatory_freeze.c | 393 ++++++++ sr_unix/condstk_expand.c | 95 ++ sr_unix/custom_errors_sample.txt | 33 + sr_unix/file_head_write_secshr.c | 79 ++ sr_unix/gds_rundown_ch.c | 39 + sr_unix/gds_rundown_err_cleanup.c | 91 ++ sr_unix/gds_rundown_err_cleanup.h | 16 + sr_unix/grab_crit_immediate.c | 108 +++ sr_unix/gt_timers_add_safe_hndlrs.c | 29 + sr_unix/gt_timers_add_safe_hndlrs.h | 17 + sr_unix/gtm_asm_establish.c | 24 + sr_unix/gtm_c_stack_trace.c | 147 +++ sr_unix/gtm_conv_init.c | 100 ++ sr_unix/gtm_system.c | 88 ++ sr_unix/gtmdbgflags.h | 49 + sr_unix/gtmsource_freeze.c | 65 ++ sr_unix/iott_iocontrol.c | 54 ++ sr_unix/mu_replpool_release_sem.c | 186 ++++ sr_unix/mu_size_arsample.c | 400 ++++++++ sr_unix/mu_size_impsample.c | 281 ++++++ sr_unix/mu_size_scan.c | 354 +++++++ sr_unix/mu_swap_root.c | 462 +++++++++ sr_unix/mupip_size.c | 210 +++++ sr_unix/mupip_size.h | 23 + sr_unix/op_fnzpeek.c | 664 +++++++++++++ sr_unix/repl_logfileinfo_get.c | 80 ++ sr_unix/show_install_config.sh | 54 ++ sr_unix/util_help.c | 63 ++ sr_unix/util_help.h | 16 + sr_unix/wait_for_disk_space.c | 155 +++ sr_unix/wait_for_disk_space.h | 17 + sr_vvms/grab_crit_immediate.c | 109 +++ sr_vvms/kitprepare.com | 73 ++ sr_vvms/spkitupdate.com | 28 + sr_x86_64/merrors_ansi.h | 1364 +++++++++++++++++++++++++++ sr_x86_64/opp_indsavglvn.s | 38 + sr_x86_64/opp_indsavlvn.s | 38 + 107 files changed, 13822 insertions(+) create mode 100644 .gitignore create mode 100644 sr_alpha/axp.h create mode 100644 sr_alpha/cacheflush.m64 create mode 100644 sr_alpha/double2s.c create mode 100644 sr_alpha/emit_code_sp.c create mode 100644 sr_alpha/emit_code_sp.h create mode 100644 sr_alpha/follow.m64 create mode 100644 sr_alpha/gtm_dump.c create mode 100644 sr_alpha/inst_flush.m64 create mode 100644 sr_alpha/mint2mval.m64 create mode 100644 sr_alpha/movq.m64 create mode 100644 sr_alpha/mval2bool.m64 create mode 100644 sr_alpha/mval2mint.m64 create mode 100644 sr_alpha/objlangdefs.h create mode 100644 sr_alpha/op_call.m64 create mode 100644 sr_alpha/op_equnul.m64 create mode 100644 sr_alpha/op_forlcldo.m64 create mode 100644 sr_alpha/op_linestart.m64 create mode 100644 sr_alpha/op_pattern.m64 create mode 100644 sr_alpha/op_sorts_after.m64 create mode 100644 sr_alpha/pseudo_ret.m64 create mode 100644 sr_alpha/zbreaksp.h create mode 100644 sr_i386/merrors_ansi.h create mode 100644 sr_i386/opp_indsavglvn.s create mode 100644 sr_i386/opp_indsavlvn.s create mode 100644 sr_linux/hugetlbfs_overrides.c create mode 100644 sr_linux/hugetlbfs_overrides.h create mode 100644 sr_linux/platform.cmake create mode 100644 sr_port/anticipatory_freeze.h create mode 100644 sr_port/create_temporaries.c create mode 100644 sr_port/dsewrap.mpt create mode 100644 sr_port/f_get1.c create mode 100644 sr_port/f_zpeek.c create mode 100644 sr_port/f_zwrite.c create mode 100644 sr_port/glvn_pool.c create mode 100644 sr_port/glvn_pool.h create mode 100644 sr_port/gtm_common_defs.h create mode 100644 sr_port/gtm_ipv6.h create mode 100644 sr_port/iosocket_destroy.c create mode 100644 sr_port/lock_str_to_buff.c create mode 100644 sr_port/lock_str_to_buff.h create mode 100644 sr_port/mpiece.mpt create mode 100644 sr_port/mtables.h create mode 100644 sr_port/mu_put_gvn_fragment.c create mode 100644 sr_port/mupip_put_gvn_fragment.h create mode 100644 sr_port/op_fnget1.c create mode 100644 sr_port/op_fnzwrite.c create mode 100644 sr_port/op_glvnpop.c create mode 100644 sr_port/op_glvnslot.c create mode 100644 sr_port/op_igetdst.c create mode 100644 sr_port/op_indfnname2.c create mode 100644 sr_port/op_indget1.c create mode 100644 sr_port/op_indget2.c create mode 100644 sr_port/op_indmerge2.c create mode 100644 sr_port/op_indsavglvn.c create mode 100644 sr_port/op_indsavlvn.c create mode 100644 sr_port/op_litc.c create mode 100644 sr_port/op_rfrshgvn.c create mode 100644 sr_port/op_rfrshlvn.c create mode 100644 sr_port/op_savgvn.c create mode 100644 sr_port/op_savlvn.c create mode 100644 sr_port/op_shareslot.c create mode 100644 sr_port/op_stoglvn.c create mode 100644 sr_port/op_stolitc.c create mode 100644 sr_port/preemptive_db_clnup.c create mode 100644 sr_port/preemptive_db_clnup.h create mode 100644 sr_port/reorg_funcs.c create mode 100644 sr_port/trim.mpt create mode 100644 sr_port/underr_strict.c create mode 100644 sr_unix/CMakeLists.txt create mode 100644 sr_unix/anticipatory_freeze.c create mode 100644 sr_unix/condstk_expand.c create mode 100644 sr_unix/custom_errors_sample.txt create mode 100644 sr_unix/file_head_write_secshr.c create mode 100644 sr_unix/gds_rundown_ch.c create mode 100644 sr_unix/gds_rundown_err_cleanup.c create mode 100644 sr_unix/gds_rundown_err_cleanup.h create mode 100644 sr_unix/grab_crit_immediate.c create mode 100644 sr_unix/gt_timers_add_safe_hndlrs.c create mode 100644 sr_unix/gt_timers_add_safe_hndlrs.h create mode 100644 sr_unix/gtm_asm_establish.c create mode 100644 sr_unix/gtm_c_stack_trace.c create mode 100644 sr_unix/gtm_conv_init.c create mode 100644 sr_unix/gtm_system.c create mode 100644 sr_unix/gtmdbgflags.h create mode 100644 sr_unix/gtmsource_freeze.c create mode 100644 sr_unix/iott_iocontrol.c create mode 100644 sr_unix/mu_replpool_release_sem.c create mode 100644 sr_unix/mu_size_arsample.c create mode 100644 sr_unix/mu_size_impsample.c create mode 100644 sr_unix/mu_size_scan.c create mode 100644 sr_unix/mu_swap_root.c create mode 100644 sr_unix/mupip_size.c create mode 100644 sr_unix/mupip_size.h create mode 100644 sr_unix/op_fnzpeek.c create mode 100644 sr_unix/repl_logfileinfo_get.c create mode 100644 sr_unix/show_install_config.sh create mode 100644 sr_unix/util_help.c create mode 100644 sr_unix/util_help.h create mode 100644 sr_unix/wait_for_disk_space.c create mode 100644 sr_unix/wait_for_disk_space.h create mode 100644 sr_vvms/grab_crit_immediate.c create mode 100644 sr_vvms/kitprepare.com create mode 100644 sr_vvms/spkitupdate.com create mode 100644 sr_x86_64/merrors_ansi.h create mode 100644 sr_x86_64/opp_indsavglvn.s create mode 100644 sr_x86_64/opp_indsavlvn.s diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..937c52e --- /dev/null +++ b/.gitignore @@ -0,0 +1,398 @@ +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Gradle Patch ### +**/build/ + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + + +### Intellij+iml ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+iml Patch ### +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar +.flattened-pom.xml + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +### Node Patch ### +# Serverless Webpack directories +.webpack/ + +# Optional stylelint cache + +# SvelteKit build / generate output +.svelte-kit + + +### yarn ### + +.yarn/* +!.yarn/releases +!.yarn/patches +!.yarn/plugins +!.yarn/sdks +!.yarn/versions + +# if you are NOT using Zero-installs, then: +# comment the following lines +!.yarn/cache + +# and uncomment the following lines +# .pnp.* + +### CVS ### +/CVS/* +**/CVS/* +.cvsignore +*/.cvsignore \ No newline at end of file diff --git a/sr_alpha/axp.h b/sr_alpha/axp.h new file mode 100644 index 0000000..1f514ce --- /dev/null +++ b/sr_alpha/axp.h @@ -0,0 +1,133 @@ +/**************************************************************** + * * + * Copyright 2001, 2002 Sanchez Computer Associates, Inc. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +/* axp.h - AXP machine instruction information. + * + * Requires "axp_registers.h" and "axp_gtm_registers.h". + * + */ + + +/* Machine instruction templates. */ + +#define ALPHA_INS_ADDL ((unsigned)0x10 << ALPHA_SHIFT_OP) +#define ALPHA_INS_BEQ ((unsigned)0x39 << ALPHA_SHIFT_OP) +#define ALPHA_INS_BGE ((unsigned)0x3e << ALPHA_SHIFT_OP) +#define ALPHA_INS_BGT ((unsigned)0x3f << ALPHA_SHIFT_OP) +#define ALPHA_INS_BIS ((unsigned)0x11 << ALPHA_SHIFT_OP | 0x20 << ALPHA_SHIFT_FUNC) +#define ALPHA_INS_BLE ((unsigned)0x3b << ALPHA_SHIFT_OP) +#define ALPHA_INS_BLT ((unsigned)0x3a << ALPHA_SHIFT_OP) +#define ALPHA_INS_BLBC ((unsigned)0x38 << ALPHA_SHIFT_OP) +#define ALPHA_INS_BLBS ((unsigned)0x3c << ALPHA_SHIFT_OP) +#define ALPHA_INS_BNE ((unsigned)0x3d << ALPHA_SHIFT_OP) +#define ALPHA_INS_BSR ((unsigned)0x34 << ALPHA_SHIFT_OP) +#define ALPHA_INS_BR ((unsigned)0x30 << ALPHA_SHIFT_OP) +#define ALPHA_INS_JMP ((unsigned)0x1a << ALPHA_SHIFT_OP) +#define ALPHA_INS_JSR ((unsigned)0x1a << ALPHA_SHIFT_OP | 1 << ALPHA_SHIFT_BRANCH_FUNC) +#define ALPHA_INS_LDA ((unsigned)0x08 << ALPHA_SHIFT_OP) +#define ALPHA_INS_LDAH ((unsigned)0x09 << ALPHA_SHIFT_OP) +#define ALPHA_INS_LDL ((unsigned)0x28 << ALPHA_SHIFT_OP) +#define ALPHA_INS_LDQ ((unsigned)0x29 << ALPHA_SHIFT_OP) +#define ALPHA_INS_RET ((unsigned)0x1a << ALPHA_SHIFT_OP | 2 << ALPHA_SHIFT_BRANCH_FUNC) +#define ALPHA_INS_STL ((unsigned)0x2c << ALPHA_SHIFT_OP) +#define ALPHA_INS_STQ ((unsigned)0x2d << ALPHA_SHIFT_OP) +#define ALPHA_INS_SUBL ((unsigned)0x10 << ALPHA_SHIFT_OP | 0x9 << ALPHA_SHIFT_FUNC) +#define ALPHA_INS_SUBQ ((unsigned)0x10 << ALPHA_SHIFT_OP | 0x29 << ALPHA_SHIFT_FUNC) + + +/* Bit offsets to instruction fields. */ + +#define ALPHA_SHIFT_OP 26 +#define ALPHA_SHIFT_BRANCH_FUNC 14 +#define ALPHA_SHIFT_FUNC 5 +#define ALPHA_SHIFT_LITERAL 13 +#define ALPHA_SHIFT_RA 21 +#define ALPHA_SHIFT_RB 16 +#define ALPHA_SHIFT_RC 0 +#define ALPHA_SHIFT_BRANCH_DISP 0 +#define ALPHA_SHIFT_DISP 0 + + +/* Bit masks for instruction fields. */ + +#define ALPHA_BIT_LITERAL (1 << 12) +#define ALPHA_MASK_BRANCH_DISP 0x1fffff +#define ALPHA_MASK_BRANCH_FUNC 0xc00000 +#define ALPHA_MASK_DISP 0xffff +#define ALPHA_MASK_FUNC 0x7f +#define ALPHA_MASK_LITERAL 0xff +#define ALPHA_MASK_OP 0x3f +#define ALPHA_MASK_REG 0x1f + + +/* Alternative assembler mnemonics for machine instruction. */ + +#define ALPHA_INS_CLRQ (ALPHA_INS_BIS \ + | (ALPHA_REG_ZERO << ALPHA_SHIFT_RA) \ + | (ALPHA_REG_ZERO << ALPHA_SHIFT_RB)) +#define ALPHA_INS_LPC (ALPHA_INS_BR \ + | (GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA)) +#define ALPHA_INS_MOVE (ALPHA_INS_BIS \ + | ALPHA_REG_ZERO << ALPHA_SHIFT_RB) +#define ALPHA_INS_NOP (ALPHA_INS_BIS \ + | (ALPHA_REG_ZERO << ALPHA_SHIFT_RA) \ + | (ALPHA_REG_ZERO << ALPHA_SHIFT_RB) \ + | (ALPHA_REG_ZERO << ALPHA_SHIFT_RC)) + + +/* Construction forms. */ + +#define ALPHA_BRA(op,ra,disp) ((op) | ((ra) << ALPHA_SHIFT_RA) | (disp)&ALPHA_MASK_BRANCH_DISP) +#define ALPHA_JMP(op,ra,rb) ((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB)) +#define ALPHA_LIT(op,ra,lit,rc) ((op) | ((ra) << ALPHA_SHIFT_RA) \ + | (((lit)&ALPHA_MASK_LITERAL) << ALPHA_SHIFT_LITERAL) \ + | ALPHA_BIT_LITERAL \ + | ((rc) << ALPHA_SHIFT_RC)) +#define ALPHA_MEM(op,ra,rb,disp)((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB) | (disp)&ALPHA_MASK_DISP) +#define ALPHA_OPR(op,ra,rb,rc) ((op) | ((ra) << ALPHA_SHIFT_RA) | ((rb) << ALPHA_SHIFT_RB) | ((rc) << ALPHA_SHIFT_RC)) + +#ifdef DEBUG +#define GET_OPCODE(ains) ((ains >> ALPHA_SHIFT_OP) & ALPHA_MASK_OP) +#define GET_RA(ains) ((ains >> ALPHA_SHIFT_RA) & ALPHA_MASK_REG) +#define GET_RB(ains) ((ains >> ALPHA_SHIFT_RB) & ALPHA_MASK_REG) +#define GET_RC(ains) ((ains >> ALPHA_SHIFT_RC) & ALPHA_MASK_REG) +#define GET_MEMDISP(ains) ((ains >> ALPHA_SHIFT_DISP) & ALPHA_MASK_DISP) +#define GET_BRDISP(ains) ((ains >> ALPHA_SHIFT_BRANCH_DISP) & ALPHA_MASK_BRANCH_DISP) +#define GET_FUNC(ains) ((ains >> ALPHA_SHIFT_FUNC) & ALPHA_MASK_FUNC) + +#define ADDL_INST "addl" +#define SUBL_INST "subl" +#define SUBQ_INST "subq" +#define BIS_INST "bis" +#define JSR_INST "jsr" +#define RET_INST "ret" +#define JMP_INST "jmp" +#define LDA_INST "lda" +#define LDAH_INST "ldah" +#define LDL_INST "ldl" +#define LDQ_INST "ldq" +#define STL_INST "stl" +#define STQ_INST "stq" +#define BR_INST "br" +#define BSR_INST "bsr" +#define BLBC_INST "blbc" +#define BEQ_INST "beq" +#define BLT_INST "blt" +#define BLE_INST "ble" +#define BLBS_INST "blbs" +#define BNE_INST "bne" +#define BGE_INST "bge" +#define BGT_INST "bgt" +#define CONSTANT "Constant 0x" + +/* Space for op_code to be in */ +#define OPSPC 7 +#endif diff --git a/sr_alpha/cacheflush.m64 b/sr_alpha/cacheflush.m64 new file mode 100644 index 0000000..27a553d --- /dev/null +++ b/sr_alpha/cacheflush.m64 @@ -0,0 +1,27 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title cacheflush - flush data and instruction caches + +; cacheflush +; +; entry: +; a0 (r16) address of start of region to flush +; a1 (r17) length (in bytes) of region to flush +; a2 (r18) flag indicating which region to flush (not used on AXP) + + $routine name=cacheflush, entry=cacheflush_ca, kind=null + + imb + + ret r26 + + $end_routine name=cacheflush diff --git a/sr_alpha/double2s.c b/sr_alpha/double2s.c new file mode 100644 index 0000000..7b7efd8 --- /dev/null +++ b/sr_alpha/double2s.c @@ -0,0 +1,158 @@ +/**************************************************************** + * * + * Copyright 2001, 2009 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "stringpool.h" + +#define MAX_NUM_SIZE 64 + +GBLREF spdesc stringpool; + +static char pot_index [256] = + { + -78, 78, -77, 77, 77, 77, -76, 76, 76, -75, 75, 75, -74, 74, 74, 74, + -73, 73, 73, -72, 72, 72, -71, 71, 71, 71, -70, 70, 70, -69, 69, 69, + -68, 68, 68, -67, 67, 67, 67, -66, 66, 66, -65, 65, 65, -64, 64, 64, + 64, -63, 63, 63, -62, 62, 62, -61, 61, 61, 61, -60, 60, 60, -59, 59, + 59, -58, 58, 58, 58, -57, 57, 57, -56, 56, 56, -55, 55, 55, 55, -54, + 54, 54, -53, 53, 53, -52, 52, 52, 52, -51, 51, 51, -50, 50, 50, -49, + 49, 49, 49, -48, 48, 48, -47, 47, 47, -46, 46, 46, 46, -45, 45, 45, + -44, 44, 44, -43, 43, 43, 43, -42, 42, 42, -41, 41, 41, -40, 40, 40, + 40, -39, 39, 39, -38, 38, 38, -37, 37, 37, -36, 36, 36, 36, -35, 35, + 35, -34, 34, 34, -33, 33, 33, 33, -32, 32, 32, -31, 31, 31, -30, 30, + 30, 30, -29, 29, 29, -28, 28, 28, -27, 27, 27, 27, -26, 26, 26, -25, + 25, 25, -24, 24, 24, 24, -23, 23, 23, -22, 22, 22, -21, 21, 21, 21, + -20, 20, 20, -19, 19, 19, -18, 18, 18, 18, -17, 17, 17, -16, 16, 16, + -15, 15, 15, 15, -14, 14, 14, -13, 13, 13, -12, 12, 12, 12, -11, 11, + 11, -10, 10, 10, -9, 9, 9, -8, 8, 8, 8, -7, 7, 7, -6, 6, + 6, -5, 5, 5, 5, -4, 4, 4, -3, 3, 3, -2, 2, 2, 2, -1 + }; + +static double pot [79] = + { + 1.701411834604692e+38 + 2.83e+22, + 1e+38, 1e+37, 1e+36, 1e+35, 1e+34, 1e+33, 1e+32, + 1e+31, 1e+30, 1e+29, 1e+28, 1e+27, 1e+26, 1e+25, 1e+24, + 1e+23, 1e+22, 1e+21, 1e+20, 1e+19, 1e+18, 1e+17, 1e+16, + 1e+15, 1e+14, 1e+13, 1e+12, 1e+11, 1e+10, 1e+9, 1e+8, + 1e+7, 1e+6, 1e+5, 1e+4, 1e+3, 1e+2, 1e+1, 1.0, + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, + 1e-9, 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, + 1e-17, 1e-18, 1e-19, 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, + 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, 1e-30, 1e-31, 1e-32, + 1e-33, 1e-34, 1e-35, 1e-36, 1e-37, 1e-38, 0 + }; + +#define POT_UNITY 39 /* Subscript of pot: pot[POT_UNITY] == 1.0 */ + + +struct D_float /* Format of D-floating point datum */ +{ + unsigned int : 7; /* fraction, bits 0:6 */ + unsigned int exp : 8; /* exponent, bits 7:14 */ + unsigned int sign : 1; /* sign, bit 15 */ + unsigned int : 16; /* fraction, bits 16:31 */ + unsigned int : 32; /* fraction, bits 32:63 */ +}; + +void double2s (double *dp, mval *v) +{ + double d = *dp; + char *p, *q; + int i, j, k; + + ENSURE_STP_FREE_SPACE(MAX_NUM_SIZE); + assert (stringpool.free >= stringpool.base); + v->mvtype = MV_STR; + p = v->str.addr + = (char *)stringpool.free; + + if (d == 0.0) + *p++ = '0'; + else + { + if (d < 0.0) + { + *p++ = '-'; /* plug in a minus sign */ + d = -d; /* but make d positive */ + } + + i = pot_index[((struct D_float *)dp)->exp]; + if (i < 0) + { + i = -i; + if (d < pot[i]) + ++i; + } + i = POT_UNITY + 1 - i; + + /* "Normalize" the number; i.e. adjust it to be between 0.0 and 1.0 */ + d *= pot[i + POT_UNITY]; + + if (d < 5e-16) + /* Call it zero */ + *p++ = '0'; + else + { + /* Round the sixteenth digit */ + d += 5e-16; + + if (d >= 1.0) + { + /* Readjust it to be between 0.0 and 1.0 */ + d /= 10.0; + ++i; + } + + q = p; /* q will point to the last non-zero byte */ + j = i; + + if (i <= 0) + { + *p++ = '.'; + for (; i < 0; ++i) + *p++ = '0'; + } + + for (i = 15; i > 0; --i) + { + /* Multiply the value by ten, put the integer portion + of the result into k (0 <= k <= 9), and replace the + value with the fractional portion of the result */ + k = d *= 10.0; + d -= k; + + *p++ = '0' + k; + + if (k > 0) + q = p; + if (--j == 0) + { + q = p; + *p++ = '.'; + } + } + + if (j > 0) + do + *p++ = '0'; + while (--j > 0); + else + p = q; + } + } + + v->str.len = p - (char *)stringpool.free; + stringpool.free = (unsigned char *)p; + assert(stringpool.free <= stringpool.top); + + return; +} diff --git a/sr_alpha/emit_code_sp.c b/sr_alpha/emit_code_sp.c new file mode 100644 index 0000000..6aaf4b7 --- /dev/null +++ b/sr_alpha/emit_code_sp.c @@ -0,0 +1,278 @@ +/**************************************************************** + * * + * Copyright 2001, 2009 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "cgp.h" +#include "compiler.h" +#include +#include "list_file.h" +#include + +GBLREF uint4 code_buf[]; /* Instruction buffer */ +GBLREF int code_idx; /* Index into code_buf */ +GBLREF char cg_phase; /* Current compiler phase */ +GBLREF int4 curr_addr; +#ifdef DEBUG +GBLREF unsigned char *obpt; /* output buffer index */ +GBLREF unsigned char outbuf[]; /* assembly language output buffer */ +static unsigned int ains; /* assembler instruction (binary) */ +#endif + + +/* Used by emit_base_offset to extract offset parts */ +int alpha_adjusted_upper(int offset) +{ + int upper; + + upper = (offset >> 16) & 0xFFFF; + if (offset & 0x8000) + upper = (upper + 1) & 0xFFFF; + + return upper; +} + + +void emit_base_offset(int base, int offset) +{ + /* NOTE: emit_base_offset does not advance past its last + generated instruction because that instruction is + incomplete; it contains only a base and offset -- the + rt and opcode field are left empty for use by the caller. */ + int upper, low, source; + + switch (cg_phase) + { +#ifdef DEBUG + case CGP_ASSEMBLY: +#endif + case CGP_ADDR_OPT: + case CGP_APPROX_ADDR: + case CGP_MACHINE: + assert(base >= 0 && base <= 31); + source = base; + upper = alpha_adjusted_upper(offset); + + if (0 != upper) + { + code_buf[code_idx++] = ALPHA_INS_LDAH + | (GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA) + | (source << ALPHA_SHIFT_RB) + | (upper & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP; + source = GTM_REG_CODEGEN_TEMP; + } + low = offset & 0xFFFF; + code_buf[code_idx] = source << ALPHA_SHIFT_RB + | (low & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP; + break; + default: + GTMASSERT; + } +} + + +#ifdef DEBUG +void fmt_ra() +{ + *obpt++ = 'r'; + obpt = i2asc(obpt, GET_RA(ains)); +} +void fmt_ra_rb() +{ + fmt_ra(); + *obpt++ = ','; + *obpt++; + *obpt++ = 'r'; + obpt = i2asc(obpt, GET_RB(ains)); +} +void fmt_ra_rb_rc() +{ + fmt_ra_rb(); + *obpt++ = ','; + *obpt++; + *obpt++ = 'r'; + obpt = i2asc(obpt, GET_RC(ains)); +} +void fmt_ra_mem() +{ + fmt_ra(); + *obpt++ = ','; + obpt++; + *obpt++ = '0'; + *obpt++ = 'x'; + obpt += i2hex_nofill(GET_MEMDISP(ains), obpt, 6); + *obpt++ = '('; + *obpt++ = 'r'; + obpt = i2asc(obpt, GET_RB(ains)); + *obpt++ = ')'; +} +void fmt_ra_brdisp() +{ + fmt_ra(); + *obpt++ = ','; + obpt++; + *obpt++ = '0'; + *obpt++ = 'x'; + obpt += i2hex_nofill(GET_BRDISP(ains) * 4, obpt, 6); +} +void format_machine_inst(void) +{ + int instindx; + + for (instindx = 0; instindx < code_idx; instindx++) + { + list_chkpage(); + obpt = &outbuf[0]; + memset(obpt, SP, ASM_OUT_BUFF); + obpt += 10; + i2hex((curr_addr - SIZEOF(rhdtyp)), (uchar_ptr_t)obpt, 8); + curr_addr += 4; + obpt += 10; + i2hex(code_buf[instindx], (uchar_ptr_t)obpt, 8); + obpt += 10; + ains = code_buf[instindx]; + switch(GET_OPCODE(ains)) + { + case 0x8: + memcpy(obpt, LDA_INST, SIZEOF(LDA_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x9: + memcpy(obpt, LDAH_INST, SIZEOF(LDAH_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x10: + /* Note opcodes 0x10, 0x11, have overlapping functions but none that we generate + so we can combine their disassembly. + */ + case 0x11: + switch(GET_FUNC(ains)) + { + case 0x0: /* main opcode 0x10 */ + memcpy(obpt, ADDL_INST, SIZEOF(ADDL_INST) - 1); + break; + case 0x9: /* main opcode 0x10 */ + memcpy(obpt, SUBL_INST, SIZEOF(SUBL_INST) - 1); + break; + case 0x29: /* main opcode 0x10 */ + memcpy(obpt, SUBQ_INST, SIZEOF(SUBQ_INST) - 1); + break; + case 0x20: /* main opcode 0x11 */ + memcpy(obpt, BIS_INST, SIZEOF(BIS_INST) - 1); + break; + default: + GTMASSERT; + } + obpt += OPSPC; + fmt_ra_rb_rc(); + break; + case 0x1a: + switch(GET_MEMDISP(ains) & 0x3) + { + case 0x0: + memcpy(obpt, JMP_INST, SIZEOF(JMP_INST) - 1); + break; + case 0x1: + memcpy(obpt, JSR_INST, SIZEOF(JSR_INST) - 1); + break; + case 0x2: + memcpy(obpt, RET_INST, SIZEOF(RET_INST) - 1); + break; + default: + GTMASSERT; + } + obpt += OPSPC; + fmt_ra_rb(); + break; + case 0x28: + memcpy(obpt, LDL_INST, SIZEOF(LDL_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x29: + memcpy(obpt, LDQ_INST, SIZEOF(LDQ_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x2c: + memcpy(obpt, STL_INST, SIZEOF(STL_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x2d: + memcpy(obpt, STQ_INST, SIZEOF(STQ_INST) - 1); + obpt += OPSPC; + fmt_ra_mem(); + break; + case 0x30: + memcpy(obpt, BR_INST, SIZEOF(BR_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x34: + memcpy(obpt, BSR_INST, SIZEOF(BSR_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x38: + memcpy(obpt, BLBC_INST, SIZEOF(BLBC_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x39: + memcpy(obpt, BEQ_INST, SIZEOF(BEQ_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3a: + memcpy(obpt, BLT_INST, SIZEOF(BLT_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3b: + memcpy(obpt, BLE_INST, SIZEOF(BLE_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3c: + memcpy(obpt, BLBS_INST, SIZEOF(BLBS_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3d: + memcpy(obpt, BNE_INST, SIZEOF(BNE_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3e: + memcpy(obpt, BGE_INST, SIZEOF(BGE_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + case 0x3f: + memcpy(obpt, BGT_INST, SIZEOF(BGT_INST) - 1); + obpt += OPSPC; + fmt_ra_brdisp(); + break; + default: /* Not an instruction but a constant */ + memcpy(obpt, CONSTANT, SIZEOF(CONSTANT) - 1); + obpt += SIZEOF(CONSTANT) - 1; + i2hex(ains, obpt, 8); + obpt += 8; + } + emit_eoi(); + } +} +#endif diff --git a/sr_alpha/emit_code_sp.h b/sr_alpha/emit_code_sp.h new file mode 100644 index 0000000..c7da71b --- /dev/null +++ b/sr_alpha/emit_code_sp.h @@ -0,0 +1,206 @@ +/**************************************************************** + * * + * Copyright 2003, 2009 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef EMIT_CODE_SP_INCLUDED +#define EMIT_CODE_SP_INCLUDED + +#include "axp_registers.h" +#include "axp_gtm_registers.h" +#include "axp.h" + +void emit_base_offset(int base, int offset); +int alpha_adjusted_upper(int offset); + +#ifdef DEBUG +void format_machine_inst(void); +void fmt_ra(void); +void fmt_ra_rb(void); +void fmt_ra_rb_rc(void); +void fmt_ra_mem(void); +void fmt_ra_brdisp(void); +#endif + +#define INST_SIZE (int)SIZEOF(uint4) +#define BRANCH_OFFSET_FROM_IDX(idx_start, idx_end) (idx_end - (idx_start + 1)) +#define LONG_JUMP_OFFSET (0x4ffffffc) /* should be large enough to force the long jump instruction sequence */ +#define MAX_BRANCH_CODEGEN_SIZE 32 /* The length in bytes, of the longest form of branch instruction sequence */ + +#define MAX_OFFSET 0x3fff +#define STACK_ARG_OFFSET(indx) (8 * (indx)) /* All arguments on Alpha platforms are 8 bytes wide on stack */ +#define MACHINE_FIRST_ARG_REG ALPHA_REG_A0 + +/* Register usage in some of the code generation expansions */ +#define CALLS_TINT_TEMP_REG ALPHA_REG_R1 +#define CLRL_REG ALPHA_REG_ZERO +#define CMPL_TEMP_REG ALPHA_REG_T1 +#define GET_ARG_REG(indx) (ALPHA_REG_A0 + (indx)) +#define MOVC3_SRC_REG ALPHA_REG_R0 +#define MOVC3_TRG_REG ALPHA_REG_R1 +#define MOVL_RETVAL_REG ALPHA_REG_V0 +#define MOVL_REG_R1 ALPHA_REG_R1 + +/* Macros to define the opcodes for use in emit_jmp() and emit_tip() args */ + +#define GENERIC_OPCODE_BEQ ((uint4)ALPHA_INS_BEQ) +#define GENERIC_OPCODE_BGE ((uint4)ALPHA_INS_BGE) +#define GENERIC_OPCODE_BGT ((uint4)ALPHA_INS_BGT) +#define GENERIC_OPCODE_BLE ((uint4)ALPHA_INS_BLE) +#define GENERIC_OPCODE_BLT ((uint4)ALPHA_INS_BLT) +#define GENERIC_OPCODE_BNE ((uint4)ALPHA_INS_BNE) +#define GENERIC_OPCODE_BLBC ((uint4)ALPHA_INS_BLBC) +#define GENERIC_OPCODE_BLBS ((uint4)ALPHA_INS_BLBS) +#define GENERIC_OPCODE_BR ((uint4)ALPHA_INS_BR) +#define GENERIC_OPCODE_LDA ((uint4)ALPHA_INS_LDA) +#define GENERIC_OPCODE_LOAD ((uint4)ALPHA_INS_LDL) +#define GENERIC_OPCODE_STORE ((uint4)ALPHA_INS_STL) +#define GENERIC_OPCODE_NOP ((uint4)ALPHA_INS_NOP) + +/* Macro to extract parts of generic opcodes */ +#define GENXCT_LOAD_SRCREG(inst) ((inst >> ALPHA_SHIFT_RB) & ALPHA_MASK_REG) + +/* Macros to create specific generated code sequences */ + +/* Note that the GEN_CLEAR/SET_TRUTH macros are only used on VMS (TRUTH_IN_REG) */ +#define GEN_CLEAR_TRUTH code_buf[code_idx++] = (ALPHA_INS_STL | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \ + | GTM_REG_DOLLAR_TRUTH << ALPHA_SHIFT_RB \ + | 0 << ALPHA_SHIFT_DISP) +#define GEN_SET_TRUTH { \ + code_buf[code_idx++] = (ALPHA_INS_BIS | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \ + | 1 << ALPHA_SHIFT_LITERAL | ALPHA_BIT_LITERAL \ + | GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RC); \ + code_buf[code_idx++] = (ALPHA_INS_STL | GTM_REG_CODEGEN_TEMP << ALPHA_SHIFT_RA \ + | GTM_REG_DOLLAR_TRUTH << ALPHA_SHIFT_RB \ + | 0 << ALPHA_SHIFT_DISP); \ + } +#define GEN_LOAD_ADDR(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_LDA | reg << ALPHA_SHIFT_RA \ + | breg << ALPHA_SHIFT_RB \ + | (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP) +#define GEN_LOAD_WORD(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_LDL | reg << ALPHA_SHIFT_RA \ + | breg << ALPHA_SHIFT_RB \ + | (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP) +#define GEN_STORE_WORD(reg, breg, disp) code_buf[code_idx++] = (ALPHA_INS_STL | reg << ALPHA_SHIFT_RA \ + | breg << ALPHA_SHIFT_RB \ + | (disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP) +#define GEN_LOAD_IMMED(reg, disp) GEN_LOAD_ADDR(reg, ALPHA_REG_ZERO, disp) +#define GEN_CLEAR_WORD_EMIT(reg) emit_trip(*(fst_opr + *inst++), TRUE, ALPHA_INS_STL, reg) +#define GEN_LOAD_WORD_EMIT(reg) emit_trip(*(fst_opr + *inst++), TRUE, ALPHA_INS_LDL, reg) +#define GEN_SUBTRACT_REGS(src1, src2, trgt) \ + code_buf[code_idx++] = (ALPHA_INS_SUBL \ + | src1 << ALPHA_SHIFT_RA \ + | src2 << ALPHA_SHIFT_RB \ + | trgt << ALPHA_SHIFT_RC) +#define GEN_ADD_IMMED(reg, imval) code_buf[code_idx++] = (ALPHA_INS_ADDL \ + | reg << ALPHA_SHIFT_RA \ + | imval << ALPHA_SHIFT_LITERAL | ALPHA_BIT_LITERAL \ + | reg << ALPHA_SHIFT_RC) +#define GEN_JUMP_REG(reg) code_buf[code_idx++] = (ALPHA_INS_JMP | ALPHA_REG_ZERO << ALPHA_SHIFT_RA \ + | reg << ALPHA_SHIFT_RB) +#define GEN_STORE_ARG(reg, offset) code_buf[code_idx++] = (ALPHA_INS_STQ | reg << ALPHA_SHIFT_RA \ + | ALPHA_REG_SP << ALPHA_SHIFT_RB \ + | (offset & ALPHA_MASK_DISP) << ALPHA_SHIFT_DISP) +#define GEN_PCREL code_buf[code_idx++] = (ALPHA_INS_LPC) +#define GEN_MOVE_REG(trg, src) code_buf[code_idx++] = (ALPHA_INS_MOVE | src << ALPHA_SHIFT_RA | trg << ALPHA_SHIFT_RC) + +#if defined(__vms) +/* CALL_INST_SIZE is the byte length of the minimum-length instruction sequence to implement a transfer + * table call. In the case of OpenVMS AXP, this is the sequence: + * + * ldl r27, xfer(r11) ; get address of procedure descriptor from transfer table + * ldq r26, 8(r27) ; get code address of procedure from procedure descriptor + * jmp r26, (r26) ; call it + * + * This value is used to determine how to adjust the offset value for a relative call and may not + * be appropriate for the Alpha because VAX relative calls are emulated on the Alpha differently. +*/ +# define CALL_INST_SIZE (3 * INST_SIZE) +# define GEN_XFER_TBL_CALL(xfer) \ + { \ + emit_base_offset(GTM_REG_XFER_TABLE, xfer); \ + code_buf[code_idx++] |= ALPHA_INS_LDL | ALPHA_REG_PV << ALPHA_SHIFT_RA; \ + emit_base_offset(ALPHA_REG_PV, 8); \ + code_buf[code_idx++] |= ALPHA_INS_LDQ | ALPHA_REG_RA << ALPHA_SHIFT_RA; \ + code_buf[code_idx++] = ALPHA_INS_JSR | ALPHA_REG_RA << ALPHA_SHIFT_RA | ALPHA_REG_RA << ALPHA_SHIFT_RB; \ + } +#elif defined(__osf__) +/* CALL_INST_SIZE is the byte length of the minimum-length instruction sequence to implement a transfer + * table call. In the case of OSF/1 (Digital Unix) AXP, this is the sequence: + * + * ldl r27, offset(r12) # get address of entry point from transfer table + * jmp r26, (r27) # call it + * + * This value is used to determine how to adjust the offset value for a relative call and may not + * be appropriate for the Alpha because VAX relative calls are emulated on the Alpha differently. +*/ +# define CALL_INST_SIZE (2 * INST_SIZE) +# define GEN_XFER_TBL_CALL(xfer) \ + { \ + emit_base_offset(GTM_REG_XFER_TABLE, xfer); \ + code_buf[code_idx++] |= ALPHA_INS_LDL | ALPHA_REG_PV << ALPHA_SHIFT_RA; \ + code_buf[code_idx++] = ALPHA_INS_JSR | ALPHA_REG_RA << ALPHA_SHIFT_RA | ALPHA_REG_PV << ALPHA_SHIFT_RB; \ + } +#else +# error "Unsupported platform" +#endif + + +/* Macros to return an instruction value. This is typcically used to modify an instruction + that is already in the instruction buffer such as the last instruction that was created + by emit_pcrel(). +*/ +#define IGEN_COND_BRANCH_REG_OFFSET(opcode, reg, disp) (opcode | ((reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA) \ + | ((disp & ALPHA_MASK_DISP) << ALPHA_SHIFT_BRANCH_DISP)) +#define IGEN_UCOND_BRANCH_REG_OFFSET(opcode, reg, disp) IGEN_COND_BRANCH_REG_OFFSET(opcode, reg, disp) +#define IGEN_LOAD_ADDR_REG(reg) (ALPHA_INS_LDA | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA) +#define IGEN_LOAD_WORD_REG(reg) (ALPHA_INS_LDL | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA) +#define IGEN_LOAD_NATIVE_REG(reg) IGEN_LOAD_WORD_REG(reg) +#define IGEN_COND_BRANCH_OFFSET(disp) ((disp & ALPHA_MASK_BRANCH_DISP) << ALPHA_SHIFT_BRANCH_DISP) +#define IGEN_UCOND_BRANCH_OFFSET(disp) IGEN_COND_BRANCH_OFFSET(disp) +#define IGEN_LOAD_LINKAGE(reg) (ALPHA_INS_LDQ | (reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA) +#define IGEN_GENERIC_REG(opcode, reg) (opcode | ((reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA)) + +/* Some macros that are used in certain routines in emit_code.c. The names of these + macros start with the routine name they are used in. +*/ + +/* Branch has origin of +1 instructions. However, if the branch was nullified in an earlier shrink_trips, + * the origin is the current instruction itself */ +#define EMIT_JMP_ADJUST_BRANCH_OFFSET branch_offset = ((branch_offset != 0) ? branch_offset - 1 : 0) +/* Can jump be done within range of immediate operand */ +#define EMIT_JMP_SHORT_CODE_CHECK (branch_offset >= (-(ALPHA_MASK_BRANCH_DISP/2) - 1) \ + && branch_offset <= (ALPHA_MASK_BRANCH_DISP/2)) +/* Emit the short jump */ +#define EMIT_JMP_SHORT_CODE_GEN \ +{ \ + code_buf[code_idx++] = (branchop | (reg << ALPHA_SHIFT_RA) \ + | ((branch_offset & ALPHA_MASK_BRANCH_DISP) << ALPHA_SHIFT_BRANCH_DISP)); \ + branch_offset--; \ +} +/* Is this a conditional branch? */ +#define EMIT_JMP_OPPOSITE_BR_CHECK (branchop != ALPHA_INS_BR && (branchop != ALPHA_INS_BEQ || reg != ALPHA_REG_ZERO)) +#define EMIT_JMP_GEN_COMPARE /* No compare necessary */ +#define EMIT_JMP_LONG_CODE_CHECK FALSE +/* Is the offset field in this instruction zero? */ +#define EMIT_JMP_ZERO_DISP_COND (0 == ((code_buf[code_idx] >> ALPHA_SHIFT_DISP) & ALPHA_MASK_DISP)) +/* Emit code to load a given numeric literal */ +#define EMIT_TRIP_ILIT_GEN { /* Emit liternal number */ \ + emit_base_offset(ALPHA_REG_ZERO, immediate); \ + code_buf[code_idx++] |= (ALPHA_INS_LDA | \ + (trg_reg & ALPHA_MASK_REG) << ALPHA_SHIFT_RA); \ + } +/* + * GT.M on AIX and SPARC is 64bit + * By default the loads/stores use ldd/std(load double), + * but if the value being dealt with is a word,the + * opcode in generic_inst is changed to ldw/stw + */ +#define REVERT_GENERICINST_TO_WORD(inst) + +#endif diff --git a/sr_alpha/follow.m64 b/sr_alpha/follow.m64 new file mode 100644 index 0000000..7267a82 --- /dev/null +++ b/sr_alpha/follow.m64 @@ -0,0 +1,32 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title FOLLOW "Allows run-time modules to call OP_FOLLOW" + +; FOLLOW simply passes its two arguments, which are pointers to +; mval's, to OP_FOLLOW, which expects them in registers r0 and r1. +; OP_FOLLOW returns 1, 0, or -1; FOLLOW returns a boolean result: +; 1 (true) if OP_FOLLOW returned 1, otherwise 0 (false). + + $routine FOLLOW, entry=FOLLOW_CA, kind=stack + .base r27, $ls + + sextl r16, r0 + sextl r17, r1 + $call OP_FOLLOW, set_arg_info=false + sextl r0, r0 + cmovlt r0, 0, r0 + + $return + + $end_routine + + .end diff --git a/sr_alpha/gtm_dump.c b/sr_alpha/gtm_dump.c new file mode 100644 index 0000000..422d9b7 --- /dev/null +++ b/sr_alpha/gtm_dump.c @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2001 Sanchez Computer Associates, Inc. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +/*** STUB FILE ***/ + +#include "mdef.h" +#include "error.h" + +void gtm_dump(void) {}; diff --git a/sr_alpha/inst_flush.m64 b/sr_alpha/inst_flush.m64 new file mode 100644 index 0000000..8f63803 --- /dev/null +++ b/sr_alpha/inst_flush.m64 @@ -0,0 +1,24 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title inst_flush flush instruction cache + +; inst_flush is a C-callable routine that makes the instruction cache coherent with memory. + + $routine name=inst_flush,entry=inst_flush_ca,kind=null + + imb + + ret r26 + + $end_routine name=inst_flush + + .end diff --git a/sr_alpha/mint2mval.m64 b/sr_alpha/mint2mval.m64 new file mode 100644 index 0000000..262527d --- /dev/null +++ b/sr_alpha/mint2mval.m64 @@ -0,0 +1,51 @@ + .title mint2mval "Convert integer to mval" + +; ############################################################### +; # # +; # Copyright 2001, 2004 Sanchez Computer Associates, Inc. # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ############################################################### + +; On input, r1 = integer value, r0 -> mval + + mval$def + + $linkage_section + +int_hi_val: + .quad INT_HI + + $routine MINT2MVAL, entry=MINT2MVAL_CA, kind=null + lda sp, -24(sp) + stq r26, (sp) + stq r13, 8(sp) + mov r27, r13 + .base r13, $ls + + ldq r22, int_hi_val + cmplt r1, r22, r28 + beq r28, 11$ ; int >= INT_HI + negq r22, r22 + cmple r1, r22, r28 + bne r28, 11$ ; int <= -INT_HI + + mv_i2mval r1, r0 + +12$: ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 24(sp) + ret r26 + +11$: mov r0, r16 + mov r1, r17 + $call I2MVAL, args=, set_arg_info=false, nonstandard=true + br 12$ + + $end_routine + + .end diff --git a/sr_alpha/movq.m64 b/sr_alpha/movq.m64 new file mode 100644 index 0000000..ef9d980 --- /dev/null +++ b/sr_alpha/movq.m64 @@ -0,0 +1,21 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title movq move quadword + + $routine name=movq,entry=movq_ca,kind=null + + ldq r28, (r16) + stq r28, (r17) + + ret r26 + + $end_routine name=movq diff --git a/sr_alpha/mval2bool.m64 b/sr_alpha/mval2bool.m64 new file mode 100644 index 0000000..d294d1f --- /dev/null +++ b/sr_alpha/mval2bool.m64 @@ -0,0 +1,39 @@ +; ################################################################ +; # # +; # Copyright 2000, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title mval2bool "Sets condition code from mval" + +; On entry, r1 -> mval. +; On exit, r24 = numeric value of mval + + mval$def + + $routine MVAL2BOOL, entry=MVAL2BOOL_CA, kind=null + lda sp, -24(sp) + stq r26, (sp) + stq r13, 8(sp) + mov r27, r13 + .base r13, $ls + + mv_force_defined r1 + stq r1, 16(sp) + mv_force_num (r1) + ldq r1, 16(sp) + ldl r24, mval$l_m1(r1) + + ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 24(sp) + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/mval2mint.m64 b/sr_alpha/mval2mint.m64 new file mode 100644 index 0000000..a27508c --- /dev/null +++ b/sr_alpha/mval2mint.m64 @@ -0,0 +1,39 @@ +; ################################################################ +; # # +; # Copyright 2000, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title mval2mint "Converts an mval to integer" + +; On entry, r1 -> mval +; On exit, r0 = integer value + + mval$def + + $routine MVAL2MINT, entry=MVAL2MINT_CA, kind=null + lda sp, -24(sp) + stq r26, (sp) + stq r13, 8(sp) + mov r27, r13 + .base r13, $ls + + mv_force_defined r1 + stq r1, 16(sp) + mv_force_num (r1) + ldq r16, 16(sp) + $call MVAL2I, args=, set_arg_info=false, nonstandard=true + + ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 24(sp) + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/objlangdefs.h b/sr_alpha/objlangdefs.h new file mode 100644 index 0000000..1d5d6c0 --- /dev/null +++ b/sr_alpha/objlangdefs.h @@ -0,0 +1,457 @@ +/**************************************************************** + * * + * Copyright 2001 Sanchez Computer Associates, Inc. * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +/* Object record types: */ +#define EOBJ$C_EMH 8 +#define EOBJ$C_EEOM 9 +#define EOBJ$C_EGSD 10 +#define EOBJ$C_ETIR 11 +#define EOBJ$C_EDBG 12 +#define EOBJ$C_ETBT 13 +#define EOBJ$C_MAXRECTYP 13 + +/* Byte offsets into object record and related constants: */ +#define EOBJ$K_SUBTYP 4 +#define EOBJ$C_SUBTYP 4 +#define EOBJ$C_MAXRECSIZ 8192 +#define EOBJ$C_STRLVL 2 +#define EOBJ$C_SYMSIZ 31 +#define EOBJ$C_STOREPLIM -1 +#define EOBJ$C_PSCALILIM 16 +#define EOBJ$S_EOBJRECDEF 10 +#define EOBJ$W_RECTYP 0 +#define EOBJ$W_SIZE 2 +#define EOBJ$W_SUBTYP 4 +#define EOBJ$B_MHD_STRLV 6 +#define EOBJ$B_MHD_HOLD 7 +#define EOBJ$W_MHD_RECSZ 8 +#define EOBJ$T_MHD_NAME 10 + +/* Object header record (EOBJ$C_EMH) subtypes: */ +#define EMH$C_MHD 0 +#define EMH$C_LNM 1 +#define EMH$C_SRC 2 +#define EMH$C_TTL 3 +#define EMH$C_CPR 4 +#define EMH$C_MTC 5 +#define EMH$C_GTX 6 +#define EMH$C_MAXHDRTYP 6 + +/* Byte offsets of fields in object header record (EOBJ$C_EMH): */ +#define EMH$S_EMHDEF 52 +#define EMH$W_RECTYP 0 +#define EMH$W_SIZE 2 +#define EMH$W_HDRTYP 4 +#define EMH$B_STRLVL 6 +#define EMH$B_TEMP 7 +#define EMH$L_ARCH1 8 +#define EMH$L_ARCH2 12 +#define EMH$L_RECSIZ 16 +#define EMH$B_NAMLNG 20 +#define EMH$S_NAME 31 +#define EMH$T_NAME 21 + +#define EEOM$C_SUCCESS 0 +#define EEOM$C_WARNING 1 +#define EEOM$C_ERROR 2 +#define EEOM$C_ABORT 3 +#define EEOM$K_EOMMIN 10 +#define EEOM$C_EOMMIN 10 +#define EEOM$K_EOMMX1 10 +#define EEOM$C_EOMMX1 10 +#define EEOM$M_WKTFR 0X1 +#define EEOM$K_EOMMAX 24 +#define EEOM$C_EOMMAX 24 +#define EEOM$S_EEOMDEF 24 +#define EEOM$W_RECTYP 0 +#define EEOM$W_SIZE 2 +#define EEOM$L_TOTAL_LPS 4 +#define EEOM$W_COMCOD 8 +#define EEOM$B_TFRFLG 10 +#define EEOM$V_WKTFR 0 +#define EEOM$B_TEMP 11 +#define EEOM$L_PSINDX 12 +#define EEOM$S_TFRADR 8 +#define EEOM$Q_TFRADR 16 +#define EEOM$L_TFRADR 16 + + +#define EGSD$K_ENTRIES 2 +#define EGSD$C_ENTRIES 2 + +#define EGSD$C_PSC 0 +#define EGSD$C_SYM 1 +#define EGSD$C_IDC 2 +#define EGSD$C_ENV 3 +#define EGSD$C_LSY 4 +#define EGSD$C_SPSC 5 +#define EGSD$C_SYMV 6 +#define EGSD$C_SYMM 7 +#define EGSD$C_SYMG 8 +#define EGSD$C_MAXRECTYP 8 + +#define EGSD$S_EGSDEF 12 +#define EGSD$W_RECTYP 0 +#define EGSD$W_RECSIZ 2 +#define EGSD$L_ALIGNLW 4 +#define EGSD$W_GSDTYP 8 +#define EGSD$W_GSDSIZ 10 + +#define EGPS$M_PIC 0X1 +#define EGPS$M_LIB 0X2 +#define EGPS$M_OVR 0X4 +#define EGPS$M_REL 0X8 +#define EGPS$M_GBL 0X10 +#define EGPS$M_SHR 0X20 +#define EGPS$M_EXE 0X40 +#define EGPS$M_RD 0X80 +#define EGPS$M_WRT 0X100 +#define EGPS$M_VEC 0X200 +#define EGPS$M_NOMOD 0X400 +#define EGPS$M_COM 0X800 +#define EGPS$K_NAME 12 +#define EGPS$C_NAME 12 +#define EGPS$S_EGPSDEF 44 +#define EGPS$W_GSDTYP 0 +#define EGPS$T_START 0 +#define EGPS$W_SIZE 2 +#define EGPS$B_ALIGN 4 +#define EGPS$B_TEMP 5 +#define EGPS$W_FLAGS 6 +#define EGPS$V_PIC 0 +#define EGPS$V_LIB 1 +#define EGPS$V_OVR 2 +#define EGPS$V_REL 3 +#define EGPS$V_GBL 4 +#define EGPS$V_SHR 5 +#define EGPS$V_EXE 6 +#define EGPS$V_RD 7 +#define EGPS$V_WRT 8 +#define EGPS$V_VEC 9 +#define EGPS$V_NOMOD 10 +#define EGPS$V_COM 11 +#define EGPS$L_ALLOC 8 +#define EGPS$B_NAMLNG 12 +#define EGPS$S_NAME 31 +#define EGPS$T_NAME 13 + +#define ESGPS$M_PIC 0X1 +#define ESGPS$M_LIB 0X2 +#define ESGPS$M_OVR 0X4 +#define ESGPS$M_REL 0X8 +#define ESGPS$M_GBL 0X10 +#define ESGPS$M_SHR 0X20 +#define ESGPS$M_EXE 0X40 +#define ESGPS$M_RD 0X80 +#define ESGPS$M_WRT 0X100 +#define ESGPS$M_VEC 0X200 +#define ESGPS$M_NOMOD 0X400 +#define ESGPS$M_COM 0X800 +#define ESGPS$K_NAME 25 +#define ESGPS$C_NAME 25 +#define ESGPS$S_ESGPSDEF 56 +#define ESGPS$W_GSDTYP 0 +#define ESGPS$T_START 0 +#define ESGPS$W_SIZE 2 +#define ESGPS$B_ALIGN 4 +#define ESGPS$B_TEMP 5 +#define ESGPS$W_FLAGS 6 +#define ESGPS$V_PIC 0 +#define ESGPS$V_LIB 1 +#define ESGPS$V_OVR 2 +#define ESGPS$V_REL 3 +#define ESGPS$V_GBL 4 +#define ESGPS$V_SHR 5 +#define ESGPS$V_EXE 6 +#define ESGPS$V_RD 7 +#define ESGPS$V_WRT 8 +#define ESGPS$V_VEC 9 +#define ESGPS$V_NOMOD 10 +#define ESGPS$V_COM 11 +#define ESGPS$L_ALLOC 8 +#define ESGPS$L_BASE 12 +#define ESGPS$S_VALUE 8 +#define ESGPS$Q_VALUE 16 +#define ESGPS$L_VALUE 16 +#define ESGPS$B_NAMLNG 24 +#define ESGPS$S_NAME 31 +#define ESGPS$T_NAME 25 + +#define EGSY$M_WEAK 0X1 +#define EGSY$M_DEF 0X2 +#define EGSY$M_UNI 0X4 +#define EGSY$M_REL 0X8 +#define EGSY$M_COMM 0X10 +#define EGSY$M_VECEP 0X20 +#define EGSY$M_NORM 0X40 +#define EGSY$S_EGSYDEF 8 +#define EGSY$W_GSDTYP 0 +#define EGSY$T_START 0 +#define EGSY$W_SIZE 2 +#define EGSY$B_DATYP 4 +#define EGSY$B_TEMP 5 +#define EGSY$W_FLAGS 6 +#define EGSY$V_WEAK 0 +#define EGSY$V_DEF 1 +#define EGSY$V_UNI 2 +#define EGSY$V_REL 3 +#define EGSY$V_COMM 4 +#define EGSY$V_VECEP 5 +#define EGSY$V_NORM 6 + +#define EGST$K_NAME 37 +#define EGST$C_NAME 37 +#define EGST$S_EGSTDEF 68 +#define EGST$W_GSDTYP 0 +#define EGST$T_START 0 +#define EGST$W_SIZE 2 +#define EGST$B_DATYP 4 +#define EGST$B_TEMP 5 +#define EGST$W_FLAGS 6 +#define EGST$S_VALUE 8 +#define EGST$Q_VALUE 8 +#define EGST$L_VALUE 8 +#define EGST$S_LP_1 8 +#define EGST$Q_LP_1 16 +#define EGST$L_LP_1 16 +#define EGST$S_LP_2 8 +#define EGST$Q_LP_2 24 +#define EGST$L_LP_2 24 +#define EGST$L_PSINDX 32 +#define EGST$B_NAMLNG 36 +#define EGST$S_NAME 31 +#define EGST$T_NAME 37 + +#define ESDF$K_NAME 33 +#define ESDF$C_NAME 33 +#define ESDF$S_ESDFDEF 64 +#define ESDF$W_GSDTYP 0 +#define ESDF$T_START 0 +#define ESDF$W_SIZE 2 +#define ESDF$B_DATYP 4 +#define ESDF$B_TEMP 5 +#define ESDF$W_FLAGS 6 +#define ESDF$S_VALUE 8 +#define ESDF$Q_VALUE 8 +#define ESDF$L_VALUE 8 +#define ESDF$S_CODE_ADDRESS 8 +#define ESDF$Q_CODE_ADDRESS 16 +#define ESDF$L_CODE_ADDRESS 16 +#define ESDF$L_CA_PSINDX 24 +#define ESDF$L_PSINDX 28 +#define ESDF$B_NAMLNG 32 +#define ESDF$S_NAME 31 +#define ESDF$T_NAME 33 + +#define ESDFV$K_NAME 25 +#define ESDFV$C_NAME 25 +#define ESDFV$S_ESDFVDEF 56 +#define ESDFV$W_GSDTYP 0 +#define ESDFV$T_START 0 +#define ESDFV$W_SIZE 2 +#define ESDFV$B_DATYP 4 +#define ESDFV$B_TEMP 5 +#define ESDFV$W_FLAGS 6 +#define ESDFV$S_VALUE 8 +#define ESDFV$Q_VALUE 8 +#define ESDFV$L_VALUE 8 +#define ESDFV$L_PSINDX 16 +#define ESDFV$L_VECTOR 20 +#define ESDFV$B_NAMLNG 24 +#define ESDFV$S_NAME 31 +#define ESDFV$T_NAME 25 +#define ESDFM$K_NAME 25 +#define ESDFM$C_NAME 25 +#define ESDFM$S_ESDFMDEF 56 +#define ESDFM$W_GSDTYP 0 +#define ESDFM$T_START 0 +#define ESDFM$W_SIZE 2 +#define ESDFM$B_DATYP 4 +#define ESDFM$B_TEMP 5 +#define ESDFM$W_FLAGS 6 +#define ESDFM$S_VALUE 8 +#define ESDFM$Q_VALUE 8 +#define ESDFM$L_VALUE 8 +#define ESDFM$L_PSINDX 16 +#define ESDFM$L_VERSION_MASK 20 +#define ESDFM$B_NAMLNG 24 +#define ESDFM$S_NAME 31 +#define ESDFM$T_NAME 25 +#define ESRF$K_NAME 9 +#define ESRF$C_NAME 9 +#define ESRF$S_ESRFDEF 40 +#define ESRF$W_GSDTYP 0 +#define ESRF$T_START 0 +#define ESRF$W_SIZE 2 +#define ESRF$B_DATYP 4 +#define ESRF$B_TEMP 5 +#define ESRF$W_FLAGS 6 +#define ESRF$B_NAMLNG 8 +#define ESRF$S_NAME 31 +#define ESRF$T_NAME 9 +#define EIDC$C_LEQ 0 +#define EIDC$C_EQUAL 1 +#define EIDC$S_EIDCDEF 7 +#define EIDC$W_GSDTYP 0 +#define EIDC$W_SIZE 2 +#define EIDC$B_NAMLNG 4 +#define EIDC$T_NAME 5 +#define EIDC$W_FLAGS 5 +#define EIDC$V_BINIDENT 0 +#define EIDC$S_IDMATCH 2 +#define EIDC$V_IDMATCH 1 +#define EIDC$S_ERRSEV 3 +#define EIDC$V_ERRSEV 3 + +#define EENV$M_DEF 0X1 +#define EENV$M_NESTED 0X2 +#define EENV$S_EENVDEF 40 +#define EENV$W_GSDTYP 0 +#define EENV$W_SIZE 2 +#define EENV$W_FLAGS 4 +#define EENV$V_DEF 0 +#define EENV$V_NESTED 1 +#define EENV$W_ENVINDX 6 +#define EENV$B_NAMLNG 8 +#define EENV$S_NAME 31 +#define EENV$T_NAME 9 + +#define ELSY$M_WEAK 0X1 +#define ELSY$M_DEF 0X2 +#define ELSY$M_UNI 0X4 +#define ELSY$M_REL 0X8 +#define ELSY$S_ELSYDEF 14 +#define ELSY$W_GSDTYP 0 +#define ELSY$T_START 0 +#define ELSY$W_SIZE 2 +#define ELSY$B_DATYP 4 +#define ELSY$B_TEMP1 5 +#define ELSY$W_FLAGS 6 +#define ELSY$V_WEAK 0 +#define ELSY$V_DEF 1 +#define ELSY$V_UNI 2 +#define ELSY$V_REL 3 +#define ELSY$L_PSINDX 8 +#define ELSY$W_ENVINDX 12 + +#define ELSRF$K_NAME 17 +#define ELSRF$C_NAME 17 +#define ELSRF$S_ELSRFDEF 48 +#define ELSRF$W_GSDTYP 0 +#define ELSRF$T_START 0 +#define ELSRF$W_SIZE 2 +#define ELSRF$B_DATYP 4 +#define ELSRF$B_TEMP1 5 +#define ELSRF$W_FLAGS 6 +#define ELSRF$L_PSINDX 8 +#define ELSRF$W_ENVINDX 12 +#define ELSRF$W_TEMP2 14 +#define ELSRF$B_NAMLNG 16 +#define ELSRF$S_NAME 31 +#define ELSRF$T_NAME 17 + +#define ELSDF$K_NAME 25 +#define ELSDF$C_NAME 25 +#define ELSDF$S_ELSDFDEF 56 +#define ELSDF$W_GSDTYP 0 +#define ELSDF$T_START 0 +#define ELSDF$W_SIZE 2 +#define ELSDF$B_DATYP 4 +#define ELSDF$B_TEMP1 5 +#define ELSDF$W_FLAGS 6 +#define ELSDF$S_VALUE 8 +#define ELSDF$Q_VALUE 8 +#define ELSDF$L_VALUE 8 +#define ELSDF$L_PSINDX 16 +#define ELSDF$W_ENVINDX 20 +#define ELSDF$W_TEMP2 22 +#define ELSDF$B_NAMLNG 24 +#define ELSDF$S_NAME 31 +#define ELSDF$T_NAME 25 + +/* ETIR command types: */ +/* ETIR stack commands: */ +#define ETIR$C_MINSTACOD 0 +#define ETIR$C_STA_GBL 0 +#define ETIR$C_STA_LW 1 +#define ETIR$C_STA_QW 2 +#define ETIR$C_STA_PQ 3 +#define ETIR$C_STA_LI 4 +#define ETIR$C_STA_MOD 5 +#define ETIR$C_STA_CKARG 6 +#define ETIR$C_MAXSTACOD 6 + +#define ETIR$C_MINSTOCOD 50 +#define ETIR$C_STO_B 50 +#define ETIR$C_STO_W 51 +#define ETIR$C_STO_LW 52 +#define ETIR$C_STO_QW 53 +#define ETIR$C_STO_IMMR 54 +#define ETIR$C_STO_GBL 55 +#define ETIR$C_STO_CA 56 +#define ETIR$C_STO_RB 57 +#define ETIR$C_STO_AB 58 +#define ETIR$C_STO_OFF 59 +#define ETIR$C_STO_IMM 61 +#define ETIR$C_STO_GBL_LW 62 +#define ETIR$C_STO_HINT_GBL 64 +#define ETIR$C_STO_HINT_PS 65 +#define ETIR$C_MAXSTOCOD 65 + +#define ETIR$C_MINOPRCOD 100 +#define ETIR$C_OPR_NOP 100 +#define ETIR$C_OPR_ADD 101 +#define ETIR$C_OPR_SUB 102 +#define ETIR$C_OPR_MUL 103 +#define ETIR$C_OPR_DIV 104 +#define ETIR$C_OPR_AND 105 +#define ETIR$C_OPR_IOR 106 +#define ETIR$C_OPR_EOR 107 +#define ETIR$C_OPR_NEG 108 +#define ETIR$C_OPR_COM 109 +#define ETIR$C_OPR_INSV 110 +#define ETIR$C_OPR_ASH 111 +#define ETIR$C_OPR_USH 112 +#define ETIR$C_OPR_ROT 113 +#define ETIR$C_OPR_SEL 114 +#define ETIR$C_OPR_REDEF 115 +#define ETIR$C_OPR_DFLIT 116 +#define ETIR$C_MAXOPRCOD 116 + +#define ETIR$C_MINCTLCOD 150 +#define ETIR$C_CTL_SETRB 150 +#define ETIR$C_CTL_AUGRB 151 +#define ETIR$C_CTL_DFLOC 152 +#define ETIR$C_CTL_STLOC 153 +#define ETIR$C_CTL_STKDL 154 +#define ETIR$C_MAXCTLCOD 154 + +#define ETIR$C_MINSTCCOD 200 +#define ETIR$C_STC_LP 200 +#define ETIR$C_STC_LP_PSB 201 +#define ETIR$C_STC_GBL 202 +#define ETIR$C_STC_GCA 203 +#define ETIR$C_STC_PS 204 +#define ETIR$C_STC_NOP_GBL 205 +#define ETIR$C_STC_NOP_PS 206 +#define ETIR$C_STC_BSR_GBL 207 +#define ETIR$C_STC_BSR_PS 208 +#define ETIR$C_STC_LDA_GBL 209 +#define ETIR$C_STC_LDA_PS 210 +#define ETIR$C_STC_BOH_GBL 211 +#define ETIR$C_STC_BOH_PS 212 +#define ETIR$C_STC_NBH_GBL 213 +#define ETIR$C_STC_NBH_PS 214 +#define ETIR$C_MAXSTCCOD 214 + +#define ETIR$S_ETIRDEF 4 +#define ETIR$W_RECTYP 0 +#define ETIR$W_SIZE 2 diff --git a/sr_alpha/op_call.m64 b/sr_alpha/op_call.m64 new file mode 100644 index 0000000..d2e6d27 --- /dev/null +++ b/sr_alpha/op_call.m64 @@ -0,0 +1,51 @@ + .title OP_CALL +; ############################################################### +; # # +; # Copyright 2001, 2003 Sanchez Computer Associates, Inc. # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ############################################################### + + G_MSF + + + $linkage_section + +a_frame_pointer: + .address frame_pointer + + + $code_section + + $routine OP_CALLB, entry=OP_CALL_CA, aliases=, kind=null + + lda sp, -16(sp) + stq r13, 8(sp) + stq r26, (sp) + mov r27, r13 + .base r13, $ls + + ldq r1, a_frame_pointer + ldl r1, (r1) + +; Bump the return PC past the branch sequence following the jsr that got us here: + addl r26, r16, r26 ; length of branch sequence + stl r26, msf$mpc_off(r1) ; and store it in the Mumps stack frame + + $call COPY_STACK_FRAME, set_arg_info=false, nonstandard=true + + ldq r12, a_frame_pointer + ldl r12, (r12) + + ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 16(sp) + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/op_equnul.m64 b/sr_alpha/op_equnul.m64 new file mode 100644 index 0000000..713ecc3 --- /dev/null +++ b/sr_alpha/op_equnul.m64 @@ -0,0 +1,61 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title OP_EQUNUL "Compare mval to null string" + + mval$def + + + $linkage_section + +a_undef_inhibit: + .address undef_inhibit + + + $code_section + + $routine OP_EQUNUL, entry=OP_EQUNUL_CA, kind=null + .base r27, $ls + + mv_if_notdefined (r0), 30$ + + mv_if_notstring (r0), 20$ + ldl r28, mval$l_strlen(r0) + bne r28, 20$ + +; Mval is a null string +10$: mov 1, r24 + ret r26 + +; Mval is not a null string +20$: clr r24 + ret r26 + +; If undef_inhibit is set, then all undefined values are equal to the null string: +30$: ldq r28, a_undef_inhibit + ldq_u r24, (r28) + extbl r24, r28, r24 + bne r24, 10$ ; it's set; treat mval as a null string + +; It's not set, so issue a message: + lda sp, -8(sp) ; but first, + stq r26, (sp) ; save the return address + mov r0, r16 + $call UNDERR, args=, set_arg_info=false, nonstandard=true + + ldq r26, (sp) ; restore our return address + lda sp, 8(sp) + + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/op_forlcldo.m64 b/sr_alpha/op_forlcldo.m64 new file mode 100644 index 0000000..b88cdb3 --- /dev/null +++ b/sr_alpha/op_forlcldo.m64 @@ -0,0 +1,51 @@ + .title OP_FORLCLDO +; ############################################################### +; # # +; # Copyright 2001, 2003 Sanchez Computer Associates, Inc. # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ############################################################### + + G_MSF + + + $linkage_section + +a_frame_pointer: + .address frame_pointer + + + $code_section + + $routine OP_FORLCLDOB, entry=OP_FORLCLDO_CA, aliases=, kind=null + lda sp, -16(sp) + stq r13, 8(sp) + stq r26, (sp) + mov r27, r13 + .base r13, $ls + + ldq r1, a_frame_pointer + ldl r1, (r1) + +; Bump the return PC past the branch instruction following the jsr that got us here: + addl r26, r16, r26 ; length of branch sequence + stl r26, msf$mpc_off(r1) ; and store it in the Mumps stack frame + + $call EXFUN_FRAME, set_arg_info=false, nonstandard=true + + ldq r12, a_frame_pointer + ldl r12, (r12) + ldl r9, msf$temps_ptr_off(r12) + + ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 16(sp) + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/op_linestart.m64 b/sr_alpha/op_linestart.m64 new file mode 100644 index 0000000..725b26a --- /dev/null +++ b/sr_alpha/op_linestart.m64 @@ -0,0 +1,24 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title op_linestart + G_MSF + +; op_linestart - establish start of line in GT.M MUMPS stack frame + + $routine name=op_linestart,entry=op_linestart_ca,kind=null + + stl r26, msf$mpc_off(r12) + stl r13, msf$ctxt_off(r12) + + ret r26 + + $end_routine name=op_linestart diff --git a/sr_alpha/op_pattern.m64 b/sr_alpha/op_pattern.m64 new file mode 100644 index 0000000..726f0d8 --- /dev/null +++ b/sr_alpha/op_pattern.m64 @@ -0,0 +1,51 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title OP_PATTERN + + mval$def + + $routine OP_PATTERN, entry=OP_PATTERN_CA, kind=null + lda sp, -16(sp) + stq r13, 8(sp) + stq r26, (sp) + mov r27, r13 + .base r13, $ls + + mov r0, r16 + mov r1, r17 + + ; + ; This is an array of unaligned ints. If the first word is zero, then call do_pattern + ; instead of do_patfixed. Only the low order byte is significant and so it is the only + ; one we need to test. We would do this in assembly because (1) we need the assmembly + ; routine anyway to save the return value into $TEST and (2) it saves an extra level of + ; call linkage at the C level to do the decision here. + ; + ldl r28, mval$a_straddr(r1) + ldq_u r24, (r28) + extbl r24, r28, r24 + beq r24, 20$ + +10$: $call DO_PATFIXED, args=, set_arg_info=false, nonstandard=true + +15$: mov r0, r24 + ldq r26, (sp) + ldq r13, 8(sp) + lda sp, 16(sp) + ret r26 + +20$: $call DO_PATTERN, args=, set_arg_info=false, nonstandard=true + br 15$ + + $end_routine + + .end diff --git a/sr_alpha/op_sorts_after.m64 b/sr_alpha/op_sorts_after.m64 new file mode 100644 index 0000000..d664244 --- /dev/null +++ b/sr_alpha/op_sorts_after.m64 @@ -0,0 +1,41 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title OP_SORTS_AFTER + +; On entry: +; r0 -> mval for left hand side +; r1 -> mval for right hand side +; +; On exit: +; r24 < 0 : lhs ']] rhs (lhs ]] rhs is false) +; r24 = 0 : lhs = rhs (lhs ]] rhs is false) +; r24 > 0 : lhs ]] rhs (lhs ]] rhs is true) + + + $routine OP_SORTS_AFTER, entry=OP_SORTS_AFTER_CA, kind=null + lda sp, -8(sp) + stq r26, (sp) + .base r27, $ls + + mov r0, r16 + mov r1, r17 + $call SORTS_AFTER, args=, set_arg_info=false, nonstandard=true + mov r0, r24 + + ldq r26, (sp) + lda sp, 8(sp) + + ret r26 + + $end_routine + + .end diff --git a/sr_alpha/pseudo_ret.m64 b/sr_alpha/pseudo_ret.m64 new file mode 100644 index 0000000..3fa3e45 --- /dev/null +++ b/sr_alpha/pseudo_ret.m64 @@ -0,0 +1,37 @@ +; ################################################################ +; # # +; # Copyright 2001, 2008 Fidelity Information Services, Inc # +; # # +; # This source code contains the intellectual property # +; # of its copyright holder(s), and is made available # +; # under a license. If you do not know the terms of # +; # the license, please stop and do not read further. # +; # # +; ################################################################ + + .title PSEUDO_RET + +; PSEUDO_RET calls opp_ret (which doesn't return). It executes in a +; GT.M MUMPS stack frame and is, in fact, normally entered via a +; getframe/ret instruction sequence. +; +; entry: +; r13 - address of PSEUDO_RET's procedure descriptor (not r27) +; +; WARNING: because PSEUDO_RET is designed to be invoked from a GT.M +; MUMPS stack frame, it does not conform to the Alpha calling +; standard and cannot be invoked from any high-level language. The +; invoker should load the address of PSEUDO_RET's procedure descriptor +; into r13, not r27. + + + $code_section + + $routine PSEUDO_RET, entry=PSEUDO_RET_CA, kind=null + .base r13, $ls + + $call opp_ret, set_arg_info=false, nonstandard=true + + $end_routine + + .end diff --git a/sr_alpha/zbreaksp.h b/sr_alpha/zbreaksp.h new file mode 100644 index 0000000..cc91060 --- /dev/null +++ b/sr_alpha/zbreaksp.h @@ -0,0 +1,28 @@ +/**************************************************************** + * * + * Copyright 2001, 2009 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +typedef unsigned short zb_code; +#define ZB_CODE_MASK 0xffff +#define INST_TYPE zb_code + +/* The ZBreak command operates by finding the generated code for the op_linestart or op_linefetch for the source + * line in question and changing the offset in the transfer table load address instruction from the op_linestart or + * op_linefetch offset to the appropriate zbreak functionality opcode offset. + * In some platforms(IA64 and ZOS) since the INSTRUCTION LAYOUT is complex we need following + * macros for instruction manipulation. + * EXTRACT_OFFSET_TO_M_OPCODE + * FIX_OFFSET_WITH_ZBREAK_OFFSET + * EXTRACT_AND_UPDATE_INST + * These macros are called only when COMPLEX_INSTRUCTION_UPDATE is defined + * If COMPLEX_INSTRUCTION_UPDATE is not defined portable code in the caller of these macros + * is invoked. + */ +#undef COMPLEX_INSTRUCTION_UPDATE diff --git a/sr_i386/merrors_ansi.h b/sr_i386/merrors_ansi.h new file mode 100644 index 0000000..38cc6a1 --- /dev/null +++ b/sr_i386/merrors_ansi.h @@ -0,0 +1,1364 @@ +/**************************************************************** + * * + * Copyright 2001,2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + + +const static readonly int error_ansi[] = { + 0, /* ACK */ + 0, /* BREAKZST */ + 0, /* BADACCMTHD */ + 0, /* BADJPIPARAM */ + 0, /* BADSYIPARAM */ + 0, /* BITMAPSBAD */ + 0, /* BREAK */ + 0, /* BREAKDEA */ + 0, /* BREAKZBA */ + 0, /* STATCNT */ + 0, /* BTFAIL */ + 0, /* MUPRECFLLCK */ + 0, /* CMD */ + 0, /* COLON */ + 0, /* COMMA */ + 0, /* COMMAORRPAREXP */ + 0, /* COMMENT */ + 0, /* CTRAP */ + 0, /* CTRLC */ + 0, /* CTRLY */ + 0, /* DBCCERR */ + 0, /* DUPTOKEN */ + 0, /* DBJNLNOTMATCH */ + 0, /* DBFILERR */ + 0, /* DBNOTGDS */ + 0, /* DBOPNERR */ + 0, /* DBRDERR */ + 0, /* CCEDUMPNOW */ + 0, /* DEVPARINAP */ + 0, /* RECORDSTAT */ + 0, /* NOTGBL */ + 0, /* DEVPARPROT */ + 0, /* PREMATEOF */ + 0, /* GVINVALID */ + 0, /* DEVPARTOOBIG */ + 0, /* DEVPARUNK */ + 0, /* DEVPARVALREQ */ + 0, /* DEVPARMNEG */ + 0, /* DSEBLKRDFAIL */ + 0, /* DSEFAIL */ + 0, /* NOTALLREPLON */ + 0, /* BADLKIPARAM */ + 0, /* JNLREADBOF */ + 0, /* DVIKEYBAD */ + 0, /* ENQ */ + 0, /* EQUAL */ + 0, /* ERRORSUMMARY */ + 0, /* ERRWEXC */ + 0, /* ERRWIOEXC */ + 0, /* ERRWZBRK */ + 0, /* ERRWZTRAP */ + 0, /* NUMUNXEOR */ + 0, /* EXPR */ + 0, /* STRUNXEOR */ + 0, /* JNLEXTEND */ + 0, /* FCHARMAXARGS */ + 0, /* FCNSVNEXPECTED */ + 2, /* FNARGINC */ + 0, /* JNLACCESS */ + 44, /* TRANSNOSTART */ + 0, /* FNUMARG */ + 0, /* FOROFLOW */ + 0, /* YDIRTSZ */ + 0, /* JNLSUCCESS */ + 29, /* GBLNAME */ + 0, /* GBLOFLOW */ + 0, /* CORRUPT */ + 0, /* GTMCHECK */ + 0, /* GVDATAFAIL */ + 0, /* EORNOTFND */ + 0, /* GVGETFAIL */ + 0, /* GVIS */ + 0, /* GVKILLFAIL */ + 1, /* GVNAKED */ + 0, /* GVNEXTARG */ + 0, /* GVORDERFAIL */ + 0, /* GVPUTFAIL */ + 0, /* PATTABSYNTAX */ + 0, /* GVSUBOFLOW */ + 7, /* GVUNDEF */ + 0, /* TRANSNEST */ + 0, /* INDEXTRACHARS */ + 0, /* UNUSEDMSG260 */ + 0, /* INDRMAXLEN */ + 0, /* INSFFBCNT */ + 0, /* INTEGERRS */ + 0, /* INVCMD */ + 0, /* INVFCN */ + 0, /* INVOBJ */ + 8, /* INVSVN */ + 0, /* IOEOF */ + 0, /* IONOTOPEN */ + 0, /* MUPIPINFO */ + 0, /* IVTIME */ + 0, /* JOBFAIL */ + 13, /* JOBLABOFF */ + 0, /* JOBPARNOVAL */ + 0, /* JOBPARNUM */ + 0, /* JOBPARSTR */ + 0, /* JOBPARUNK */ + 0, /* JOBPARVALREQ */ + 0, /* JUSTFRACT */ + 0, /* KEY2BIG */ + 0, /* LABELEXPECTED */ + 13, /* LABELMISSING */ + 13, /* LABELUNKNOWN */ + 9, /* DIVZERO */ + 0, /* LKNAMEXPECTED */ + 0, /* JNLRDERR */ + 25, /* LOADRUNNING */ + 0, /* LPARENMISSING */ + 0, /* LSEXPECTED */ + 0, /* LVORDERARG */ + 0, /* MAXFORARGS */ + 0, /* TRANSMINUS */ + 0, /* MAXNRSUBSCRIPTS */ + 75, /* MAXSTRLEN */ + 0, /* JNLDBERR */ + 0, /* JNLFILOPN */ + 0, /* MBXRDONLY */ + 0, /* JNLINVALID */ + 0, /* MBXWRTONLY */ + 0, /* MEMORY */ + 70, /* MTBLKTOOBIG */ + 70, /* MTBLKTOOSM */ + 70, /* MTFIXRECSZ */ + 0, /* MTIS */ + 0, /* MTRDBADBLK */ + 62, /* MTRDONLY */ + 0, /* MTRDTHENWRT */ + 71, /* MTRECGTRBLK */ + 72, /* MTRECTOOBIG */ + 72, /* MTRECTOOSM */ + 0, /* JNLTMQUAL3 */ + 57, /* MULTLAB */ + 0, /* BLKCNT */ + 0, /* CCEDUMPOFF */ + 0, /* NOPLACE */ + 0, /* JNLCLOSE */ + 0, /* NOTPRINCIO */ + 0, /* NOTTOEOFONPUT */ + 0, /* NOZBRK */ + 0, /* NULSUBSC */ + 92, /* NUMOFLOW */ + 0, /* PARFILSPC */ + 0, /* PATCLASS */ + 10, /* PATCODE */ + 0, /* PATLIT */ + 0, /* PATMAXLEN */ + 0, /* LPARENREQD */ + 10, /* PATUPPERLIM */ + 0, /* PCONDEXPECTED */ + 0, /* PRCNAMLEN */ + 3, /* RANDARGNEG */ + 0, /* DBPRIVERR */ + 75, /* REC2BIG */ + 0, /* RHMISSING */ + 62, /* DEVICEREADONLY */ + 0, /* COLLDATAEXISTS */ + 88, /* ROUTINEUNKNOWN */ + 0, /* RPARENMISSING */ + 0, /* RTNNAME */ + 0, /* VIEWGVN */ + 0, /* RTSLOC */ + 0, /* RWARG */ + 0, /* RWFORMAT */ + 0, /* JNLWRTDEFER */ + 4, /* SELECTFALSE */ + 0, /* SPOREOL */ + 0, /* SRCLIN */ + 0, /* SRCLOC */ + 0, /* SRCLOCUNKNOWN */ + 0, /* STACKCRIT */ + 0, /* STACKOFLOW */ + 0, /* STACKUNDERFLO */ + 0, /* STRINGOFLOW */ + 0, /* SVNOSET */ + 0, /* VIEWFN */ + 0, /* TERMASTQUOTA */ + 5, /* TEXTARG */ + 0, /* TMPSTOREMAX */ + 0, /* VIEWCMD */ + 0, /* JNI */ + 0, /* TXTSRCFMT */ + 0, /* UIDMSG */ + 0, /* UIDSND */ + 6, /* UNDEF */ + 0, /* UNIMPLOP */ + 39, /* VAREXPECTED */ + 0, /* VARRECBLKSZ */ + 0, /* MAXARGCNT */ + 0, /* GTMSECSHRSEMGET */ + 0, /* VIEWARGCNT */ + 0, /* GTMSECSHRDMNSTARTED */ + 0, /* ZATTACHERR */ + 0, /* ZDATEFMT */ + 0, /* ZEDFILSPEC */ + 75, /* ZFILENMTOOLONG */ + 0, /* ZFILKEYBAD */ + 0, /* ZFILNMBAD */ + 0, /* ZGOTOLTZERO */ + 0, /* ZGOTOTOOBIG */ + 0, /* ZLINKFILE */ + 0, /* ZPARSETYPE */ + 0, /* ZPARSFLDBAD */ + 0, /* ZPIDBADARG */ + 0, /* ZPRIVARGBAD */ + 0, /* ZPRIVSYNTAXERR */ + 13, /* ZPRTLABNOTFND */ + 0, /* VIEWAMBIG */ + 0, /* VIEWNOTFOUND */ + 0, /* ZSETPRVARGBAD */ + 0, /* INVSPECREC */ + 0, /* ZSETPRVSYNTAX */ + 0, /* ZSRCHSTRMCT */ + 0, /* VERSION */ + 0, /* MUNOTALLSEC */ + 0, /* MUSECDEL */ + 0, /* MUSECNOTDEL */ + 0, /* RPARENREQD */ + 26, /* ZGBLDIRACC */ + 0, /* GVNAKEDEXTNM */ + 0, /* EXTGBLDEL */ + 0, /* DSEWCINITCON */ + 0, /* LASTFILCMPLD */ + 0, /* NOEXCNOZTRAP */ + 0, /* UNSDCLASS */ + 0, /* UNSDDTYPE */ + 0, /* ZCUNKTYPE */ + 0, /* ZCUNKMECH */ + 0, /* ZCUNKQUAL */ + 0, /* JNLDBTNNOMATCH */ + 0, /* ZCALLTABLE */ + 58, /* ZCARGMSMTCH */ + 58, /* ZCCONMSMTCH */ + 0, /* ZCOPT0 */ + 0, /* ZCSTATUS */ + 0, /* ZCUSRRTN */ + 0, /* ZCPOSOVR */ + 0, /* ZCINPUTREQ */ + 0, /* JNLTNOUTOFSEQ */ + 0, /* ACTRANGE */ + 0, /* ZCCONVERT */ + 0, /* ZCRTENOTF */ + 0, /* GVRUNDOWN */ + 0, /* LKRUNDOWN */ + 0, /* IORUNDOWN */ + 0, /* FILENOTFND */ + 0, /* MUFILRNDWNFL */ + 0, /* JNLTMQUAL1 */ + 0, /* FORCEDHALT */ + 0, /* LOADEOF */ + 0, /* WILLEXPIRE */ + 0, /* LOADEDBG */ + 0, /* LABELONLY */ + 0, /* MUREORGFAIL */ + 0, /* GVZPREVFAIL */ + 21, /* MULTFORMPARM */ + 16, /* QUITARGUSE */ + 0, /* NAMEEXPECTED */ + 11, /* FALLINTOFLST */ + 16, /* NOTEXTRINSIC */ + 0, /* GTMSECSHRREMSEMFAIL */ + 20, /* FMLLSTMISSING */ + 58, /* ACTLSTTOOLONG */ + 0, /* ACTOFFSET */ + 0, /* MAXACTARG */ + 0, /* GTMSECSHRREMSEM */ + 0, /* JNLTMQUAL2 */ + 0, /* GDINVALID */ + 0, /* ASSERT */ + 0, /* MUFILRNDWNSUC */ + 0, /* LOADEDSZ */ + 16, /* QUITARGLST */ + 17, /* QUITARGREQD */ + 0, /* CRITRESET */ + 0, /* UNKNOWNFOREX */ + 0, /* FSEXP */ + 0, /* WILDCARD */ + 0, /* DIRONLY */ + 0, /* FILEPARSE */ + 0, /* QUALEXP */ + 0, /* BADQUAL */ + 0, /* QUALVAL */ + 0, /* ZROSYNTAX */ + 0, /* COMPILEQUALS */ + 0, /* ZLNOOBJECT */ + 0, /* ZLMODULE */ + 0, /* DBBLEVMX */ + 0, /* DBBLEVMN */ + 0, /* DBBSIZMN */ + 0, /* DBBSIZMX */ + 0, /* DBRSIZMN */ + 0, /* DBRSIZMX */ + 0, /* DBCMPNZRO */ + 0, /* DBSTARSIZ */ + 0, /* DBSTARCMP */ + 0, /* DBCMPMX */ + 0, /* DBKEYMX */ + 0, /* DBKEYMN */ + 0, /* DBCMPBAD */ + 0, /* DBKEYORD */ + 0, /* DBPTRNOTPOS */ + 0, /* DBPTRMX */ + 0, /* DBPTRMAP */ + 0, /* IFBADPARM */ + 0, /* IFNOTINIT */ + 0, /* GTMSECSHRSOCKET */ + 0, /* LOADBGSZ */ + 0, /* LOADFMT */ + 0, /* LOADFILERR */ + 0, /* NOREGION */ + 0, /* PATLOAD */ + 0, /* EXTRACTFILERR */ + 0, /* FREEZE */ + 0, /* NOSELECT */ + 0, /* EXTRFAIL */ + 0, /* LDBINFMT */ + 0, /* NOPREVLINK */ + 0, /* CCEDUMPON */ + 0, /* CCEDMPQUALREQ */ + 0, /* CCEDBDUMP */ + 0, /* CCEDBNODUMP */ + 0, /* CCPMBX */ + 0, /* REQRUNDOWN */ + 0, /* CCPINTQUE */ + 0, /* CCPBADMSG */ + 0, /* CNOTONSYS */ + 0, /* CCPNAME */ + 0, /* CCPNOTFND */ + 0, /* OPRCCPSTOP */ + 0, /* SELECTSYNTAX */ + 0, /* LOADABORT */ + 0, /* FNOTONSYS */ + 0, /* AMBISYIPARAM */ + 0, /* PREVJNLNOEOF */ + 0, /* LKSECINIT */ + 0, /* MTDOSLAB */ + 0, /* MTDOSFOR */ + 0, /* MTINVLAB */ + 0, /* TXTSRCMAT */ + 0, /* CCENOGROUP */ + 0, /* BADDBVER */ + 0, /* LINKVERSION */ + 0, /* TOTALBLKMAX */ + 0, /* LOADCTRLY */ + 0, /* CLSTCONFLICT */ + 0, /* SRCNAM */ + 0, /* LCKGONE */ + 0, /* SUB2LONG */ + 0, /* EXTRACTCTRLY */ + 0, /* CCENOWORLD */ + 0, /* GVQUERYFAIL */ + 0, /* LCKSCANCELLED */ + 0, /* INVNETFILNM */ + 0, /* NETDBOPNERR */ + 0, /* BADSRVRNETMSG */ + 0, /* BADGTMNETMSG */ + 0, /* SERVERERR */ + 0, /* NETFAIL */ + 0, /* NETLCKFAIL */ + 0, /* TTINVFILTER */ + 0, /* MTANSILAB */ + 0, /* MTANSIFOR */ + 0, /* BADTRNPARAM */ + 0, /* DSEONLYBGMM */ + 0, /* DSEINVLCLUSFN */ + 18, /* RDFLTOOSHORT */ + 0, /* TIMRBADVAL */ + 0, /* CCENOSYSLCK */ + 0, /* CCPGRP */ + 0, /* UNSOLCNTERR */ + 0, /* BACKUPCTRL */ + 0, /* NOCCPPID */ + 0, /* CCPJNLOPNERR */ + 0, /* LCKSGONE */ + 0, /* ZLKIDBADARG */ + 0, /* DBFILOPERR */ + 0, /* CCERDERR */ + 0, /* CCEDBCL */ + 0, /* CCEDBNTCL */ + 0, /* CCEWRTERR */ + 0, /* CCEBADFN */ + 0, /* CCERDTIMOUT */ + 0, /* CCPSIGCONT */ + 0, /* CCEBGONLY */ + 0, /* CCENOCCP */ + 0, /* CCECCPPID */ + 0, /* CCECLSTPRCS */ + 0, /* ZSHOWBADFUNC */ + 0, /* NOTALLJNLEN */ + 0, /* ZSHOWGLOSMALL */ + 0, /* NOLBRSRC */ + 0, /* INVZSTEP */ + 0, /* ZSTEPARG */ + 0, /* INVSTRLEN */ + 0, /* RECCNT */ + 0, /* TEXT */ + 0, /* ZWRSPONE */ + 0, /* FILEDEL */ + 0, /* JNLBADLABEL */ + 0, /* JNLREADEOF */ + 0, /* JNLRECFMT */ + 0, /* BLKTOODEEP */ + 0, /* NESTFORMP */ + 0, /* BINHDR */ + 0, /* GOQPREC */ + 0, /* LDGOQFMT */ + 0, /* BEGINST */ + 0, /* INVMVXSZ */ + 0, /* JNLWRTNOWWRTR */ + 0, /* GTMSECSHRSHMCONCPROC */ + 0, /* JNLINVALLOC */ + 0, /* JNLINVEXT */ + 0, /* MUPCLIERR */ + 0, /* JNLTMQUAL4 */ + 0, /* GTMSECSHRREMSHM */ + 0, /* GTMSECSHRREMFILE */ + 0, /* MUNODBNAME */ + 0, /* FILECREATE */ + 0, /* FILENOTCREATE */ + 0, /* JNLPROCSTUCK */ + 0, /* INVGLOBALQUAL */ + 0, /* COLLARGLONG */ + 0, /* NOPINI */ + 0, /* DBNOCRE */ + 0, /* JNLSPACELOW */ + 0, /* DBCOMMITCLNUP */ + 0, /* BFRQUALREQ */ + 0, /* REQDVIEWPARM */ + 0, /* COLLFNMISSING */ + 0, /* JNLACTINCMPLT */ + 0, /* NCTCOLLDIFF */ + 0, /* DLRCUNXEOR */ + 0, /* DLRCTOOBIG */ + 0, /* WCERRNOTCHG */ + 0, /* WCWRNNOTCHG */ + 0, /* ZCWRONGDESC */ + 0, /* MUTNWARN */ + 0, /* GTMSECSHRUPDDBHDR */ + 0, /* LCKSTIMOUT */ + 0, /* CTLMNEMAXLEN */ + 0, /* CTLMNEXPECTED */ + 0, /* USRIOINIT */ + 0, /* CRITSEMFAIL */ + 0, /* TERMWRITE */ + 0, /* COLLTYPVERSION */ + 0, /* LVNULLSUBS */ + 0, /* GVREPLERR */ + 0, /* MTIOERR */ + 72, /* RMWIDTHPOS */ + 13, /* OFFSETINV */ + 0, /* JOBPARTOOLONG */ + 0, /* JOBARGMISSING */ + 0, /* RUNPARAMERR */ + 0, /* FNNAMENEG */ + 0, /* ORDER2 */ + 0, /* MUNOUPGRD */ + 0, /* REORGCTRLY */ + 0, /* TSTRTPARM */ + 0, /* TRIGNAMENF */ + 0, /* TRIGZBREAKREM */ + 44, /* TLVLZERO */ + 27, /* TRESTNOT */ + 41, /* TPLOCK */ + 42, /* TPQUIT */ + 0, /* TPFAIL */ + 0, /* TPRETRY */ + 0, /* TPTOODEEP */ + 0, /* ZDEFACTIVE */ + 0, /* ZDEFOFLOW */ + 0, /* MUPRESTERR */ + 0, /* MUBCKNODIR */ + 0, /* TRANS2BIG */ + 0, /* INVBITLEN */ + 0, /* INVBITSTR */ + 0, /* INVBITPOS */ + 0, /* PARNORMAL */ + 0, /* PARBUFSM */ + 72, /* RMWIDTHTOOBIG */ + 0, /* PATTABNOTFND */ + 0, /* OBJFILERR */ + 0, /* SRCFILERR */ + 95, /* NEGFRACPWR */ + 0, /* MTNOSKIP */ + 0, /* CETOOMANY */ + 0, /* CEUSRERROR */ + 0, /* CEBIGSKIP */ + 0, /* CETOOLONG */ + 0, /* CENOINDIR */ + 0, /* COLLATIONUNDEF */ + 0, /* RBWRNNOTCHG */ + 0, /* GTMSECSHRSRVF */ + 0, /* FREEZECTRL */ + 0, /* JNLFLUSH */ + 0, /* CCPSIGDMP */ + 0, /* NOPRINCIO */ + 0, /* INVPORTSPEC */ + 0, /* INVADDRSPEC */ + 78, /* SOCKPARMREQ */ + 0, /* IPADDRREQ */ + 80, /* SOCKWAIT */ + 81, /* SOCKACPT */ + 80, /* SOCKINIT */ + 81, /* OPENCONN */ + 0, /* DEVNOTIMP */ + 0, /* JNLEXTR */ + 0, /* DBREMOTE */ + 0, /* JNLREQUIRED */ + 0, /* TPMIXUP */ + 0, /* HTOFLOW */ + 72, /* RMNOBIGRECORD */ + 0, /* DBBMSIZE */ + 0, /* DBBMBARE */ + 0, /* DBBMINV */ + 0, /* DBBMMSTR */ + 0, /* DBROOTBURN */ + 0, /* REPLSTATEERR */ + 0, /* VMSMEMORY */ + 0, /* DBDIRTSUBSC */ + 0, /* TIMEROVFL */ + 0, /* GTMASSERT */ + 0, /* DBFHEADERR4 */ + 0, /* DBADDRANGE */ + 0, /* DBQUELINK */ + 0, /* DBCRERR */ + 0, /* MUSTANDALONE */ + 0, /* MUNOACTION */ + 0, /* RMBIGSHARE */ + 0, /* TPRESTART */ + 0, /* SOCKWRITE */ + 0, /* DBCNTRLERR */ + 0, /* NOTERMENV */ + 0, /* NOTERMENTRY */ + 0, /* NOTERMINFODB */ + 0, /* INVACCMETHOD */ + 0, /* JNLOPNERR */ + 0, /* JNLRECTYPE */ + 0, /* JNLTRANSGTR */ + 0, /* JNLTRANSLSS */ + 0, /* JNLWRERR */ + 0, /* FILEIDMATCH */ + 0, /* EXTSRCLIN */ + 0, /* EXTSRCLOC */ + 0, /* BIGNOACL */ + 0, /* ERRCALL */ + 0, /* ZCCTENV */ + 0, /* ZCCTOPN */ + 0, /* ZCCTNULLF */ + 0, /* ZCUNAVAIL */ + 0, /* ZCENTNAME */ + 0, /* ZCCOLON */ + 0, /* ZCRTNTYP */ + 0, /* ZCRCALLNAME */ + 0, /* ZCRPARMNAME */ + 0, /* ZCUNTYPE */ + 0, /* ZCMLTSTATUS */ + 0, /* ZCSTATUSRET */ + 0, /* ZCMAXPARAM */ + 0, /* ZCCSQRBR */ + 0, /* ZCPREALLNUMEX */ + 0, /* ZCPREALLVALPAR */ + 0, /* VERMISMATCH */ + 0, /* JNLCNTRL */ + 0, /* TRIGNAMBAD */ + 0, /* BUFRDTIMEOUT */ + 0, /* INVALIDRIP */ + 0, /* BLKSIZ512 */ + 0, /* MUTEXERR */ + 0, /* JNLVSIZE */ + 0, /* MUTEXLCKALERT */ + 0, /* MUTEXFRCDTERM */ + 0, /* GTMSECSHR */ + 0, /* GTMSECSHRSRVFID */ + 0, /* GTMSECSHRSRVFIL */ + 0, /* FREEBLKSLOW */ + 0, /* PROTNOTSUP */ + 0, /* DELIMSIZNA */ + 0, /* INVCTLMNE */ + 0, /* SOCKLISTEN */ + 0, /* LQLENGTHNA */ + 0, /* ADDRTOOLONG */ + 0, /* GTMSECSHRGETSEMFAIL */ + 0, /* CPBEYALLOC */ + 0, /* DBRDONLY */ + 0, /* DUPTN */ + 0, /* TRESTLOC */ + 0, /* REPLPOOLINST */ + 0, /* ZCVECTORINDX */ + 0, /* REPLNOTON */ + 0, /* JNLMOVED */ + 0, /* EXTRFMT */ + 0, /* CALLERID */ + 0, /* KRNLKILL */ + 0, /* MEMORYRECURSIVE */ + 0, /* FREEZEID */ + 0, /* BLKWRITERR */ + 0, /* STOPTIMEOUT */ + 0, /* TRIGMODINTP */ + 0, /* BCKUPBUFLUSH */ + 0, /* NOFORKCORE */ + 0, /* JNLREAD */ + 0, /* JNLMINALIGN */ + 0, /* UNUSEDMSG781 */ + 0, /* JNLPOOLSETUP */ + 0, /* JNLSTATEOFF */ + 0, /* RECVPOOLSETUP */ + 0, /* REPLCOMM */ + 0, /* NOREPLCTDREG */ + 0, /* REPLINFO */ + 0, /* REPLWARN */ + 0, /* REPLERR */ + 0, /* JNLNMBKNOTPRCD */ + 0, /* REPLFILIOERR */ + 0, /* REPLBRKNTRANS */ + 0, /* TTWIDTHTOOBIG */ + 0, /* REPLLOGOPN */ + 0, /* REPLFILTER */ + 0, /* GBLMODFAIL */ + 0, /* TTLENGTHTOOBIG */ + 0, /* TPTIMEOUT */ + 0, /* DEFEREVENT */ + 0, /* JNLFILNOTCHG */ + 0, /* EVENTLOGERR */ + 0, /* UPDATEFILEOPEN */ + 0, /* JNLBADRECFMT */ + 0, /* NULLCOLLDIFF */ + 0, /* MUKILLIP */ + 0, /* JNLRDONLY */ + 0, /* ANCOMPTINC */ + 0, /* ABNCOMPTINC */ + 0, /* UNUSEDMSG809 */ + 0, /* SOCKNOTFND */ + 0, /* CURRSOCKOFR */ + 79, /* SOCKETEXIST */ + 76, /* LISTENPASSBND */ + 0, /* DBCLNUPINFO */ + 0, /* MUNODWNGRD */ + 0, /* REPLTRANS2BIG */ + 0, /* RDFLTOOLONG */ + 0, /* MUNOFINISH */ + 0, /* DBFILEXT */ + 0, /* JNLFSYNCERR */ + 0, /* FSYNCTIMOUT */ + 0, /* ZCPREALLVALINV */ + 0, /* NEWJNLFILECREAT */ + 0, /* DSKSPACEFLOW */ + 0, /* GVINCRFAIL */ + 0, /* ISOLATIONSTSCHN */ + 0, /* REPLGBL2LONG */ + 0, /* TRACEON */ + 0, /* TOOMANYCLIENTS */ + 0, /* NOEXCLUDE */ + 0, /* GVINCRISOLATION */ + 0, /* EXCLUDEREORG */ + 0, /* REORGINC */ + 0, /* ASC2EBCDICCONV */ + 0, /* GTMSECSHRSTART */ + 0, /* DBVERPERFWARN1 */ + 0, /* FILEIDGBLSEC */ + 0, /* GBLSECNOTGDS */ + 0, /* BADGBLSECVER */ + 0, /* RECSIZENOTEVEN */ + 0, /* BUFFLUFAILED */ + 0, /* MUQUALINCOMP */ + 0, /* DISTPATHMAX */ + 0, /* UNUSEDMSG844 */ + 0, /* IMAGENAME */ + 0, /* GTMSECSHRPERM */ + 0, /* GTMDISTUNDEF */ + 0, /* SYSCALL */ + 0, /* MAXGTMPATH */ + 0, /* TROLLBK2DEEP */ + 0, /* INVROLLBKLVL */ + 0, /* OLDBINEXTRACT */ + 0, /* ACOMPTBINC */ + 0, /* NOTREPLICATED */ + 0, /* DBPREMATEOF */ + 0, /* KILLBYSIG */ + 0, /* KILLBYSIGUINFO */ + 0, /* KILLBYSIGSINFO1 */ + 0, /* KILLBYSIGSINFO2 */ + 0, /* SIGILLOPC */ + 0, /* SIGILLOPN */ + 0, /* SIGILLADR */ + 0, /* SIGILLTRP */ + 0, /* SIGPRVOPC */ + 0, /* SIGPRVREG */ + 0, /* SIGCOPROC */ + 0, /* SIGBADSTK */ + 0, /* SIGADRALN */ + 0, /* SIGADRERR */ + 0, /* SIGOBJERR */ + 0, /* SIGINTDIV */ + 0, /* SIGINTOVF */ + 0, /* SIGFLTDIV */ + 0, /* SIGFLTOVF */ + 0, /* SIGFLTUND */ + 0, /* SIGFLTRES */ + 0, /* SIGFLTINV */ + 0, /* SIGMAPERR */ + 0, /* SIGACCERR */ + 0, /* TRNLOGFAIL */ + 0, /* INVDBGLVL */ + 0, /* DBMAXNRSUBS */ + 0, /* GTMSECSHRSCKSEL */ + 0, /* GTMSECSHRTMOUT */ + 0, /* GTMSECSHRRECVF */ + 0, /* GTMSECSHRSENDF */ + 0, /* SIZENOTVALID8 */ + 0, /* GTMSECSHROPCMP */ + 0, /* GTMSECSHRSUIDF */ + 0, /* GTMSECSHRSGIDF */ + 0, /* GTMSECSHRSSIDF */ + 0, /* GTMSECSHRFORKF */ + 0, /* DBFSYNCERR */ + 0, /* SECONDAHEAD */ + 0, /* SCNDDBNOUPD */ + 0, /* MUINFOUINT4 */ + 0, /* NLMISMATCHCALC */ + 0, /* UNUSEDMSG898 */ + 0, /* UNUSEDMSG899 */ + 0, /* DBBADNSUB */ + 0, /* DBBADKYNM */ + 0, /* DBBADPNTR */ + 0, /* DBBNPNTR */ + 0, /* DBINCLVL */ + 0, /* DBBFSTAT */ + 0, /* DBBDBALLOC */ + 0, /* DBMRKFREE */ + 0, /* DBMRKBUSY */ + 0, /* DBBSIZZRO */ + 0, /* DBSZGT64K */ + 0, /* DBNOTMLTP */ + 0, /* DBTNTOOLG */ + 0, /* DBBPLMLT512 */ + 0, /* DBBPLMGT2K */ + 0, /* MUINFOUINT8 */ + 0, /* DBBPLNOT512 */ + 0, /* MUINFOSTR */ + 0, /* DBUNDACCMT */ + 0, /* DBTNNEQ */ + 0, /* MUPGRDSUCC */ + 0, /* DBDSRDFMTCHNG */ + 0, /* DBFGTBC */ + 0, /* DBFSTBC */ + 0, /* DBFSTHEAD */ + 0, /* DBCREINCOMP */ + 0, /* DBFLCORRP */ + 0, /* DBHEADINV */ + 0, /* DBINCRVER */ + 0, /* DBINVGBL */ + 0, /* DBKEYGTIND */ + 0, /* DBGTDBMAX */ + 0, /* DBKGTALLW */ + 0, /* DBLTSIBL */ + 0, /* DBLRCINVSZ */ + 0, /* MUREUPDWNGRDEND */ + 0, /* DBLOCMBINC */ + 0, /* DBLVLINC */ + 0, /* DBMBSIZMX */ + 0, /* DBMBSIZMN */ + 0, /* DBMBTNSIZMX */ + 0, /* DBMBMINCFRE */ + 0, /* DBMBPINCFL */ + 0, /* DBMBPFLDLBM */ + 0, /* DBMBPFLINT */ + 0, /* DBMBPFLDIS */ + 0, /* DBMBPFRDLBM */ + 0, /* DBMBPFRINT */ + 0, /* DBMAXKEYEXC */ + 0, /* DBMXRSEXCMIN */ + 0, /* UNUSEDMSG950 */ + 0, /* DBREADBM */ + 0, /* DBCOMPTOOLRG */ + 0, /* DBVERPERFWARN2 */ + 0, /* DBRBNTOOLRG */ + 0, /* DBRBNLBMN */ + 0, /* DBRBNNEG */ + 0, /* DBRLEVTOOHI */ + 0, /* DBRLEVLTONE */ + 0, /* DBSVBNMIN */ + 0, /* DBTTLBLK0 */ + 0, /* DBNOTDB */ + 0, /* DBTOTBLK */ + 0, /* DBTN */ + 0, /* DBNOREGION */ + 0, /* DBTNRESETINC */ + 0, /* DBTNLTCTN */ + 0, /* DBTNRESET */ + 0, /* MUTEXRSRCCLNUP */ + 0, /* SEMWT2LONG */ + 0, /* REPLINSTOPEN */ + 0, /* REPLINSTCLOSE */ + 0, /* UNUSEDMSG972 */ + 0, /* DBCRERR8 */ + 0, /* NUMPROCESSORS */ + 0, /* DBADDRANGE8 */ + 0, /* RNDWNSEMFAIL */ + 0, /* GTMSECSHRSHUTDN */ + 0, /* NOSPACECRE */ + 0, /* LOWSPACECRE */ + 0, /* WAITDSKSPACE */ + 0, /* OUTOFSPACE */ + 0, /* JNLPVTINFO */ + 0, /* NOSPACEEXT */ + 0, /* WCBLOCKED */ + 0, /* REPLJNLCLOSED */ + 0, /* RENAMEFAIL */ + 0, /* FILERENAME */ + 0, /* JNLBUFINFO */ + 0, /* UNUSEDMSG989 */ + 0, /* UNUSEDMSG990 */ + 0, /* TPNOTACID */ + 0, /* JNLSETDATA2LONG */ + 0, /* JNLNEWREC */ + 0, /* REPLFTOKSEM */ + 0, /* UNUSEDMSG995 */ + 0, /* EXTRIOERR */ + 0, /* EXTRCLOSEERR */ + 0, /* UNUSEDMSG998 */ + 0, /* REPLEXITERR */ + 0, /* MUDESTROYSUC */ + 0, /* DBRNDWN */ + 0, /* MUDESTROYFAIL */ + 0, /* NOTALLDBOPN */ + 0, /* MUSELFBKUP */ + 0, /* DBDANGER */ + 0, /* TRUNCATEFAIL */ + 0, /* TCGETATTR */ + 0, /* TCSETATTR */ + 0, /* IOWRITERR */ + 0, /* REPLINSTWRITE */ + 0, /* DBBADFREEBLKCTR */ + 0, /* REQ2RESUME */ + 0, /* TIMERHANDLER */ + 0, /* FREEMEMORY */ + 0, /* MUREPLSECDEL */ + 0, /* MUREPLSECNOTDEL */ + 0, /* MUJPOOLRNDWNSUC */ + 0, /* MURPOOLRNDWNSUC */ + 0, /* MUJPOOLRNDWNFL */ + 0, /* MURPOOLRNDWNFL */ + 0, /* MUREPLPOOL */ + 0, /* REPLACCSEM */ + 0, /* JNLFLUSHNOPROG */ + 0, /* REPLINSTCREATE */ + 0, /* SUSPENDING */ + 0, /* SOCKBFNOTEMPTY */ + 0, /* ILLESOCKBFSIZE */ + 0, /* NOSOCKETINDEV */ + 0, /* SETSOCKOPTERR */ + 0, /* GETSOCKOPTERR */ + 0, /* NOSUCHPROC */ + 0, /* DSENOFINISH */ + 0, /* LKENOFINISH */ + 0, /* NOCHLEFT */ + 0, /* MULOGNAMEDEF */ + 0, /* BUFOWNERSTUCK */ + 0, /* ACTIVATEFAIL */ + 0, /* DBRNDWNWRN */ + 0, /* DLLNOOPEN */ + 0, /* DLLNORTN */ + 0, /* DLLNOCLOSE */ + 0, /* FILTERNOTALIVE */ + 0, /* FILTERCOMM */ + 0, /* FILTERBADCONV */ + 0, /* PRIMARYISROOT */ + 0, /* GVQUERYGETFAIL */ + 0, /* DBCREC2BIGINBLK */ + 19, /* MERGEDESC */ + 0, /* MERGEINCOMPL */ + 0, /* DBNAMEMISMATCH */ + 0, /* DBIDMISMATCH */ + 0, /* DEVOPENFAIL */ + 0, /* IPCNOTDEL */ + 0, /* XCVOIDRET */ + 0, /* MURAIMGFAIL */ + 0, /* REPLINSTUNDEF */ + 0, /* REPLINSTACC */ + 0, /* NOJNLPOOL */ + 0, /* NORECVPOOL */ + 0, /* FTOKERR */ + 0, /* REPLREQRUNDOWN */ + 0, /* BLKCNTEDITFAIL */ + 0, /* SEMREMOVED */ + 0, /* REPLINSTFMT */ + 0, /* SEMKEYINUSE */ + 0, /* XTRNTRANSERR */ + 0, /* XTRNTRANSDLL */ + 0, /* XTRNRETVAL */ + 0, /* XTRNRETSTR */ + 101, /* INVECODEVAL */ + 0, /* SETECODE */ + 0, /* INVSTACODE */ + 0, /* REPEATERROR */ + 90, /* NOCANONICNAME */ + 0, /* NOSUBSCRIPT */ + 0, /* SYSTEMVALUE */ + 0, /* SIZENOTVALID4 */ + 0, /* STRNOTVALID */ + 0, /* UNUSEDMSG1079 */ + 0, /* ERRWETRAP */ + 0, /* TRACINGON */ + 0, /* CITABENV */ + 0, /* CITABOPN */ + 0, /* CIENTNAME */ + 0, /* CIRTNTYP */ + 0, /* CIRCALLNAME */ + 0, /* CIRPARMNAME */ + 0, /* CIDIRECTIVE */ + 0, /* CIPARTYPE */ + 0, /* CIUNTYPE */ + 0, /* CINOENTRY */ + 0, /* JNLINVSWITCHLMT */ + 0, /* SETZDIR */ + 40, /* JOBACTREF */ + 0, /* ECLOSTMID */ + 0, /* ZFF2MANY */ + 0, /* JNLFSYNCLSTCK */ + 0, /* DELIMWIDTH */ + 0, /* DBBMLCORRUPT */ + 0, /* DLCKAVOIDANCE */ + 0, /* WRITERSTUCK */ + 0, /* PATNOTFOUND */ + 0, /* INVZDIRFORM */ + 0, /* ZDIROUTOFSYNC */ + 0, /* GBLNOEXIST */ + 0, /* MAXBTLEVEL */ + 0, /* UNUSEDMSG1107 */ + 0, /* JNLALIGNSZCHG */ + 0, /* UNUSEDMSG1109 */ + 0, /* GVFAILCORE */ + 0, /* DBCDBNOCERTIFY */ + 0, /* DBFRZRESETSUC */ + 0, /* JNLFILEXTERR */ + 0, /* JOBEXAMDONE */ + 0, /* JOBEXAMFAIL */ + 0, /* JOBINTRRQST */ + 0, /* ERRWZINTR */ + 0, /* CLIERR */ + 0, /* REPLNOBEFORE */ + 0, /* REPLJNLCNFLCT */ + 0, /* JNLDISABLE */ + 0, /* FILEEXISTS */ + 0, /* JNLSTATE */ + 0, /* REPLSTATE */ + 0, /* JNLCREATE */ + 0, /* JNLNOCREATE */ + 0, /* JNLFNF */ + 0, /* PREVJNLLINKCUT */ + 0, /* PREVJNLLINKSET */ + 0, /* FILENAMETOOLONG */ + 0, /* REQRECOV */ + 0, /* JNLTRANS2BIG */ + 0, /* JNLSWITCHTOOSM */ + 0, /* JNLSWITCHSZCHG */ + 0, /* NOTRNDMACC */ + 0, /* TMPFILENOCRE */ + 0, /* SHRMEMEXHAUSTED */ + 0, /* JNLSENDOPER */ + 0, /* DDPSUBSNUL */ + 0, /* DDPNOCONNECT */ + 0, /* DDPCONGEST */ + 0, /* DDPSHUTDOWN */ + 0, /* DDPTOOMANYPROCS */ + 0, /* DDPBADRESPONSE */ + 0, /* DDPINVCKT */ + 0, /* DDPVOLSETCONFIG */ + 0, /* DDPCONFGOOD */ + 0, /* DDPCONFIGNORE */ + 0, /* DDPCONFINCOMPL */ + 0, /* DDPCONFBADVOL */ + 0, /* DDPCONFBADUCI */ + 0, /* DDPCONFBADGLD */ + 0, /* DDPRECSIZNOTNUM */ + 0, /* DDPOUTMSG2BIG */ + 0, /* DDPNOSERVER */ + 0, /* MUTEXRELEASED */ + 0, /* JNLCRESTATUS */ + 0, /* ZBREAKFAIL */ + 0, /* DLLVERSION */ + 0, /* INVZROENT */ + 0, /* DDPLOGERR */ + 0, /* GETSOCKNAMERR */ + 0, /* INVGTMEXIT */ + 0, /* CIMAXPARAM */ + 0, /* CITPNESTED */ + 0, /* CIMAXLEVELS */ + 0, /* JOBINTRRETHROW */ + 0, /* STARFILE */ + 0, /* NOSTARFILE */ + 0, /* MUJNLSTAT */ + 0, /* JNLTPNEST */ + 0, /* REPLOFFJNLON */ + 0, /* FILEDELFAIL */ + 0, /* INVQUALTIME */ + 0, /* NOTPOSITIVE */ + 0, /* INVREDIRQUAL */ + 0, /* INVERRORLIM */ + 0, /* INVIDQUAL */ + 0, /* INVTRNSQUAL */ + 0, /* JNLNOBIJBACK */ + 0, /* SETREG2RESYNC */ + 0, /* JNLALIGNTOOSM */ + 0, /* JNLFILEOPNERR */ + 0, /* JNLFILECLOSERR */ + 0, /* REPLSTATEOFF */ + 0, /* MUJNLPREVGEN */ + 0, /* MUPJNLINTERRUPT */ + 0, /* ROLLBKINTERRUPT */ + 0, /* RLBKJNSEQ */ + 0, /* REPLRECFMT */ + 0, /* PRIMARYNOTROOT */ + 0, /* DBFRZRESETFL */ + 0, /* JNLCYCLE */ + 0, /* JNLPREVRECOV */ + 0, /* RESOLVESEQNO */ + 0, /* BOVTNGTEOVTN */ + 0, /* BOVTMGTEOVTM */ + 0, /* BEGSEQGTENDSEQ */ + 0, /* DBADDRALIGN */ + 0, /* DBWCVERIFYSTART */ + 0, /* DBWCVERIFYEND */ + 0, /* MUPIPSIG */ + 0, /* HTSHRINKFAIL */ + 0, /* STPEXPFAIL */ + 0, /* DBBTUWRNG */ + 0, /* DBBTUFIXED */ + 0, /* DBMAXREC2BIG */ + 0, /* DBCSCNNOTCMPLT */ + 0, /* DBCBADFILE */ + 0, /* DBCNOEXTND */ + 0, /* DBCINTEGERR */ + 0, /* DBMINRESBYTES */ + 0, /* DBCNOTSAMEDB */ + 0, /* DBCDBCERTIFIED */ + 0, /* DBCMODBLK2BIG */ + 0, /* DBCREC2BIG */ + 0, /* DBCCMDFAIL */ + 0, /* DBCKILLIP */ + 0, /* DBCNOFINISH */ + 0, /* DYNUPGRDFAIL */ + 0, /* MMNODYNDWNGRD */ + 0, /* MMNODYNUPGRD */ + 0, /* MUDWNGRDNRDY */ + 0, /* MUDWNGRDTN */ + 0, /* MUDWNGRDNOTPOS */ + 0, /* MUUPGRDNRDY */ + 0, /* TNWARN */ + 0, /* TNTOOLARGE */ + 0, /* SHMPLRECOV */ + 0, /* MUNOSTRMBKUP */ + 0, /* EPOCHTNHI */ + 0, /* CHNGTPRSLVTM */ + 0, /* JNLUNXPCTERR */ + 0, /* OMISERVHANG */ + 0, /* RSVDBYTE2HIGH */ + 0, /* BKUPTMPFILOPEN */ + 0, /* BKUPTMPFILWRITE */ + 0, /* VMSMEMORY2 */ + 0, /* LOADBGSZ2 */ + 0, /* LOADEDSZ2 */ + 0, /* REPLINSTMISMTCH */ + 0, /* REPLINSTREAD */ + 0, /* REPLINSTDBMATCH */ + 0, /* REPLINSTNMSAME */ + 0, /* REPLINSTNMUNDEF */ + 0, /* REPLINSTNMLEN */ + 0, /* REPLINSTNOHIST */ + 0, /* REPLINSTSECLEN */ + 0, /* REPLINSTSECMTCH */ + 0, /* REPLINSTSECNONE */ + 0, /* REPLINSTSECUNDF */ + 0, /* REPLINSTSEQORD */ + 0, /* REPLINSTSTNDALN */ + 0, /* REPLREQROLLBACK */ + 0, /* REQROLLBACK */ + 0, /* UNUSEDMSG1256 */ + 0, /* SRCSRVEXISTS */ + 0, /* SRCSRVNOTEXIST */ + 0, /* SRCSRVTOOMANY */ + 0, /* JNLPOOLBADSLOT */ + 0, /* NOENDIANCVT */ + 0, /* ENDIANCVT */ + 0, /* DBENDIAN */ + 0, /* BADCHSET */ + 0, /* BADCASECODE */ + 0, /* BADCHAR */ + 0, /* DLRCILLEGAL */ + 0, /* NONUTF8LOCALE */ + 0, /* INVDLRCVAL */ + 0, /* DBMISALIGN */ + 0, /* LOADINVCHSET */ + 0, /* DLLCHSETM */ + 0, /* DLLCHSETUTF8 */ + 0, /* BOMMISMATCH */ + 0, /* WIDTHTOOSMALL */ + 80, /* SOCKMAX */ + 0, /* PADCHARINVALID */ + 0, /* ZCNOPREALLOUTPAR */ + 0, /* SVNEXPECTED */ + 0, /* SVNONEW */ + 0, /* ZINTDIRECT */ + 0, /* ZINTRECURSEIO */ + 0, /* MRTMAXEXCEEDED */ + 0, /* JNLCLOSED */ + 0, /* RLBKNOBIMG */ + 0, /* RLBKJNLNOBIMG */ + 0, /* RLBKLOSTTNONLY */ + 0, /* KILLBYSIGSINFO3 */ + 0, /* GTMSECSHRTMPPATH */ + 0, /* GTMERREXIT */ + 0, /* INVMEMRESRV */ + 0, /* OPCOMMISSED */ + 0, /* COMMITWAITSTUCK */ + 0, /* COMMITWAITPID */ + 0, /* UPDREPLSTATEOFF */ + 0, /* LITNONGRAPH */ + 0, /* DBFHEADERR8 */ + 0, /* MMBEFOREJNL */ + 0, /* MMNOBFORRPL */ + 0, /* KILLABANDONED */ + 0, /* BACKUPKILLIP */ + 0, /* LOGTOOLONG */ + 0, /* NOALIASLIST */ + 0, /* ALIASEXPECTED */ + 0, /* VIEWLVN */ + 0, /* DZWRNOPAREN */ + 0, /* DZWRNOALIAS */ + 0, /* FREEZEERR */ + 0, /* CLOSEFAIL */ + 0, /* CRYPTINIT */ + 0, /* CRYPTOPFAILED */ + 0, /* CRYPTDLNOOPEN */ + 0, /* CRYPTNOV4 */ + 0, /* CRYPTNOMM */ + 0, /* CRYPTJNLWRONGHASH */ + 0, /* CRYPTKEYFETCHFAILED */ + 0, /* CRYPTKEYFETCHFAILEDNF */ + 0, /* CRYPTHASHGENFAILED */ + 0, /* CRYPTNOPSWDINTP */ + 0, /* BADTAG */ + 0, /* ICUVERLT36 */ + 0, /* ICUSYMNOTFOUND */ + 0, /* STUCKACT */ + 0, /* CALLINAFTERXIT */ + 0, /* LOCKSPACEFULL */ + 0, /* IOERROR */ + 0, /* MAXSSREACHED */ + 0, /* SNAPSHOTNOV4 */ + 0, /* SSV4NOALLOW */ + 0, /* SSTMPDIRSTAT */ + 0, /* SSTMPCREATE */ + 0, /* JNLFILEDUP */ + 0, /* SSPREMATEOF */ + 0, /* SSFILOPERR */ + 0, /* REGSSFAIL */ + 0, /* SSSHMCLNUPFAIL */ + 0, /* SSFILCLNUPFAIL */ + 0, /* SETINTRIGONLY */ + 0, /* MAXTRIGNEST */ + 0, /* TRIGCOMPFAIL */ + 0, /* NOZTRAPINTRIG */ + 0, /* ZTWORMHOLE2BIG */ + 0, /* JNLENDIANLITTLE */ + 0, /* JNLENDIANBIG */ + 0, /* TRIGINVCHSET */ + 0, /* TRIGREPLSTATE */ + 0, /* GVDATAGETFAIL */ + 0, /* TRIG2NOTRIG */ + 0, /* ZGOTOINVLVL */ + 0, /* TRIGTCOMMIT */ + 0, /* TRIGTLVLCHNG */ + 0, /* TRIGNAMEUNIQ */ + 0, /* ZTRIGINVACT */ + 0, /* INDRCOMPFAIL */ + 0, /* QUITALSINV */ + 0, /* PROCTERM */ + 0, /* SRCLNNTDSP */ + 0, /* ARROWNTDSP */ + 0, /* TRIGDEFBAD */ + 0, /* TRIGSUBSCRANGE */ + 0, /* TRIGDATAIGNORE */ + 0, /* TRIGIS */ + 0, /* TCOMMITDISALLOW */ + 0, /* SSATTACHSHM */ + 0, /* TRIGDEFNOSYNC */ + 0, /* TRESTMAX */ + 0, /* UNUSEDMSG1367 */ + 0, /* GBLEXPECTED */ + 0, /* GVZTRIGFAIL */ + 0, /* MUUSERLBK */ + 0, /* SETINSETTRIGONLY */ + 0, /* DZTRIGINTRIG */ + 0, /* SECNODZTRIGINTP */ + 0, /* BOOLSIDEFFECT */ + 0, /* DBBADUPGRDSTATE */ + 0, /* WRITEWAITPID */ + 0, /* ZGOCALLOUTIN */ + 0, /* REPLNOXENDIAN */ + 0, /* REPLXENDIANFAIL */ + 0, /* ZGOTOINVLVL2 */ + 0, /* GTMSECSHRCHDIRF */ + 0, /* JNLORDBFLU */ + 0, /* ZCCLNUPRTNMISNG */ + 0, /* ZCINVALIDKEYWORD */ + 0, /* REPLNOMULTILINETRG */ + 0, /* DBSHMNAMEDIFF */ + 0, /* SHMREMOVED */ + 0, /* DEVICEWRITEONLY */ + 0, /* ICUERROR */ + 0, /* ZDATEBADDATE */ + 0, /* ZDATEBADTIME */ + 0, /* COREINPROGRESS */ + 0, /* MAXSEMGETRETRY */ + 0, /* JNLNOREPL */ + 0, /* JNLRECINCMPL */ + 0, /* JNLALLOCGROW */ + 0, /* INVTRCGRP */ + 0, /* MUINFOUINT6 */ + 0, /* NOLOCKMATCH */ + 0, /* BADREGION */ + 0, /* LOCKSPACEUSE */ + 0, /* JIUNHNDINT */ + 0, /* GTMASSERT2 */ + 0, /* ZTRIGNOTRW */ + 0, /* TRIGMODREGNOTRW */ + 0, /* INSNOTJOINED */ + 0, /* INSROLECHANGE */ + 0, /* INSUNKNOWN */ + 0, /* NORESYNCSUPPLONLY */ + 0, /* NORESYNCUPDATERONLY */ + 0, /* NOSUPPLSUPPL */ + 0, /* REPL2OLD */ + 0, /* EXTRFILEXISTS */ + 0, /* MUUSERECOV */ + 0, /* SECNOTSUPPLEMENTARY */ + 0, /* SUPRCVRNEEDSSUPSRC */ + 0, /* UNUSEDMSG1417 */ + 0, /* UNUSEDMSG1418 */ + 0, /* UPDSYNC2MTINS */ + 0, /* UPDSYNCINSTFILE */ + 0, /* REUSEINSTNAME */ + 0, /* RCVRMANYSTRMS */ + 0, /* RSYNCSTRMVAL */ + 0, /* RLBKSTRMSEQ */ + 0, /* RESOLVESEQSTRM */ + 0, /* REPLINSTDBSTRM */ + 0, /* RESUMESTRMNUM */ + 0, /* ORLBKSTART */ + 0, /* ORLBKTERMNTD */ + 0, /* ORLBKCMPLT */ + 0, /* ORLBKNOSTP */ + 0, /* ORLBKFRZPROG */ + 0, /* ORLBKFRZOVER */ + 0, /* ORLBKNOV4BLK */ + 0, /* DBROLLEDBACK */ + 0, /* DSEWCREINIT */ + 0, /* MURNDWNOVRD */ + 0, /* REPLONLNRLBK */ + 0, /* SRVLCKWT2LNG */ + 0, /* IGNBMPMRKFREE */ + 0, /* PERMGENFAIL */ + 0, /* PERMGENDIAG */ + 0, /* MUTRUNC1ATIME */ + 0, /* MUTRUNCBACKINPROG */ + 0, /* MUTRUNCERROR */ + 0, /* MUTRUNCFAIL */ + 0, /* MUTRUNCNOSPACE */ + 0, /* MUTRUNCNOTBG */ + 0, /* MUTRUNCNOV4 */ + 0, /* MUTRUNCPERCENT */ + 0, /* MUTRUNCSSINPROG */ + 0, /* MUTRUNCSUCCESS */ + 0, /* RSYNCSTRMSUPPLONLY */ + 0, /* STRMNUMIS */ + 0, /* STRMNUMMISMTCH1 */ + 0, /* STRMNUMMISMTCH2 */ + 0, /* STRMSEQMISMTCH */ + 0, /* LOCKSPACEINFO */ + 0, /* JRTNULLFAIL */ + 0, /* LOCKSUB2LONG */ + 0, /* RESRCWAIT */ + 0, /* RESRCINTRLCKBYPAS */ + 0, /* DBFHEADERRANY */ + 0, /* REPLINSTFROZEN */ + 0, /* REPLINSTFREEZECOMMENT */ + 0, /* REPLINSTUNFROZEN */ + 0, /* DSKNOSPCAVAIL */ + 0, /* DSKNOSPCBLOCKED */ + 0, /* DSKSPCAVAILABLE */ + 0, /* ENOSPCQIODEFER */ + 0, /* CUSTOMFILOPERR */ + 0, /* CUSTERRNOTFND */ + 0, /* CUSTERRSYNTAX */ + 0, /* ORLBKINPROG */ + 0, /* DBSPANGLOINCMP */ + 0, /* DBSPANCHUNKORD */ + 0, /* DBDATAMX */ + 0, /* DBIOERR */ + 0, /* INITORRESUME */ + 0, /* GTMSECSHRNOARG0 */ + 0, /* GTMSECSHRISNOT */ + 0, /* GTMSECSHRBADDIR */ + 0, /* JNLBUFFREGUPD */ + 0, /* JNLBUFFDBUPD */ + 0, /* LOCKINCR2HIGH */ + 0, /* LOCKIS */ + 0, /* LDSPANGLOINCMP */ + 0, /* MUFILRNDWNFL2 */ + 0, /* MUINSTFROZEN */ + 0, /* MUINSTUNFROZEN */ + 0, /* GTMEISDIR */ + 0, /* SPCLZMSG */ + 0, /* MUNOTALLINTEG */ + 0, /* BKUPRUNNING */ + 0, /* MUSIZEINVARG */ + 0, /* MUSIZEFAIL */ + 0, /* SIDEEFFECTEVAL */ + 0, /* CRYPTINIT2 */ + 0, /* CRYPTDLNOOPEN2 */ + 0, /* CRYPTBADCONFIG */ + 0, /* DBCOLLREQ */ + 0, /* SETEXTRENV */ + 0, /* NOTALLDBRNDWN */ + 0, /* TPRESTNESTERR */ + 0, /* JNLFILRDOPN */ + 0, /* SEQNUMSEARCHTIMEOUT */ + 0, /* FTOKKEY */ + 0, /* SEMID */ + 0, /* JNLQIOSALVAGE */ + 0, /* FAKENOSPCLEARED */ + 0, /* MMFILETOOLARGE */ + 0, /* BADZPEEKARG */ + 0, /* BADZPEEKRANGE */ + 0, /* BADZPEEKFMT */ + 0, /* DBMBMINCFREFIXED */ + 0, /* NULLENTRYREF */ + 0, /* ZPEEKNORPLINFO */ + 0, /* MMREGNOACCESS */ + 0, /* MALLOCMAXUNIX */ + 0, /* MALLOCMAXVMS */ + 0, /* HOSTCONFLICT */ + 0, /* GETADDRINFO */ + 0, /* GETNAMEINFO */ + 0, /* SOCKBIND */ + 0, /* INSTFRZDEFER */ + 0, /* REGOPENRETRY */ + 0, /* REGOPENFAIL */ + }; diff --git a/sr_i386/opp_indsavglvn.s b/sr_i386/opp_indsavglvn.s new file mode 100644 index 0000000..7458c8f --- /dev/null +++ b/sr_i386/opp_indsavglvn.s @@ -0,0 +1,39 @@ +################################################################# +# # +# Copyright 2012 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +# PAGE ,132 + .title opp_indsavglvn.s + +# .386 +# .MODEL FLAT, C + +.include "linkage.si" + .INCLUDE "g_msf.si" + + .sbttl opp_indsavglvn +# PAGE + + .DATA +.extern frame_pointer # /* :DWORD */ + + .text +.extern op_indsavglvn + +# PUBLIC opp_indsavglvn +ENTRY opp_indsavglvn # /* PROC */ + putframe + addl $4,%esp # /* burn return pc */ + call op_indsavglvn + addl $12,%esp # /* burn three passed-in args */ + getframe + ret +# opp_indsavglvn ENDP + +# END diff --git a/sr_i386/opp_indsavlvn.s b/sr_i386/opp_indsavlvn.s new file mode 100644 index 0000000..14cf4c6 --- /dev/null +++ b/sr_i386/opp_indsavlvn.s @@ -0,0 +1,39 @@ +################################################################# +# # +# Copyright 2012 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +# PAGE ,132 + .title opp_indsavlvn.s + +# .386 +# .MODEL FLAT, C + +.include "linkage.si" + .INCLUDE "g_msf.si" + + .sbttl opp_indsavlvn +# PAGE + + .DATA +.extern frame_pointer # /* :DWORD */ + + .text +.extern op_indsavlvn + +# PUBLIC opp_indsavlvn +ENTRY opp_indsavlvn # /* PROC */ + putframe + addl $4,%esp # /* burn return pc */ + call op_indsavlvn + addl $8,%esp # /* burn two passed-in args */ + getframe + ret +# opp_indsavlvn ENDP + +# END diff --git a/sr_linux/hugetlbfs_overrides.c b/sr_linux/hugetlbfs_overrides.c new file mode 100644 index 0000000..04023d1 --- /dev/null +++ b/sr_linux/hugetlbfs_overrides.c @@ -0,0 +1,112 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +/* + * This file contains functions related to Linux HugeTLB support. Its functions rely + * on libhugetlbfs which allocates memory in Huge Pages. + * This library is Linux only and works only on (currently) x86, AMD64 and PowerPC + * Supported Huge Page functionality requires the following prerequisites: + * Linux kernel support of Huge Pages + * x86_64 or i386 architecture + * libhugetlbfs.so being installed + * Availability of Huge Pages through setting value to /proc/sys/vm/nr_hugepages or hugepages= kernel parameter or + * /proc/sys/vm/nr_overcommit_hugepages + * In order to use shmget with Huge Pages, either the process gid should be in /proc/sys/vm/hugetlb_shm_group or the + * process should have CAP_IPC_LOCK + * In order to remap .text/.data/.bss sections, a file system of type hugetlbfs should be mounted + * Appropriate environmental variables should be set (refer to libhugetlbfs documentation) to enable/disable Huge Pages + */ +#include "mdef.h" + +#include +#include "gtm_string.h" + +#include "get_page_size.h" +#include "hugetlbfs_overrides.h" +#undef shmget +#include "send_msg.h" +#include "wbox_test_init.h" +#ifdef DEBUG +# define WBTEST_HUGETLB_DLSYM_ERROR "WBTEST_HUGETLB_DLSYM error" +#endif + +GBLDEF long gtm_os_hugepage_size = -1; /* Default Huge Page size of OS. If huge pages are not supported or the + * value doesn't fit into a *long* it will be equal to the OS page size + */ +OS_PAGE_SIZE_DECLARE + +/* ptr to libhugetlbfs's overriden shmget. It uses Linux Huge Pages to back the shared segment if possible */ +STATICDEF int (*p_shmget) (key_t, size_t, int) = NULL; +/* returns default huge page size of the OS or -1 in case huge pages are not supported or their sizes doesn't + * fit into a long. Refer to libhugetlbfs for further info. */ +STATICDEF long (*p_gethugepagesize) (void) = NULL; +STATICDEF boolean_t hugetlb_is_attempted = FALSE; +/* all shmget declarations have already been MACROed to gtm_shmget in mdefsp.h so we need to declare the real + * one here */ +extern int shmget (key_t __key, size_t __size, int __shmflg); + +error_def(ERR_DLLNORTN); +error_def(ERR_TEXT); + +/* A MACRO in mdefsp.h (LINUX_ONLY) replaces all shmget with this function */ +int gtm_shmget (key_t key, size_t size, int shmflg) +{ + assert(hugetlb_is_attempted); /* libhugetlbfs_init must be called prior to this function */ + return p_shmget(key, size, shmflg); +} + +/* + * This function initializes libhugetlbfs if it's available. Upon dlopen() the initializing function of libhugetlbfs + * is called. If libhugetlbfs is available gtm_shmget uses its shmget. Otherwise it falls back to the native shmget. + * For malloc to use hugepages, it calls __morecore() hook if it needs more memory. In case libhugetlbfs is available + * and other Huge Page conditions are met, the libhugetlbfs assigns __morecore() to a version which backs them with + * hugepages during its initialization + * Consult libhugetlbfs documentation for a list of HugeTLB configuration environment variables. + */ +void libhugetlbfs_init(void) +{ + char *error = NULL; + void *handle; + + assert(!hugetlb_is_attempted); + handle = dlopen("libhugetlbfs.so", RTLD_NOW); + GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLOPEN, handle, NULL); + if (NULL != handle) + { + /* C99 standard leaves casting from "void *" to a function pointer undefined. The assignment used + * below is the POSIX.1-2003 (Technical Corrigendum 1) workaround; */ + *(void **) (&p_shmget) = dlsym(handle, "shmget"); + GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLSYM, p_shmget, NULL); + if (NULL != p_shmget) /* NULL value for shmget() necessarily means it was not found */ + { + *(void **) (&p_gethugepagesize) = dlsym(handle, "gethugepagesize"); + if (NULL != p_gethugepagesize) + gtm_os_hugepage_size = p_gethugepagesize(); + else + error = dlerror(); + } else + error = dlerror(); + GTM_WHITE_BOX_TEST(WBTEST_HUGETLB_DLSYM, error, WBTEST_HUGETLB_DLSYM_ERROR); + if (error) + { + p_shmget = NULL; + send_msg(VARLSTCNT(8) ERR_DLLNORTN, 2, LEN_AND_LIT("shmget from libhugetlbfs.so"), ERR_TEXT, 2, + LEN_AND_STR(error)); + } + } + if (NULL == p_shmget) + p_shmget = &shmget; /* Fall back to using the native shmget */ + get_page_size(); + if (-1 == gtm_os_hugepage_size) + gtm_os_hugepage_size = OS_PAGE_SIZE; + assert(0 == (gtm_os_hugepage_size % OS_PAGE_SIZE)); /* huge pages sizes are multiples of page sizes */ + hugetlb_is_attempted = TRUE; +} diff --git a/sr_linux/hugetlbfs_overrides.h b/sr_linux/hugetlbfs_overrides.h new file mode 100644 index 0000000..f212773 --- /dev/null +++ b/sr_linux/hugetlbfs_overrides.h @@ -0,0 +1,25 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef HUGETLBFS_OVERRIDES_H_ +#define HUGETLBFS_OVERRIDES_H_ + +#if defined(__linux__) && ( defined(__i386__) || defined(__x86_64__) ) +# define HUGETLB_SUPPORTED 1 +#endif + +GBLREF long gtm_os_hugepage_size; +#define OS_HUGEPAGE_SIZE gtm_os_hugepage_size + +extern int gtm_shmget(key_t __key, size_t __size, int __shmflg); +void libhugetlbfs_init(void); + +#endif /* HUGETLBFS_OVERRIDES_H_ */ diff --git a/sr_linux/platform.cmake b/sr_linux/platform.cmake new file mode 100644 index 0000000..4e8605f --- /dev/null +++ b/sr_linux/platform.cmake @@ -0,0 +1,59 @@ +################################################################# +# # +# Copyright 2013 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +if("${CMAKE_SIZEOF_VOID_P}" EQUAL 4) + set(arch "x86") + set(bits 32) + set(FIND_LIBRARY_USE_LIB64_PATHS FALSE) +else() + set(arch "x86_64") + set(bits 64) +endif() + +# Platform directories +list(APPEND gt_src_list sr_linux) +if(${bits} EQUAL 32) + list(APPEND gt_src_list sr_i386 sr_x86_regs sr_unix_nsb) +else() + list(APPEND gt_src_list sr_x86_64 sr_x86_regs) + set(gen_xfer_desc 1) +endif() + +# Assembler +set(CMAKE_INCLUDE_FLAG_ASM "-Wa,-I") # gcc -I does not make it to "as" + +# Compiler +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -ansi -fsigned-char -fPIC -Wmissing-prototypes -fno-omit-frame-pointer") + +set(CMAKE_C_FLAGS_RELEASE + "${CMAKE_C_FLAGS_RELEASE} -fno-defer-pop -fno-strict-aliasing -ffloat-store") + +add_definitions( + #-DNOLIBGTMSHR #gt_cc_option_DBTABLD=-DNOLIBGTMSHR + -D_GNU_SOURCE + -D_FILE_OFFSET_BITS=64 + -D_XOPEN_SOURCE=600 + -D_LARGEFILE64_SOURCE + ) + +# Linker +set(gtm_link "-Wl,-u,gtm_filename_to_id -Wl,-u,gtm_zstatus -Wl,--version-script,\"${GTM_BINARY_DIR}/gtmexe_symbols.export\"") +set(gtm_dep "${GTM_BINARY_DIR}/gtmexe_symbols.export") + +set(libgtmshr_link "-Wl,-u,gtm_ci -Wl,-u,gtm_filename_to_id -Wl,--version-script,\"${GTM_BINARY_DIR}/gtmshr_symbols.export\"") +set(libgtmshr_dep "${GTM_BINARY_DIR}/gtmexe_symbols.export") + +if(${bits} EQUAL 32) + set(libmumpslibs "-lncurses -lm -ldl -lc -lpthread -lrt") +else() + set(libmumpslibs "-lelf -lncurses -lm -ldl -lc -lpthread -lrt") +endif() diff --git a/sr_port/anticipatory_freeze.h b/sr_port/anticipatory_freeze.h new file mode 100644 index 0000000..ef51450 --- /dev/null +++ b/sr_port/anticipatory_freeze.h @@ -0,0 +1,344 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#ifndef _ANTICIPATORY_FREEZE_H +#define _ANTICIPATORY_FREEZE_H + +#ifdef UNIX + +#include "gtm_time.h" /* needed for GET_CUR_TIME */ +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsblk.h" +#include "gdsfhead.h" +#include "repl_msg.h" /* needed for gtmsource.h */ +#include "gtmsource.h" /* needed for jnlpool_addrs typedef */ +#include "sleep_cnt.h" /* needed for SLEEP_INSTFREEZEWAIT macro */ +#include "wait_for_disk_space.h" /* needed by DB_LSEEKWRITE macro for prototype */ +#include "gtmimagename.h" /* needed for IS_GTM_IMAGE */ + +boolean_t is_anticipatory_freeze_needed(sgmnt_addrs *csa, int msg_id); +void set_anticipatory_freeze(sgmnt_addrs *csa, int msg_id); +boolean_t init_anticipatory_freeze_errors(void); + +/* Define function pointers to certain functions to avoid executables like gtmsecshr from unnecessarily + * linking with these functions (which causes the database/replication stuff to be pulled in). + */ +typedef boolean_t (*is_anticipatory_freeze_needed_t)(sgmnt_addrs *csa, int msgid); +typedef void (*set_anticipatory_freeze_t)(sgmnt_addrs *csa, int msg_id); + +GBLREF is_anticipatory_freeze_needed_t is_anticipatory_freeze_needed_fnptr; +GBLREF set_anticipatory_freeze_t set_anticipatory_freeze_fnptr; +GBLREF boolean_t pool_init; +GBLREF boolean_t mupip_jnl_recover; +#ifdef DEBUG +GBLREF uint4 lseekwrite_target; +#endif + +error_def(ERR_MUINSTFROZEN); +error_def(ERR_MUINSTUNFROZEN); + +error_def(ERR_MUNOACTION); +error_def(ERR_REPLINSTFREEZECOMMENT); +error_def(ERR_REPLINSTFROZEN); +error_def(ERR_REPLINSTUNFROZEN); +error_def(ERR_TEXT); + + +#define ENABLE_FREEZE_ON_ERROR \ +{ \ + if (ANTICIPATORY_FREEZE_AVAILABLE) \ + { /* Set anticipatory freeze function pointers to be used later (in send_msg and rts_error) */ \ + is_anticipatory_freeze_needed_fnptr = &is_anticipatory_freeze_needed; \ + set_anticipatory_freeze_fnptr = &set_anticipatory_freeze; \ + } \ +} + +#define CHECK_IF_FREEZE_ON_ERROR_NEEDED(CSA, MSG_ID, FREEZE_NEEDED, FREEZE_MSG_ID) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + DCL_THREADGBL_ACCESS; \ + \ + SETUP_THREADGBL_ACCESS; \ + if (!FREEZE_NEEDED && ANTICIPATORY_FREEZE_AVAILABLE && (NULL != is_anticipatory_freeze_needed_fnptr)) \ + { /* NOT gtmsecshr */ \ + if (IS_REPL_INST_UNFROZEN && (*is_anticipatory_freeze_needed_fnptr)((sgmnt_addrs *)CSA, MSG_ID)) \ + { \ + FREEZE_NEEDED = TRUE; \ + FREEZE_MSG_ID = MSG_ID; \ + } \ + } \ +} + +#define FREEZE_INSTANCE_IF_NEEDED(CSA, FREEZE_NEEDED, FREEZE_MSG_ID) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + \ + if (FREEZE_NEEDED) \ + { \ + assert(NULL != set_anticipatory_freeze_fnptr); \ + (*set_anticipatory_freeze_fnptr)((sgmnt_addrs *)CSA, FREEZE_MSG_ID); \ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTFROZEN, 1, \ + jnlpool.repl_inst_filehdr->inst_info.this_instname); \ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTFREEZECOMMENT, 1, jnlpool.jnlpool_ctl->freeze_comment); \ + } \ +} + +#define CLEAR_ANTICIPATORY_FREEZE(FREEZE_CLEARED) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + \ + if (IS_REPL_INST_FROZEN) \ + { \ + jnlpool.jnlpool_ctl->freeze = 0; \ + FREEZE_CLEARED = TRUE; \ + } \ +} + +#define REPORT_INSTANCE_UNFROZEN(FREEZE_CLEARED) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + \ + if (FREEZE_CLEARED) \ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(3) ERR_REPLINSTUNFROZEN, 1, \ + jnlpool.repl_inst_filehdr->inst_info.this_instname); \ +} + +#define AFREEZE_MASK 0x01 +#define ANTICIPATORY_FREEZE_AVAILABLE (0 != (TREF(gtm_custom_errors)).len) +#define INSTANCE_FREEZE_HONORED(CSA) (DBG_ASSERT(NULL != CSA) \ + ((NULL != jnlpool.jnlpool_ctl) \ + && ((REPL_ALLOWED(((sgmnt_addrs *)CSA)->hdr)) \ + || mupip_jnl_recover /* recover or rollback */ \ + || ((sgmnt_addrs *)CSA)->nl->onln_rlbk_pid ))) +#define ANTICIPATORY_FREEZE_ENABLED(CSA) (INSTANCE_FREEZE_HONORED(CSA) \ + && ANTICIPATORY_FREEZE_AVAILABLE \ + && (((sgmnt_addrs *)CSA)->hdr->freeze_on_fail)) +#define IS_REPL_INST_FROZEN ((NULL != jnlpool.jnlpool_ctl) && jnlpool.jnlpool_ctl->freeze) +#define IS_REPL_INST_UNFROZEN ((NULL != jnlpool.jnlpool_ctl) && !jnlpool.jnlpool_ctl->freeze) + +#define INST_FROZEN_COMMENT "PID %d encountered %s; Instance frozen" + +#define MSGID_TO_ERRMSG(MSG_ID, ERRMSG) \ +{ \ + const err_ctl *ctl; \ + \ + ctl = err_check(MSG_ID); \ + assert(NULL != ctl); \ + GET_MSG_INFO(MSG_ID, ctl, ERRMSG); \ +} + +#define GENERATE_INST_FROZEN_COMMENT(BUF, BUF_LEN, MSG_ID) \ +{ \ + GBLREF uint4 process_id; \ + const err_msg *msginfo; \ + \ + MSGID_TO_ERRMSG(MSG_ID, msginfo); \ + SNPRINTF(BUF, BUF_LEN, INST_FROZEN_COMMENT, process_id, msginfo->tag); \ +} + +/* This is a version of the macro which waits for the instance freeze to be lifted off assuming the process has + * already attached to the journal pool. We need to wait for the freeze only if the input database cares about + * anticipatory freeze. Examples of those databases that dont care are non-replicated databases, databases with + * "freeze_on_fail" field set to FALSE in the file header etc. Hence the use of ANTICIPATORY_FREEZE_ENABLED below. + * Note: Do not use "hiber_start" as that uses timers and if we are already in a timer handler now, nested timers + * wont work. Since SHORT_SLEEP allows a max of 1000, we use 500 (half a second) for now. + */ +#define WAIT_FOR_REPL_INST_UNFREEZE(CSA) \ +{ \ + gd_region *reg; \ + char *time_ptr, time_str[CTIME_BEFORE_NL + 2]; /* for GET_CUR_TIME macro */ \ + now_t now; \ + DCL_THREADGBL_ACCESS; \ + \ + SETUP_THREADGBL_ACCESS; \ + assert(NULL != CSA); \ + if (INSTANCE_FREEZE_HONORED(CSA)) \ + { \ + reg = ((sgmnt_addrs *)CSA)->region; \ + if (!IS_GTM_IMAGE) \ + { \ + GET_CUR_TIME; \ + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_MUINSTFROZEN, 5, CTIME_BEFORE_NL, time_ptr, \ + jnlpool.repl_inst_filehdr->inst_info.this_instname, DB_LEN_STR(reg)); \ + } \ + WAIT_FOR_REPL_INST_UNFREEZE_NOCSA; \ + if (!IS_GTM_IMAGE) \ + { \ + GET_CUR_TIME; \ + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(7) ERR_MUINSTUNFROZEN, 5, CTIME_BEFORE_NL, time_ptr, \ + jnlpool.repl_inst_filehdr->inst_info.this_instname, DB_LEN_STR(reg)); \ + } \ + } \ +} +/* This is a safer version of the WAIT_FOR_REPL_INST_UNFREEZE macro, which waits for the instance freeze + * to be lifted off but is not sure if the process has access to the journal pool yet. + * If it does not, then it assumes the instance is not frozen. + */ +#define WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + \ + assert(NULL != CSA); \ + if (IS_REPL_INST_FROZEN) \ + WAIT_FOR_REPL_INST_UNFREEZE(CSA); \ +} + +/* Below are similar macros like the above but with no CSA to specifically check for */ +#define WAIT_FOR_REPL_INST_UNFREEZE_NOCSA \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + GBLREF volatile int4 exit_state; \ + GBLREF int4 exi_condition; \ + GBLREF int4 forced_exit_err; \ + \ + assert(NULL != jnlpool.jnlpool_ctl); \ + /* If this region is not replicated, do not care for instance freezes */ \ + while (jnlpool.jnlpool_ctl->freeze) \ + { \ + if (exit_state != 0) \ + { \ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); \ + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); \ + exit(-exi_condition); \ + } \ + SHORT_SLEEP(SLEEP_INSTFREEZEWAIT); \ + DEBUG_ONLY(CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD); \ + } \ +} +#define WAIT_FOR_REPL_INST_UNFREEZE_NOCSA_SAFE \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + \ + if (IS_REPL_INST_FROZEN) \ + WAIT_FOR_REPL_INST_UNFREEZE_NOCSA; \ +} + +/* GTM_DB_FSYNC/GTM_JNL_FSYNC are similar to GTM_FSYNC except that we dont do the fsync + * (but instead hang) if we detect the instance is frozen. We proceed with the fsync once the freeze clears. + * CSA is a parameter indicating which database it is that we want to fsync. + * GTM_REPL_INST_FSYNC is different in that we currently dont care about instance freeze for replication + * instance file writes. + */ +#define GTM_DB_FSYNC(CSA, FD, RC) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + node_local_ptr_t cnl; \ + \ + assert((NULL != CSA) || (NULL == jnlpool.jnlpool_ctl)); \ + if (NULL != CSA) \ + { \ + WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA); \ + cnl = (CSA)->nl; \ + if (NULL != cnl) \ + INCR_GVSTATS_COUNTER((CSA), cnl, n_db_fsync, 1); \ + } \ + GTM_FSYNC(FD, RC); \ +} + +#define GTM_JNL_FSYNC(CSA, FD, RC) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + node_local_ptr_t cnl; \ + \ + assert((NULL != CSA) || (NULL == jnlpool.jnlpool_ctl)); \ + if (NULL != CSA) \ + { \ + WAIT_FOR_REPL_INST_UNFREEZE_SAFE(CSA); \ + cnl = (CSA)->nl; \ + if (NULL != cnl) \ + INCR_GVSTATS_COUNTER((CSA), cnl, n_jnl_fsync, 1); \ + } \ + GTM_FSYNC(FD, RC); \ +} + +#define GTM_REPL_INST_FSYNC(FD, RC) GTM_FSYNC(FD, RC) + +#define LSEEKWRITE_IS_TO_NONE 0 +#define LSEEKWRITE_IS_TO_DB 1 +#define LSEEKWRITE_IS_TO_JNL 2 + +#ifdef DEBUG +#define FAKE_ENOSPC(CSA, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET, LCL_STATUS) \ +{ \ + GBLREF jnlpool_addrs jnlpool; \ + if (NULL != CSA) \ + { \ + if (WBTEST_ENABLED(WBTEST_RECOVER_ENOSPC)) \ + { /* This test case is only used by mupip */ \ + gtm_wbox_input_test_case_count++; \ + if ((0 != gtm_white_box_test_case_count) \ + && (gtm_white_box_test_case_count <= gtm_wbox_input_test_case_count)) \ + { \ + LCL_STATUS = ENOSPC; \ + if (gtm_white_box_test_case_count == gtm_wbox_input_test_case_count) \ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_TEXT, 2, \ + LEN_AND_LIT("Turning on fake ENOSPC for exit status test")); \ + } \ + } else if (!IS_DSE_IMAGE /*DSE does not freeze so let it work as normal */ \ + && ((NULL != jnlpool.jnlpool_ctl) && (NULL != ((sgmnt_addrs *)CSA)->nl)) \ + && ((sgmnt_addrs *)CSA)->nl->FAKE_WHICH_ENOSPC) \ + { \ + LCL_STATUS = ENOSPC; \ + lseekwrite_target = LSEEKWRITE_TARGET; \ + } \ + } \ +} + +void clear_fake_enospc_if_master_dead(void); + +#define CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD clear_fake_enospc_if_master_dead() + +#else +#define FAKE_ENOSPC(CSA, FAKE_ENOSPC, LSEEKWRITE_TARGET, LCL_STATUS) {} +#endif + + +#define DB_LSEEKWRITE(csa, db_fn, fd, new_eof, buff, size, status) \ + DO_LSEEKWRITE(csa, db_fn, fd, new_eof, buff, size, status, fake_db_enospc, LSEEKWRITE_IS_TO_DB) + +#define JNL_LSEEKWRITE(csa, jnl_fn, fd, new_eof, buff, size, status) \ + DO_LSEEKWRITE(csa, jnl_fn, fd, new_eof, buff, size, status, fake_jnl_enospc, LSEEKWRITE_IS_TO_JNL) + +#define DO_LSEEKWRITE(csa, fnptr, fd, new_eof, buff, size, status, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET) \ +{ \ + int lcl_status; \ + \ + if (NULL != csa) \ + WAIT_FOR_REPL_INST_UNFREEZE_SAFE(csa); \ + LSEEKWRITE(fd, new_eof, buff, size, lcl_status); \ + FAKE_ENOSPC(csa, FAKE_WHICH_ENOSPC, LSEEKWRITE_TARGET, lcl_status); \ + if (ENOSPC == lcl_status) \ + { \ + wait_for_disk_space(csa, (char *)fnptr, fd, (off_t)new_eof, (char *)buff, (size_t)size, &lcl_status); \ + assert((NULL == csa) || (NULL == ((sgmnt_addrs *)csa)->nl) || !((sgmnt_addrs *)csa)->nl->FAKE_WHICH_ENOSPC \ + || (ENOSPC != lcl_status)); \ + } \ + status = lcl_status; \ +} + +/* Currently, writes to replication instance files do NOT trigger instance freeze behavior. + * Neither does a pre-existing instance freeze affect replication instance file writes. + * Hence this is defined as simple LSEEKWRITE. + */ +#define REPL_INST_LSEEKWRITE LSEEKWRITE + +#define REPL_INST_AVAILABLE (repl_inst_get_name((char *)replpool_id.instfilename, &full_len, SIZEOF(replpool_id.instfilename), \ + return_on_error)) + +#else /* #ifdef UNIX */ +# define ANTICIPATORY_FREEZE_AVAILABLE FALSE +# define ANTICIPATORY_FREEZE_ENABLED(CSA) FALSE +# define REPL_INST_AVAILABLE FALSE +# define WAIT_FOR_REPL_INST_UNFREEZE +# define WAIT_FOR_REPL_INST_UNFREEZE_SAFE +#endif /* #ifdef UNIX */ + +#endif /* #ifndef _ANTICIPATORY_FREEZE_H */ diff --git a/sr_port/create_temporaries.c b/sr_port/create_temporaries.c new file mode 100644 index 0000000..5c56e2b --- /dev/null +++ b/sr_port/create_temporaries.c @@ -0,0 +1,125 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" +#include "gtm_ctype.h" + +#include "compiler.h" +#include "mdq.h" +#include "opcode.h" +#include "indir_enum.h" +#include "nametabtyp.h" +#include "toktyp.h" +#include "funsvn.h" +#include "mmemory.h" +#include "advancewindow.h" +#include "namelook.h" +#include "cmd.h" +#include "svnames.h" +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "alias.h" +#include "glvn_pool.h" +#ifdef UNICODE_SUPPORTED +#include "gtm_utf8.h" +#endif + +/* This function adds triples to the execution chain to store the values of subscripts (in glvns in compound SETs) + * in temporaries (using OC_STOTEMP opcode). This function is only invoked when + * a) The SET is a compound SET (i.e. there are multiple targets specified on the left side of the SET command). + * b) Subscripts are specified in glvns which are targets of the SET. + * e.g. set a=0,(a,array(a))=1 + * The expected result of the above command as per the M-standard is that array(0) (not array(1)) gets set to 1. + * That is, the value of the subscript "a" should be evaluated at the start of the compound SET before any sets happen + * and should be used in any subscripts that refer to the name "a". + * In the above example, since it is a compound SET and "a" is used in a subscript, we need to store the value of "a" + * before the start of the compound SET (i.e.a=0) in a temporary and use that as the subscript for "array". + * If in the above example the compound set was instead specified as set a=1,array(a)=1, the value of 1 gets substituted + * when used in "array(a)". + * This is where the compound set acts differently from a sequence of multiple sets. This is per the M-standard. + * In the above example, the subscript used was also a target within the compound SET. It is possible that the + * subscript is not also an individual target within the same compound SET. Even in that case, this function + * will be called to store the subscript in temporaries (as we dont know at compile time if a particular + * subscript is also used as a target within a compound SET). + */ +void create_temporaries(triple *sub, opctype put_oc) +{ + oprtype *sb1; + triple *s0, *s1; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + assert(TREF(temp_subs)); + assert(NULL != sub); + sb1 = &sub->operand[1]; + if ((OC_GVNAME == put_oc) || (OC_PUTINDX == put_oc) || (OC_SRCHINDX == put_oc)) + { + sub = sb1->oprval.tref; /* global name */ + assert(OC_PARAMETER == sub->opcode); + sb1 = &sub->operand[1]; + } else if (OC_GVEXTNAM == put_oc) + { + sub = sb1->oprval.tref; /* first env */ + assert(OC_PARAMETER == sub->opcode); + sb1 = &sub->operand[0]; + assert(TRIP_REF == sb1->oprclass); + s0 = sb1->oprval.tref; + if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode)) + { + s1 = maketriple(OC_STOTEMP); + s1->operand[0] = *sb1; + *sb1 = put_tref(s1); + s0 = s0->exorder.fl; + dqins(s0->exorder.bl, exorder, s1); + } + sb1 = &sub->operand[1]; + sub = sb1->oprval.tref; /* second env */ + assert(OC_PARAMETER == sub->opcode); + sb1 = &sub->operand[0]; + assert(TRIP_REF == sb1->oprclass); + s0 = sb1->oprval.tref; + if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode)) + { + s1 = maketriple(OC_STOTEMP); + s1->operand[0] = *sb1; + *sb1 = put_tref(s1); + s0 = s0->exorder.fl; + dqins(s0->exorder.bl, exorder, s1); + } + sb1 = &sub->operand[1]; + sub = sb1->oprval.tref; /* global name */ + assert(OC_PARAMETER == sub->opcode); + sb1 = &sub->operand[1]; + } + while (sb1->oprclass) + { + assert(TRIP_REF == sb1->oprclass); + sub = sb1->oprval.tref; + assert(OC_PARAMETER == sub->opcode); + sb1 = &sub->operand[0]; + assert(TRIP_REF == sb1->oprclass); + s0 = sb1->oprval.tref; + if ((OC_GETINDX == s0->opcode) || (OC_VAR == s0->opcode)) + { + s1 = maketriple(OC_STOTEMP); + s1->operand[0] = *sb1; + *sb1 = put_tref(s1); + s0 = s0->exorder.fl; + dqins(s0->exorder.bl, exorder, s1); + } + sb1 = &sub->operand[1]; + } +} diff --git a/sr_port/dsewrap.mpt b/sr_port/dsewrap.mpt new file mode 100644 index 0000000..42dc7fe --- /dev/null +++ b/sr_port/dsewrap.mpt @@ -0,0 +1,249 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; Copyright 2012, 2013 Fidelity Information Services, Inc. ; +; ; +; This source code contains the intellectual property ; +; of its copyright holder(s), and is made available ; +; under a license. If you do not know the terms of ; +; the license, please stop and do not read further. ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%DSEWRAP +%dsewrap + ; Wrappers for DSE to avoid inadvertently making database changes + set $ETRAP="do errtrap^%DSEWRAP" + set $ecode=",U255," ; must call an entryref + quit:$quit 255 quit ; in case error trap does not end the call + +DUMP(r,o,w,d) ; upper case wrapper for dump + new tmp + set tmp=$$dump(r,.o,w,d) + quit:$quit tmp quit + +dump(reglist,output,what,detail) ; dump information + ; reglist - comma separated list of regions, "*" (default) for all regions + ; output - required variable passed by reference where output is returned + ; what - optional information to dump - "fileheader" (default) is only option for now + ; detail - optional default is basic information, "all" is full fileheader dump + ; install an error handler if non exists + if 0=$length($ETRAP) new $ETRAP set $ETRAP="do errtrap^%DSEWRAP" + new cmd,dse,debug,error,gtmdist,i,io,isVMS,line,mod,nopipe,region,ver + ; save previous $IO to restore once the routine has completed + set io=$io + if $data(%DSEWRAP("debug")) do + . set debug=$increment(%DSEWRAP("debug")) + . set debug(debug,"input","reglist")=$get(reglist) + . set debug(debug,"input","what")=$get(what) + . set debug(debug,"input","detail")=$get(detail) + ; + ; Determine if we can use PIPES or not AND where to find DSE + set ver=$tr($piece($zversion," ",2),"V-.",""),ver=$select(ver<1000:ver*10,1:$extract(ver,1,5)) + set isVMS=$zversion["VMS" + set nopipe=((ver<53003)&($get(%DSEWRAP("forcenopipe"),0)))!isVMS,mod=$select(isVMS:"/",1:"-") + set gtmdist=$select(isVMS:"gtm$dist",1:"gtm_dist") + ; + ; Applicable regions list + set reglist=$$reglist($$FUNC^%UCASE($get(reglist,"*")),isVMS) + ; What operation? for now, should be just "dump -fileheader [-all]" + if (0=$length($get(what)))!("fileheader"=$$FUNC^%LCASE($get(what))) set what=mod_"fileheader" + else set $ecode=",U254," quit:$quit 254 quit + if 0=$length($get(detail)) set detail="" + else if "all"=$$FUNC^%LCASE(detail) set detail=mod_"all" + else if $length(detail," ")>1 do + . set detail=$$^%MPIECE(detail," "," ") + . for i=1:1:$length(detail," ") if $piece(detail," ",i)'?1(1"/",1"-").A set $piece(detail," ",i)=mod_$piece(detail," ",i) + set cmd="dump "_what_" "_detail + ; Use alternate GT.M version - only supported with pipes + if nopipe&$data(%DSEWRAP("alternate")) set $ecode=",U252," quit:$quit 252 quit + ; DSE command to use + set dse=$get(%DSEWRAP("alternate"),$ztrnlnm(gtmdist)_"/dse") + if $data(debug) merge debug(debug,"outputreg")=reglist + if reglist="" set $ecode=",U251," quit:$quit 251 quit + ; Drive DSE + if 0=nopipe set error=$$dsepipecmd(.output,reglist,dse,cmd) + else set error=$$dsefilecmd(.output,reglist,cmd,isVMS) + use io + if $data(%DSEWRAP("debug")) merge %DSEWRAP("debug")=debug + quit:$quit error quit + + ; drive DSE through a PIPE device +dsepipecmd(output,regionlist,dse,cmd) + new error,curreg + open "dseproc":(shell="/bin/sh":command=dse)::"pipe" + use "dseproc" + for curreg=2:1:$length(regionlist,",") do + . set region=$piece(regionlist,",",curreg) + . if ($length(region)=0)&($data(debug)) set debug(debug,"reg",curreg)="first"_$c(10) + . if $length(region)>0 do ; should be 0 only when curreg=2 + . . write region,! if $data(debug) set debug(debug,"reg",curreg)=region_$c(10) + . . set error=$$parsefhead(.output,1) + . write cmd,! if $data(debug) set debug(debug,"reg",curreg)=$get(debug(debug,"reg",curreg))_cmd + . set error=$$parsefhead(.output,1) + write "exit",! + write /eof + set error=$$parsefhead(.output,1) + close "dseproc" + quit error + + ; when PIPE devices are not supported drive DSE via a HEREDOC in a script +dsefilecmd(output,regionlist,cmd,isVMS) + new scriptfile,dsecmd,dumpfile,error,i,hdr,ftr,line,ts + set ts="_"_$tr($horolog,",","_") + set scriptfile=$select(isVMS:"dsedump"_ts_".com",1:"dsedump"_ts_".sh") + set dsecmd=$select(isVMS:"@",1:"chmod 755 "_scriptfile_"; ./")_scriptfile + set dumpfile="dsedump.txt" + open scriptfile:newversion use scriptfile + ; print the header + set hdr=$select(isVMS:"dsecomhdr",1:"dseshhdr") + for i=1:1 set line=$text(@hdr+i) quit:line["quit" write $piece(line,";",2),! + ; print the dump commands per region + for curreg=2:1:$length(regionlist,",") do + . set region=$piece(regionlist,",",curreg) + . if $length(region)>0 write region,! ; should be 0 only when curreg=2 + . write cmd,! + ; print the footer + set ftr=$select(isVMS:"dsecomftr",1:"dseshftr") + for i=1:1 set line=$text(@ftr+i) quit:line["quit" write $piece(line,";",2),! + ; close and execute the script file + close scriptfile + zsystem dsecmd + ; read script output and rename the file + open dumpfile:readonly use dumpfile set error=$$parsefhead(.output) + close dumpfile:(rename=dumpfile_ts) + ; if no error occurred and debug is UNDEF, delete the script file + if (0=error)&(0=$data(debug)) open scriptfile:readonly close scriptfile:delete + quit error + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; generate the applicable region list + ; the output string is a comma separated list of "FIND -REGION=" and + ; not a list of regions. The first piece is always null as a null string + ; indicates that the script could find no applicable regions. The second piece + ; could be null. If so, that piece represents the first region in which DSE + ; starts up +reglist(reglist,isVMS) + ; reglist - comma separated list of regions + ; isVMS - use '/' (vms) or '-' (unix) for the modifier + ; determine GT.CM regions, '::' (vms) vs ':' (unix) + new reg,regavail,i,mod,gtcmKey,regpath + set mod=$select(isVMS:"/",1:"-") + set gtcmKey=$select(isVMS:"::",1:":") + ; determine the applicable regions - reglist vs actual available regions + set reglist=$select($get(reglist)="":"*",reglist="ALL":"*",1:reglist) + set regavail="" + if "*"'=reglist for i=1:1:$length(reglist,",") do + . set reg=$piece(reglist,",",i) set regavail(reg)=1 ; define the region + kill reg + for i=1:1 set reg=$view("gvnext",$get(reg)) quit:reg="" do + . set regpath=$VIEW("GVFILE",reg) + . quit:(1<$length(regpath,gtcmKey)) + . if ("*"=reglist)!($data(regavail(reg))) do + . . set $piece(regavail,",",$length(regavail,",")+1)=$select(i>1:"find "_mod_"region="_reg,1:"") + quit regavail + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +parsefhead(output,active) + new error,debug,fcnt,field,file,i,line,parsed,region,value + set error=0 + if $data(%DSEWRAP("debug")) set debug=$increment(%DSEWRAP("debug")) + if $length($etrap)=0 set $etrap="use $p zshow ""*"" halt" + ; + for i=1:1 read line(i):5 quit:error quit:$zeof quit:$select($data(active)=0:0,line(i)["DSE>":1,1:0) do + . if ($test=0)&($length(line(i))=0) write ! + . set line=$tr($$FUNC^%TRIM(line(i)),$c(10,13),"") + . quit:($length(line)=0) + . if line["%GTM-E-" set error=1 if $data(%DSEWRAP("debug")) set debug(debug,"error")=line + . if line?1"DSE>".E kill region,file quit ; DSE prompt means reset header information + . quit:line["Error: already in region: " ; ignore already in region error + . if line?1"File"1." ".E set fcnt=$length(line," "),file=$piece(line," ",fcnt) quit + . if line?1"Region"1." ".E do quit + . . set fcnt=$length(line," "),region=$piece(line," ",fcnt) + . . if $data(parsed(region,"File")) kill parsed(region) ; DUPLICATE, throw it away + . . set parsed(region,"File")=file + . quit:$data(region)=0 + . if line?1"Date/Time".E set parsed(region,"Date/Time")=$$FUNC^%TRIM($extract(line,10,$length(line))) quit + . ;;; Match stats like output "DRD : #" + . else if line?3(1U,1N)1" : #".E do + . . set field=$$FUNC^%TRIM($piece(line,"0x",1)),value="0x"_$piece(line,"0x",2) + . . do addfield(.parsed,region,field,value) + . ;;; Match lines with " : (0x[0-9A0Z]*| (TRUE|FALSE))" in them + . else if $length(line," : ")>1 do + . . set field=$$FUNC^%TRIM($piece(line," : ",1)),value=$tr($piece(line," : ",2)," ","") + . . do addfield(.parsed,region,field,value) + . ;;; Match all column oriented data + . else do + . . ;;;; Adjust for the varying column width - the order matters + . . if $extract(line,44,45)=" " set $extract(line,44,45)="|" ; dump -all : Snapshot information + . . else if $extract(line,35,42)=" " set $extract(line,35,42)="|" ; dump -all : all after "Full Block Write.*" + . . else if $extract(line,42,43)=" " set $extract(line,42,43)="|" ; dump + . . new columns,col,data,lastfield,lastpiece + . . set columns=$length(line,"|") + . . ;;;; Handle the column data + . . for col=1:1:columns do + . . . set data=$$FUNC^%TRIM($piece(line,"|",col)) ; trim because of "Snapshot in progress" + . . . set lastpiece=$length(data," ") + . . . ;;;;;; Special case - value is a compound statement like "[WAS_ON] OFF" + . . . if (data["State")&(data["[") set lastpiece=$length(data," ")-1 + . . . ; value is separated by the last space + . . . set value=$piece(data," ",lastpiece,$length(data," ")) + . . . ; take everything but the value and trim off extra spaces + . . . set field=$$FUNC^%TRIM($extract(data,1,($length(data)-$length(value)))) + . . . ;;;;;; Special case - fields where value may not exist + . . . if (data?1"Snapshot file name")!(data?1(1"Journal",1"Temp")1" File:") set value="",field=data + . . . ;;;;;; Special case - paired records like those with "Transaction =" + . . . if field="Transaction =" set field=lastfield_" TN" ; handle paired records + . . . if $data(%DSEWRAP("debug")) set debug(debug,i,field)=value + . . . do addfield(.parsed,region,field,value) + . . . set lastfield=field + merge output=parsed + if $data(%DSEWRAP("debug")) do + . merge %DSEWRAP("debug",debug,"line")=line + . set debug(debug,"pipe0ZOEF")=$zeof,debug(debug,"pipe0DEVICE")=$device,debug(debug,"pipe0ZA")=$ZA + . merge %DSEWRAP("debug")=debug + quit:$quit error quit + +addfield(var,region,field,value) + if $data(var(region,field))\10 set var(region,field,$increment(var(region,field)))=value + else if $data(var(region,field)) do + . set var(region,field,1)=var(region,field),var(region,field)=2,var(region,field,2)=value + else set var(region,field)=value + quit + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +errtrap + use $p + set $etrap="use $principal write $zstatus,! zhalt 1" + set userecode=$piece($ecode,",",2) + set errtext=$select(userecode?1"U"3N:$text(@userecode),1:"") + if $length(errtext) write $text(+0),@$piece(errtext,";",2),! + else write $zstatus,! + if $zlevel<5 zhalt +$extract(userecode,2,$length(userecode)) + quit + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Scripts to drive DSE via ZSystem +dsecomhdr + ;$ define sys$output dsedump.txt + ;$ define sys$error dsedump.txt + ;$ purge /nolog dsedump.txt + ;$ $gtm$dist:dse.exe + quit +dsecomftr + ;$ deassign sys$output + ;$ deassign sys$error + quit +dseshhdr + ;#!/bin/sh + ;$gtm_dist/dse > dsedump.txt 2>&1 << EOF + quit +dseshftr + ;EOF + quit + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Error message texts +U251 ;"-F-NOREGIONS none of the target regions exist" +U252 ;"-F-NOPIPENOALTERNATE GT.M "_$zversion_" does not support pipes and cannot drive a different version of GT.M" +U253 ;"-F-ILLEGALDETAIL """_detail_""" is not a valid specification of details to dump" +U254 ;"-F-ILLEGALSELECTION """_what_""" is not a valid selection of what to dump" +U255 ;"-F-BADINVOCATION Must invoke as DO DUMP^"_$text(+0)_"(...)" diff --git a/sr_port/f_get1.c b/sr_port/f_get1.c new file mode 100644 index 0000000..35c6ea6 --- /dev/null +++ b/sr_port/f_get1.c @@ -0,0 +1,70 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "compiler.h" +#include "toktyp.h" +#include "opcode.h" +#include "indir_enum.h" +#include "mdq.h" +#include "op.h" +#include "fullbool.h" + +error_def(ERR_VAREXPECTED); + +int f_get1(oprtype *a, opctype op) +{ + triple *oldchain, *r; + save_se save_state; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + r = maketriple(OC_NOOP); /* We'll fill in the opcode later, when we figure out what it is */ + switch (TREF(window_token)) + { + case TK_IDENT: + r->opcode = OC_FNGET1; + if (!lvn(&r->operand[0], OC_SRCHINDX, 0)) + return FALSE; + break; + case TK_CIRCUMFLEX: + r->opcode = OC_FNGVGET1; + if (!gvn()) + return FALSE; + break; + case TK_ATSIGN: + r->opcode = OC_INDFUN; + r->operand[1] = put_ilit((mint)indir_get); + if (SHIFT_SIDE_EFFECTS) + { /* with short-circuited booleans move indirect processing to expr_start */ + START_GVBIND_CHAIN(&save_state, oldchain); + if (!indirection(&r->operand[0])) + { + setcurtchain(oldchain); + return FALSE; + } + ins_triple(r); + PLACE_GVBIND_CHAIN(&save_state, oldchain); + *a = put_tref(r); + return TRUE; + } + if (!indirection(&(r->operand[0]))) + return FALSE; + break; + default: + stx_error(ERR_VAREXPECTED); + return FALSE; + } + ins_triple(r); + *a = put_tref(r); + return TRUE; +} diff --git a/sr_port/f_zpeek.c b/sr_port/f_zpeek.c new file mode 100644 index 0000000..1006b61 --- /dev/null +++ b/sr_port/f_zpeek.c @@ -0,0 +1,78 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#include "mdef.h" + +#include "compiler.h" +#include "opcode.h" +#include "toktyp.h" +#include "advancewindow.h" + +error_def(ERR_COMMA); + +#ifdef UNIX +/* Compile 4 parameter $ZPEEK(baseadr,offset,length<,format>) function where: + * + * structid - A string containing a set of mnemonics that identify the structure to fetch from (see op_fnzpeek.c) + * offset - Offset into the block (error if negative). + * length - Length to return (error if negative or > MAX_STRLEN). + * format - Option parm contains single char formatting code (see op_fnzpeek.c) + */ +int f_zpeek(oprtype *a, opctype op) +{ + oprtype x; + triple *offset, *length, *format, *r; + mval mv; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + r = maketriple(op); + if (EXPR_FAIL == expr(&(r->operand[0]), MUMPS_STR)) /* Structure identifier string */ + return FALSE; + if (TK_COMMA != TREF(window_token)) + { + stx_error(ERR_COMMA); + return FALSE; + } + advancewindow(); + offset = newtriple(OC_PARAMETER); + r->operand[1] = put_tref(offset); + if (EXPR_FAIL == expr(&(offset->operand[0]), MUMPS_INT)) + return FALSE; + if (TK_COMMA != TREF(window_token)) + { + stx_error(ERR_COMMA); + return FALSE; + } + advancewindow(); + length = newtriple(OC_PARAMETER); + offset->operand[1] = put_tref(length); + if (EXPR_FAIL == expr(&(length->operand[0]), MUMPS_INT)) + return FALSE; + format = newtriple(OC_PARAMETER); + length->operand[1] = put_tref(format); + if (TK_COMMA != TREF(window_token)) + format->operand[0] = put_str("C", 1); /* Default format if none specified */ + else + { + advancewindow(); + if (EXPR_FAIL == expr(&(format->operand[0]), MUMPS_STR)) + return FALSE; + } + ins_triple(r); + *a = put_tref(r); + return TRUE; +} +#else /* VMS - function not supported here */ +int f_zpeek(oprtype *a, opctype op) +{ + GTMASSERT; +} +#endif diff --git a/sr_port/f_zwrite.c b/sr_port/f_zwrite.c new file mode 100644 index 0000000..429e736 --- /dev/null +++ b/sr_port/f_zwrite.c @@ -0,0 +1,60 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "toktyp.h" +#include "mdq.h" +#include "fullbool.h" + + +/* $ZWRITE(): Single parameter - string expression */ +int f_zwrite(oprtype *a, opctype op) +{ + triple *oldchain, *r; + save_se save_state; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + if (TK_ATSIGN != TREF(window_token)) + { + r = maketriple(op); + if (EXPR_FAIL == expr(&(r->operand[0]), MUMPS_STR)) + return FALSE; + ins_triple(r); + } else + { + r = maketriple(OC_INDFUN); + if (SHIFT_SIDE_EFFECTS) + { + START_GVBIND_CHAIN(&save_state, oldchain); + if (!indirection(&(r->operand[0]))) + { + setcurtchain(oldchain); + return FALSE; + } + r->operand[1] = put_ilit((mint)indir_fnzwrite); + ins_triple(r); + PLACE_GVBIND_CHAIN(&save_state, oldchain); + } else + { + if (!indirection(&(r->operand[0]))) + return FALSE; + r->operand[1] = put_ilit((mint)indir_fnzwrite); + ins_triple(r); + } + } + *a = put_tref(r); + return TRUE; +} + diff --git a/sr_port/glvn_pool.c b/sr_port/glvn_pool.c new file mode 100644 index 0000000..b96667c --- /dev/null +++ b/sr_port/glvn_pool.c @@ -0,0 +1,99 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include + +#include "gtm_stdio.h" + +#include "min_max.h" +#include "lv_val.h" +#include +#include "mv_stent.h" +#include "compiler.h" +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "opcode.h" +#include "glvn_pool.h" +#include "parm_pool.h" /* for CAPACITY_ROUND_UP2 macro */ + +void glvn_pool_init(void) +{ + glvn_pool *pool; + uint4 capacity, mval_capacity, slotoff; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + capacity = INIT_GLVN_POOL_CAPACITY; + mval_capacity = INIT_GLVN_POOL_MVAL_CAPACITY; + slotoff = (uint4)OFFSETOF(glvn_pool, slot[0]); + pool = (glvn_pool *)malloc(ROUND_UP(slotoff, (capacity + 1) * SIZEOF(glvn_pool_entry))); + pool->mval_stack = (mval *)malloc(mval_capacity * SIZEOF(mval)); + pool->capacity = capacity; + pool->top = 0; + pool->mval_capacity = mval_capacity; + pool->mval_top = 0; + memset(pool->for_slot, (int)GLVN_POOL_EMPTY, (MAX_FOR_STACK + 1) * SIZEOF(uint4)); + TREF(glvn_pool_ptr) = pool; +} + +void glvn_pool_expand_slots(void) +{ + glvn_pool *pool, *old_pool; + uint4 capacity, slotoff; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + old_pool = TREF(glvn_pool_ptr); + capacity = 2 * old_pool->capacity; + assert(capacity <= MAX_EXPECTED_CAPACITY); /* Don't expect more than this in the test system */ + slotoff = (uint4)OFFSETOF(glvn_pool, slot[0]); + pool = (glvn_pool *)malloc(ROUND_UP(slotoff, (capacity + 1) * SIZEOF(glvn_pool_entry))); + memcpy(pool, old_pool, slotoff + old_pool->top * SIZEOF(glvn_pool_entry)); + pool->capacity = capacity; + TREF(glvn_pool_ptr) = pool; + free(old_pool); +} + +void glvn_pool_expand_mvals(void) +{ + glvn_pool *pool; + glvn_pool_entry *slot, *top; + int i, n; + mval *mval_stack, *old_mval_stack; + uint4 mval_capacity; + INTPTR_T shift; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + pool = TREF(glvn_pool_ptr); + mval_capacity = 2 * pool->mval_capacity; + assert(mval_capacity <= MAX_EXPECTED_MVAL_CAPACITY); /* Don't expect more than this in the test system */ + old_mval_stack = pool->mval_stack; + mval_stack = (mval *)malloc(mval_capacity * SIZEOF(mval)); + memcpy(mval_stack, old_mval_stack, pool->mval_top * SIZEOF(mval)); + shift = (INTPTR_T)mval_stack - (INTPTR_T)old_mval_stack; + for (slot = pool->slot, top = slot + pool->top - 1; slot < top; slot++) + { /* Touch up glvn_info pointers, but leave lvn start alone */ + n = slot->glvn_info.n; + assert(n <= MAX_ACTUALS); + if (FIRST_SAVED_ARG(slot)) + slot->lvname = (mval *)(shift + (char *)slot->lvname); + for (i = FIRST_SAVED_ARG(slot); i < n; i++) + slot->glvn_info.arg[i] = (void *)(shift + (char *)slot->glvn_info.arg[i]); + } + pool->mval_stack = mval_stack; + pool->mval_capacity = mval_capacity; + free(old_mval_stack); +} diff --git a/sr_port/glvn_pool.h b/sr_port/glvn_pool.h new file mode 100644 index 0000000..aa82f2c --- /dev/null +++ b/sr_port/glvn_pool.h @@ -0,0 +1,139 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef GLVN_POOL_H_INCLUDED +#define GLVN_POOL_H_INCLUDED + +#include "callg.h" +#include "compiler.h" +#include "lv_val.h" + +/* Here we provide tools for saving identifying information of local or global variables. For local variables this includes + * the variable name itself, as well as copies of each subscript. For global variables we save each argument that needs to + * be later passed into op_gvname/op_gvnaked/op_gvextnam. Note that deferring the op_gvnaked call allows us to achieve + * correct naked indicator flow. For example, in the command SET @"^(subs)"=rhs, the ^() needs to be evaluated relative to + * the expression on the right hand side, and the right hand side needs to happen AFTER the subscripts have been evaluated. + * The structure involved - the "glvn pool" - consists of a stack of entries, each corresponding to a single glvn, and + * a parallel stack of mvals, each corresponding to some parent entry. Both stacks are expandable, doubling in size whenever + * they run out of space. The glvn pool entries can be popped in three different ways. For SET, it's convenient to save the + * glvn pool state, i.e. the top of the array of still-relevant entries. After completion of the set, the pool is restored to + * this state and younger entries popped. With FOR, it's more convenient defer popping until another FOR loop at the same + * nesting level starts. At that time the previously used FOR slot is recycled and everything younger than it is popped. + * Finally, when a non-indirect frame is unwound, all younger pool entries are popped. + */ + +#define ANY_SLOT 0 +#define FIRST_SAVED_ARG(SLOT) ((OC_SAVLVN == (SLOT)->sav_opcode) ? 1 : 0) +/* To avoid breaking gtmpcat, we retain the 'for_ctrl_stack' field of the frame_pointer struct instead of replacing it +* with a uint4 'glvn_indx' field. The macros manipulate this field. Also for the convenience of gtmpcat: we declare the +* glvn_pool and glvn_pool_entry structs in compiler.h instead of here. This is because gtmpcat does not know to include +* glvn_pool.h when going through gtm_threadgbl_defs.h. +* When gtmpcat is changed to accommodate a new name, these macros and the stack frame struct need to be changed, +* and the glvn_pool structs in compiler.h should probably be moved into this file. +*/ +#define GLVN_INDX(FP) ((uint4)(UINTPTR_T)((FP)->for_ctrl_stack)) +#define GLVN_POOL_EMPTY ((uint4)-1) /* this must be an "impossible" value for a real pool */ +#define GLVN_POOL_SLOTS_AVAILABLE ((TREF(glvn_pool_ptr))->capacity - (TREF(glvn_pool_ptr))->top) +#define GLVN_POOL_MVALS_AVAILABLE ((TREF(glvn_pool_ptr))->mval_capacity - (TREF(glvn_pool_ptr))->mval_top) +#define INIT_GLVN_POOL_CAPACITY 8 +#define INIT_GLVN_POOL_MVAL_CAPACITY 64 +#define GLVN_POOL_UNTOUCHED 0 +#define MAX_EXPECTED_CAPACITY 2048 +#define MAX_EXPECTED_MVAL_CAPACITY 2048 +#define SLOT_NEEDS_REWIND(INDX) (((TREF(glvn_pool_ptr))->top <= (INDX)) && (GLVN_POOL_EMPTY != (INDX))) +#define SLOT_OPCODE(INDX) ((TREF(glvn_pool_ptr))->slot[INDX].sav_opcode) + +#define SET_GLVN_INDX(FP, VALUE) \ +{ \ + (FP)->for_ctrl_stack = (unsigned char *)(UINTPTR_T)(VALUE); \ +} + +#define GLVN_POOL_EXPAND_IF_NEEDED \ +{ \ + if (!TREF(glvn_pool_ptr)) \ + glvn_pool_init(); \ + else if (!GLVN_POOL_SLOTS_AVAILABLE) \ + glvn_pool_expand_slots(); \ +} + +#define ENSURE_GLVN_POOL_SPACE(SPC) \ +{ \ + if (GLVN_POOL_MVALS_AVAILABLE < (uint4)(SPC)) \ + { \ + glvn_pool_expand_mvals(); \ + assert(GLVN_POOL_MVALS_AVAILABLE >= (uint4)(SPC)); \ + } \ +} + +#define GET_GLVN_POOL_STATE(SLOT, M) \ +{ /* Find current available SLOT and mval. */ \ + uint4 INDX, MVAL_INDX; \ + \ + INDX = (TREF(glvn_pool_ptr))->share_slot; \ + SLOT = &(TREF(glvn_pool_ptr))->slot[INDX]; \ + MVAL_INDX = SLOT->mval_top; \ + M = &(TREF(glvn_pool_ptr))->mval_stack[MVAL_INDX]; \ +} + +#define DRAIN_GLVN_POOL_IF_NEEDED \ +{ \ + int I; \ + uint4 INDX, FINDX; \ + glvn_pool_entry *SLOT; \ + \ + if ((GLVN_POOL_UNTOUCHED != GLVN_INDX(frame_pointer)) && !(frame_pointer->flags & SFF_INDCE)) \ + { /* Someone used an ugly FOR control variable or did an indirect set. */ \ + INDX = (GLVN_POOL_EMPTY != GLVN_INDX(frame_pointer)) ? GLVN_INDX(frame_pointer) : 0; \ + op_glvnpop(INDX); \ + for (I = 1; I <= MAX_FOR_STACK; I++) \ + { /* rewind the for_slot array */ \ + FINDX = (TREF(glvn_pool_ptr))->for_slot[I]; \ + if (SLOT_NEEDS_REWIND(FINDX)) \ + { /* reset to precursor */ \ + SLOT = &(TREF(glvn_pool_ptr))->slot[FINDX]; \ + assert(!SLOT_NEEDS_REWIND(SLOT->precursor)); \ + (TREF(glvn_pool_ptr))->for_slot[I] = SLOT->precursor; \ + } else /* no higher FOR levels were used by current frame */ \ + break; \ + } \ + } \ +} + +#define INSERT_INDSAVGLVN(CTRL, V, RECYCLE, DO_REF) \ +{ \ + triple *PUSH, *SAV, *PAR; \ + \ + PUSH = newtriple(OC_GLVNSLOT); \ + PUSH->operand[0] = put_ilit((mint)(RECYCLE)); \ + CTRL = put_tref(PUSH); \ + SAV = newtriple(OC_INDSAVGLVN); \ + SAV->operand[0] = V; \ + PAR = newtriple(OC_PARAMETER); \ + SAV->operand[1] = put_tref(PAR); \ + PAR->operand[0] = CTRL; \ + PAR->operand[1] = put_ilit((mint)(DO_REF)); /* flag to suppress global reference here */ \ +} + +void glvn_pool_init(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */ +void glvn_pool_expand_slots(void); /* invoked via GLVN_POOL_EXPAND_IF_NEEDED macro */ +void glvn_pool_expand_mvals(void); /* invoked via ENSURE_GLVN_POOL_SPACE macro */ +void op_glvnpop(uint4 indx); /* Used by [SET and $ORDER()] */ +uint4 op_glvnslot(uint4 recycle); /* Used by [FOR, SET and $ORDER()] */ +void op_indsavglvn(mval *target, uint4 slot, uint4 do_ref); /* Used by [SET and $ORDER()] */ +void op_indsavlvn(mval *target, uint4 slot); /* Used by [FOR] */ +void op_rfrshgvn(uint4 indx, opctype oc); /* Used by [SET and $ORDER()] */ +lv_val *op_rfrshlvn(uint4 indx, opctype oc); /* Used by [FOR, SET and $ORDER()] */ +void op_savgvn(UNIX_ONLY_COMMA(int argcnt) mval *val_arg, ...); /* Used by [SET and $ORDER()] */ +void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...); /* Used by [FOR, SET and $ORDER()] */ +void op_shareslot(uint4 indx, opctype opcode); /* Used by [FOR, SET and $ORDER()] */ +void op_stoglvn(uint4 indx, mval *value); /* Used by [SET] */ + +#endif /* GLVN_POOL_H_INCLUDED */ diff --git a/sr_port/gtm_common_defs.h b/sr_port/gtm_common_defs.h new file mode 100644 index 0000000..4b75d9c --- /dev/null +++ b/sr_port/gtm_common_defs.h @@ -0,0 +1,146 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#ifndef GTM_COMMON_DEFS_H +#define GTM_COMMON_DEFS_H + +#if defined(__ia64) || defined(__x86_64__) || defined(__sparc) || defined(__s390__) || defined (_AIX) +# define GTM64 +#endif + +#ifdef GTM64 +# define GTM64_ONLY(X) X +# define NON_GTM64_ONLY(X) +#else +# define GTM64_ONLY(X) +# define NON_GTM64_ONLY(X) X +#endif + +#ifndef __vms +# define readonly +# define GBLDEF +# define GBLREF extern +# define LITDEF const +# define LITREF extern const +# define error_def(x) LITREF int x +#else +# ifdef __cplusplus +# define GBLDEF +# define GBLREF extern +# define LITDEF const +# define LITREF extern const +# else +# define GBLDEF globaldef +# define GBLREF globalref +# define LITDEF const globaldef +# define LITREF const globalref +# endif +#endif +/* Use GBLDEF to define STATICDEF for variables and STATICFNDEF, STATICFNDCL for functions. Define STATICDEF to "GBLDEF". This way + * we know such usages are intended to be "static" but yet can effectively debug these variables since they are externally + * visible. For functions, do not use the "static" keyword to make them externally visible. Note that a STATICREF for variables + * does not make sense since statics are supposed to be used only within one module. + */ +#define STATICDEF GBLDEF +#define STATICFNDCL extern +#define STATICFNDEF + +#ifndef TRUE +# define TRUE 1 +#endif +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef NULL +# define NULL ((void *) 0) +#endif + +#if defined(__ia64) || defined(__MVS__) +# define INTCAST(X) ((int)(X)) +# define UINTCAST(X) ((uint4)(X)) +# define STRLEN(X) ((int)(strlen(X))) +# define USTRLEN(X) ((unsigned int)(strlen(X))) +# define OFFSETOF(X,Y) ((int)(offsetof(X,Y))) +#else +# define INTCAST(X) X +# define UINTCAST(X) X +# define STRLEN(X) strlen(X) +# define USTRLEN(X) strlen(X) +# define OFFSETOF(X,Y) offsetof(X,Y) +#endif + +#ifndef __vms +# define DIR_SEPARATOR '/' +#endif + +/* the LITERAL version of the macro should be used over STRING whenever possible for efficiency reasons */ +#define STR_LIT_LEN(LITERAL) (SIZEOF(LITERAL) - 1) +#define LITERAL_AND_LENGTH(LITERAL) (LITERAL), (SIZEOF(LITERAL) - 1) +#define LENGTH_AND_LITERAL(LITERAL) (SIZEOF(LITERAL) - 1), (LITERAL) +#define STRING_AND_LENGTH(STRING) (STRING), (STRLEN((char *)(STRING))) +#define LENGTH_AND_STRING(STRING) (strlen((char *)(STRING))), (STRING) + +#define LEN_AND_LIT(LITERAL) LENGTH_AND_LITERAL(LITERAL) +#define LIT_AND_LEN(LITERAL) LITERAL_AND_LENGTH(LITERAL) +#define STR_AND_LEN(STRING) STRING_AND_LENGTH(STRING) +#define LEN_AND_STR(STRING) LENGTH_AND_STRING(STRING) + +#define ARRAYSIZE(arr) SIZEOF(arr)/SIZEOF(arr[0]) /* # of elements defined in the array */ +#define ARRAYTOP(arr) (&arr[0] + ARRAYSIZE(arr)) /* address of the TOP of the array (first byte AFTER + * array limits).Use &arr[0] + size instead of + * &arr[size] to avoid compiler warning. + */ + +#define MEMCMP_LIT(SOURCE, LITERAL) memcmp(SOURCE, LITERAL, SIZEOF(LITERAL) - 1) +#define MEMCPY_LIT(TARGET, LITERAL) memcpy(TARGET, LITERAL, SIZEOF(LITERAL) - 1) + +#define DIVIDE_ROUND_UP(VALUE, MODULUS) (((VALUE) + ((MODULUS) - 1)) / (MODULUS)) +#define DIVIDE_ROUND_DOWN(VALUE, MODULUS) ((VALUE) / (MODULUS)) +#define ROUND_UP(VALUE, MODULUS) (DIVIDE_ROUND_UP(VALUE, MODULUS) * (MODULUS)) +#define ROUND_DOWN(VALUE, MODULUS) (DIVIDE_ROUND_DOWN(VALUE, MODULUS) * (MODULUS)) + +/* Macro to copy a source string to a malloced area that is set to the destination pointer. + * Since it is possible that DST might have multiple pointer dereferences in its usage, we + * use a local pointer variable and finally assign it to DST thereby avoiding duplication of + * those pointer dereferences (one for the malloc and one for the strcpy). + * There are two macros depending on whether a string or literal is passed. + */ +#define MALLOC_CPY_STR(DST, SRC) \ +{ \ + char *mcs_ptr; \ + int mcs_len; \ + \ + mcs_len = STRLEN(SRC) + 1; \ + mcs_ptr = malloc(mcs_len); \ + memcpy(mcs_ptr, SRC, mcs_len); \ + DST = mcs_ptr; \ +} + +#define MALLOC_CPY_LIT(DST, SRC) \ +{ \ + char *mcs_ptr; \ + int mcs_len; \ + \ + mcs_len = SIZEOF(SRC); \ + mcs_ptr = malloc(mcs_len); \ + memcpy(mcs_ptr, SRC, mcs_len); \ + DST = mcs_ptr; \ +} + +#define MALLOC_INIT(DST, SIZ) \ +{ \ + void *lcl_ptr; \ + \ + lcl_ptr = malloc(SIZ); \ + memset(lcl_ptr, 0, SIZ); \ + DST = lcl_ptr; \ +} + +#endif /* GTM_COMMON_DEFS_H */ diff --git a/sr_port/gtm_ipv6.h b/sr_port/gtm_ipv6.h new file mode 100644 index 0000000..60441ca --- /dev/null +++ b/sr_port/gtm_ipv6.h @@ -0,0 +1,134 @@ +/**************************************************************** + * * + * Copyright 2001, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +/* gtm_ipv6.h - interlude to system header file. */ +#ifndef GTM_IPV6H +#define GTM_IPV6H + +#include /* Make sure we have AI_V4MAPPED/AI_NUMERICSERV defined if available */ + +GBLREF boolean_t ipv4_only; /* If TRUE, only use AF_INET. */ + +/* ai_canonname must be set NULL for AIX. Otherwise, freeaddrinfo() freeing the ai_canonname will hit SIG-11 + * other field which were not initialized as 0 will also causes getaddrinfo()to fail + * Setting AI_PASSIVE will give you a wildcard address if addr is NULL, i.e. INADDR_ANY or IN6ADDR_ANY + * AI_NUMERICSERV is to pass the numeric port to address, it is to inhibit the name resolution to improve efficience + * AI_ADDRCONFIG: IPv4 addresses are returned only if the local system has at least one IPv4 address + configured; IPv6 addresses are only returned if the local system has at least one IPv6 + address configured. For now we only use IPv6 address. So not use this flag here. + * AI_V4MAPPED: IPv4 mapped addresses are acceptable + * (Note: for snail, AI_V4MAPPED is defined but AI_NUMERICSERV is not defined) + */ + +#if (defined(__hppa) || defined(__vms) || defined(__osf__)) +#define GTM_IPV6_SUPPORTED FALSE +#else +#define GTM_IPV6_SUPPORTED TRUE +#endif + +#if !GTM_IPV6_SUPPORTED +#define SERVER_HINTS(hints, af) \ +{ \ + assert(AF_INET6 != af); \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = AF_INET; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_PASSIVE; \ +} +#define CLIENT_HINTS(hints) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = AF_INET; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = 0; \ +} + +#define CLIENT_HINTS_AF(hints, af) \ +{ \ + assert(AF_INET == af); \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = AF_INET; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = 0; \ +} + +#elif (defined(AI_V4MAPPED) && defined(AI_NUMERICSERV)) +#define SERVER_HINTS(hints, af) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = af; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_V4MAPPED | AI_PASSIVE | AI_NUMERICSERV; \ +} +#define CLIENT_HINTS(hints) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = (ipv4_only ? AF_INET : AF_UNSPEC); \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; \ +} +#define CLIENT_HINTS_AF(hints, af) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = af; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_V4MAPPED; \ +} + +#else +#error "Ok, so we do have non-AI_V4MAPPED/AI_NUMERICSERV machines with IPv6 support" +#define SERVER_HINTS(hints, af) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = af; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_PASSIVE; \ +} +#define CLIENT_HINTS(hints) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = (ipv4_only ? AF_INET : AF_UNSPEC); \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = AI_ADDRCONFIG; \ +} +#define CLIENT_HINTS_AF(hints, af) \ +{ \ + memset(&hints, 0, SIZEOF(struct addrinfo)); \ + hints.ai_family = AF_INET; \ + hints.ai_socktype = SOCK_STREAM; \ + hints.ai_protocol = IPPROTO_TCP; \ + hints.ai_flags = 0; \ +} +#endif + +#define FREEADDRINFO(ai_ptr) \ +{ \ + if(ai_ptr) \ + freeaddrinfo(ai_ptr); \ +} + +union gtm_sockaddr_in46 +{ + struct sockaddr_in ipv4; +# if GTM_IPV6_SUPPORTED + struct sockaddr_in6 ipv6; +# endif +}; + +#endif diff --git a/sr_port/iosocket_destroy.c b/sr_port/iosocket_destroy.c new file mode 100644 index 0000000..b9fbce9 --- /dev/null +++ b/sr_port/iosocket_destroy.c @@ -0,0 +1,51 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_stdio.h" +#include "gtm_unistd.h" +#include "gtm_socket.h" + +#include "io.h" +#include "iotcpdef.h" +#include "iotcproutine.h" +#include "iosocketdef.h" +#include "gtmio.h" + +GBLREF io_log_name *io_root_log_name; + +void iosocket_destroy (io_desc *ciod) +{ + io_log_name **lpp, *lp; /* logical name pointers */ + d_socket_struct *dsocketptr; + assertpro(ciod->type == gtmsocket); + assertpro(ciod->state == dev_closed); + dsocketptr = (d_socket_struct *) ciod->dev_sp; + assertpro(dsocketptr != NULL); + for (lpp = &io_root_log_name, lp = *lpp; lp; lp = *lpp) + { + if (lp->iod->pair.in == ciod) + { + /* The only device that may be "split" is the principal device. Since it is permanently open, + * it will never get here. + */ + assert(lp->iod == ciod); + assert(lp->iod->pair.out == ciod); + *lpp = (*lpp)->next; + free(lp); + } + else + lpp = &lp->next; + } + free(dsocketptr); + free(ciod); +} diff --git a/sr_port/lock_str_to_buff.c b/sr_port/lock_str_to_buff.c new file mode 100644 index 0000000..2eaf809 --- /dev/null +++ b/sr_port/lock_str_to_buff.c @@ -0,0 +1,35 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "error.h" +#include "mlkdef.h" +#include "lock_str_to_buff.h" +#include "gtm_string.h" +#include "zshow.h" + +/* Takes a lock as input and outputs lock name to string to buff (terminated with NULL). This is called from op_lock2. + * This function consolidates "output" variable initialization and name string formatting into one function. + */ +void lock_str_to_buff(mlk_pvtblk *pvt_ptr, char *outbuff, int outbuff_len) +{ + mval v; + zshow_out output; + + memset(&output, 0, SIZEOF(output)); + output.type = ZSHOW_BUFF_ONLY; /* This setting only changes out->ptr the other fileds are ignored */ + output.buff = &outbuff[0]; + output.size = outbuff_len; + output.ptr = output.buff; + zshow_format_lock(&output,pvt_ptr); + *output.ptr = '\0'; + return; +} diff --git a/sr_port/lock_str_to_buff.h b/sr_port/lock_str_to_buff.h new file mode 100644 index 0000000..a154d2e --- /dev/null +++ b/sr_port/lock_str_to_buff.h @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef LOCK_STR_TO_BUFF_H +#define LOCK_STR_TO_BUFF_H + +void lock_str_to_buff(mlk_pvtblk *pvt_ptr1, char *outbuff, int outbuff_len); + +#endif diff --git a/sr_port/mpiece.mpt b/sr_port/mpiece.mpt new file mode 100644 index 0000000..c309e93 --- /dev/null +++ b/sr_port/mpiece.mpt @@ -0,0 +1,38 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; Copyright 2012 Fidelity Information Services, Inc. ; +; ; +; This source code contains the intellectual property ; +; of its copyright holder(s), and is made available ; +; under a license. If you do not know the terms of ; +; the license, please stop and do not read further. ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%MPIECE(str,delim,newdelim) + ; Replace one or more consecutive occurrences of input parameter + ; 'delim' with one 'newdelim' in parameter 'str' so that you can + ; use $piece on the result. + ; This lets us use $piece like AWK does + new dlen,i,lastch,len,next,output,substr + ; convert tabs to spaces when delim is not specified + if $length($get(delim))=0 set str=$translate(str,$char(9),$char(32)) + set newdelim=$get(newdelim,$char(32)) ; default to space + set delim=$get(delim,$char(32)) ; default to space + set len=$zlength(str),lastch=1,dlen=$zlength(delim) + ; $zfind to the first occurrence of delim after lastch + for i=1:1 quit:lastch>len set next=$zfind(str,delim,lastch) quit:'next do + . ; append non-null extract of str from lastch to next + . set substr=$zextract(str,lastch,next-(1+dlen)) + . if $zlength(substr) set output=$get(output)_substr_newdelim + . ; advance until the next non-delim character + . for lastch=next:1:(len+1) quit:($zextract(str,lastch)'=delim) + ; append the remainder of str + if lastch<(len+1) set output=$get(output)_$zextract(str,lastch,len) + quit $get(output) + ; split a string into an array like AWK split does +SPLIT(str,delim) + new outstr,i + set outstr=$$^%MPIECE(str,$get(delim,$char(32)),$char(0)) + for i=1:1:$zlength(outstr,$char(0)) set fields(i)=$zpiece(outstr,$char(0),i) + if $data(fields)<10 set $ECODE=",U117," + quit *fields diff --git a/sr_port/mtables.h b/sr_port/mtables.h new file mode 100644 index 0000000..b3a6654 --- /dev/null +++ b/sr_port/mtables.h @@ -0,0 +1,16 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#ifndef MTABLE_H_DEFINED +#define MTABLE_H_DEFINED + +void mtables_chk(void); /* Routine invoked in debug builds to check some mtable assertions */ + +#endif diff --git a/sr_port/mu_put_gvn_fragment.c b/sr_port/mu_put_gvn_fragment.c new file mode 100644 index 0000000..4115f27 --- /dev/null +++ b/sr_port/mu_put_gvn_fragment.c @@ -0,0 +1,36 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "op.h" +#include "mupip_put_gvn_fragment.h" +#include "mv_stent.h" + +void mupip_put_gvn_fragment(char *cp,int len, int val_off1, int val_len1) +{ + mval *u, v; + mv_stent *mv_stacktop; + + PUSH_MV_STENT(MVST_MVAL); /* protect mval value from stp_gcol */ + mv_stacktop = mv_chain; + u = &mv_chain->mv_st_cont.mvs_mval; + u->str.len = 0; + u->mvtype = 0; + op_fngvget1(u); + v.mvtype = MV_STR; + v.str.addr = cp; + v.str.len = len; + op_setzextract(u, &v, val_off1+1, (val_off1 + val_len1), u); + op_gvput(u); + assertpro(mv_stacktop == mv_chain); + POP_MV_STENT(); + return; +} diff --git a/sr_port/mupip_put_gvn_fragment.h b/sr_port/mupip_put_gvn_fragment.h new file mode 100644 index 0000000..59c2c11 --- /dev/null +++ b/sr_port/mupip_put_gvn_fragment.h @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef MUPIP_PUT_GVN_FRAGMENT_INCLUDED +#define MUPIP_PUT_GVN_FRAGMENT_INCLUDED + +void mupip_put_gvn_fragment(char *cp, int len, int val_off1, int val_len1); + +#endif /* MUPIP_PUT_GVN_FRAGMENT_INCLUDED */ diff --git a/sr_port/op_fnget1.c b/sr_port/op_fnget1.c new file mode 100644 index 0000000..d3919a8 --- /dev/null +++ b/sr_port/op_fnget1.c @@ -0,0 +1,28 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "op.h" + +/* This code is similar in function to opp_fnget (assembler) except, if src is undefined, this returns an undefined value to signal + * op_fnget2, which, in turn, returns a specified "default" value; this slight of hand deals with order of evaluation issues. + */ +void op_fnget1(mval *src, mval *dst) +{ + if (src && MV_DEFINED(src)) + { + *dst = *src; + dst->mvtype &= ~MV_ALIASCONT; /* Make sure alias container property does not pass */ + } + else + dst->mvtype = 0; + return; +} diff --git a/sr_port/op_fnzwrite.c b/sr_port/op_fnzwrite.c new file mode 100644 index 0000000..4c58e51 --- /dev/null +++ b/sr_port/op_fnzwrite.c @@ -0,0 +1,44 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "gtm_string.h" +#include "stringpool.h" +#include "op.h" +#include "zshow.h" + +error_def(ERR_MAXSTRLEN); + +/* Routine to return a string in zwrite format */ +void op_fnzwrite(mval* src, mval* dst) +{ + int dst_len, str_len; + + MV_FORCE_STR(src); + MV_FORCE_NUM(src); + if MV_IS_CANONICAL(src) + *dst = *src; + else + { + str_len = ZWR_EXP_RATIO(src->str.len); + ENSURE_STP_FREE_SPACE((int)str_len); + DBG_MARK_STRINGPOOL_UNEXPANDABLE; + format2zwr((sm_uc_ptr_t)src->str.addr, src->str.len, (uchar_ptr_t)stringpool.free, &dst_len); + DBG_MARK_STRINGPOOL_EXPANDABLE; + if (MAX_STRLEN < dst_len) + rts_error(VARLSTCNT(1) ERR_MAXSTRLEN); + dst->str.addr = (char *)stringpool.free; /* deferred in case dst == str */ + dst->str.len = dst_len; + dst->mvtype = MV_STR; + assert((unsigned char *)(dst->str.addr + dst_len) <= stringpool.top); + stringpool.free = (unsigned char *)(dst->str.addr + dst_len); + } +} diff --git a/sr_port/op_glvnpop.c b/sr_port/op_glvnpop.c new file mode 100644 index 0000000..f1256e5 --- /dev/null +++ b/sr_port/op_glvnpop.c @@ -0,0 +1,43 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +void op_glvnpop(uint4 indx) +{ + glvn_pool_entry *slot; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + slot = &(TREF(glvn_pool_ptr))->slot[indx]; + (TREF(glvn_pool_ptr))->top = indx; + (TREF(glvn_pool_ptr))->mval_top = slot->mval_top; +} diff --git a/sr_port/op_glvnslot.c b/sr_port/op_glvnslot.c new file mode 100644 index 0000000..8078179 --- /dev/null +++ b/sr_port/op_glvnslot.c @@ -0,0 +1,68 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +GBLREF stack_frame *frame_pointer; + +/* Finds a slot in the glvn pool for saving a variable name. Used by SET and FOR */ +uint4 op_glvnslot(uint4 recycle) +{ + glvn_pool_entry *slot; + uint4 indx, findx; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + GLVN_POOL_EXPAND_IF_NEEDED; + indx = (TREF(glvn_pool_ptr))->top; + if (GLVN_POOL_UNTOUCHED == GLVN_INDX(frame_pointer)) + /* low water mark - drain back to here when frame is unwound */ + SET_GLVN_INDX(frame_pointer, (indx) ? indx : GLVN_POOL_EMPTY); + slot = &(TREF(glvn_pool_ptr))->slot[indx]; + slot->sav_opcode = OC_NOOP; /* flag the slot as not filled out in case something goes wrong */ + if (ANY_SLOT != recycle) + { /* attempt to reuse slot (for FOR control) */ + assert((0 < recycle) && (recycle <= MAX_FOR_STACK)); + findx = (TREF(glvn_pool_ptr))->for_slot[recycle]; + if (((GLVN_INDX(frame_pointer) <= findx) || (GLVN_POOL_EMPTY == GLVN_INDX(frame_pointer))) && (findx < indx)) + { /* reuse and pop anything beyond it */ + slot = &(TREF(glvn_pool_ptr))->slot[findx]; + (TREF(glvn_pool_ptr))->top = findx + 1; + (TREF(glvn_pool_ptr))->mval_top = slot->mval_top; + return findx; + } + /* point new slot's precursor field at indx, which corresponds an earlier frame */ + (TREF(glvn_pool_ptr))->for_slot[recycle] = indx; + slot->precursor = (findx < indx) ? findx : GLVN_POOL_EMPTY; + } + slot->mval_top = (TREF(glvn_pool_ptr))->mval_top; + return (TREF(glvn_pool_ptr))->top++; +} diff --git a/sr_port/op_igetdst.c b/sr_port/op_igetdst.c new file mode 100644 index 0000000..b35124a --- /dev/null +++ b/sr_port/op_igetdst.c @@ -0,0 +1,21 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "op.h" + +mval *op_igetdst(void) +{ + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + return TREF(ind_result); /* see comment in comp_init.c */ +} diff --git a/sr_port/op_indfnname2.c b/sr_port/op_indfnname2.c new file mode 100644 index 0000000..c034215 --- /dev/null +++ b/sr_port/op_indfnname2.c @@ -0,0 +1,62 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "mvalconv.h" +#include "op.h" +#include "is_canonic_name.h" + +error_def(ERR_FNNAMENEG); +error_def(ERR_NOCANONICNAME); + +/* + * Removes extra subscripts from result of op_indfnname. Similar to $QLENGTH and $QSUBSCRIPT. + * E.g. $name(@"x(6,7,8)",2): + * 1. Do op_indfnname and find ALL subscripts --> "x(6,7,8)" + * 2. Evaluate second argument --> 2 + * 3. Using the results of the previous two steps, do op_indfnname2 to remove extra subscripts --> "x(6,7)" + */ +void op_indfnname2(mval *finaldst, mval *depthval, mval *prechomp) +{ + int depth, dummy, start, subscripts; + char *c; + + MV_FORCE_STR(prechomp); + depth = MV_FORCE_INT(depthval); + if (depth < 0) + rts_error(VARLSTCNT(1) ERR_FNNAMENEG); + subscripts = depth + 1; + *finaldst = *prechomp; + if (subscripts > MAX_LVSUBSCRIPTS) + return; + if (!is_canonic_name(prechomp, &subscripts, &start, &dummy)) + { /* op_indfnname should have passed us a valid name */ + assert(FALSE); + rts_error(VARLSTCNT(4) ERR_NOCANONICNAME, 2, prechomp->str.len, prechomp->str.addr); + } + if (start) + { /* indeed have subscripts to remove */ + c = finaldst->str.addr + start - 1; + if ('"' == *c) + { + c--; + start--; + } + assert(('(' == *c) || (',' == *c)); + if ('(' == *c) + start--; + else + *c = ')'; + finaldst->str.len = start; + } + return; +} diff --git a/sr_port/op_indget1.c b/sr_port/op_indget1.c new file mode 100644 index 0000000..94e6068 --- /dev/null +++ b/sr_port/op_indget1.c @@ -0,0 +1,54 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +LITREF mval literal_null; + +/* [Used by SET] Get the value of a saved local or global variable. Return literal_null by default. */ +void op_indget1(uint4 indx, mval *dst) +{ + lv_val *lv; + opctype oc; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + oc = (TREF(glvn_pool_ptr))->slot[indx].sav_opcode; + if (OC_SAVLVN == oc) + { /* lvn */ + lv = op_rfrshlvn(indx, OC_PUTINDX); + op_fnget2((mval *)lv, (mval *)&literal_null, dst); + } else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */ + { /* gvn */ + op_rfrshgvn(indx, oc); + op_fngvget(dst); + } +} diff --git a/sr_port/op_indget2.c b/sr_port/op_indget2.c new file mode 100644 index 0000000..82c0bff --- /dev/null +++ b/sr_port/op_indget2.c @@ -0,0 +1,44 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "compiler.h" +#include "opcode.h" +#include "op.h" +#include "lv_val.h" +#include "mvalconv.h" +#include "glvn_pool.h" + +error_def(ERR_ORDER2); +error_def(ERR_VAREXPECTED); + +void op_indget2(mval *dst, uint4 indx) +{ + glvn_pool_entry *slot; + lv_val *lv; + opctype oc; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + slot = &((TREF(glvn_pool_ptr))->slot[indx]); + oc = slot->sav_opcode; + if (OC_SAVLVN == oc) + { /* lvn */ + lv = op_rfrshlvn(indx, OC_RFRSHLVN); /* funky opcode prevents UNDEF in rfrlvn */ + op_fnget1((mval *)lv, dst); + } else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */ + { /* gvn */ + op_rfrshgvn(indx, oc); + op_fngvget1(dst); + } + return; +} diff --git a/sr_port/op_indmerge2.c b/sr_port/op_indmerge2.c new file mode 100644 index 0000000..5627dd8 --- /dev/null +++ b/sr_port/op_indmerge2.c @@ -0,0 +1,54 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gdsroot.h" +#include "gdskill.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "compiler.h" +#include "opcode.h" +#include "op.h" +#include "lv_val.h" +#include "mvalconv.h" +#include "glvn_pool.h" +#include "merge_def.h" +#include "filestruct.h" +#include "gdscc.h" +#include "copy.h" +#include "jnl.h" +#include "buddy_list.h" +#include "hashtab_int4.h" /* needed for tp.h */ +#include "tp.h" +#include "gvname_info.h" +#include "op_merge.h" + +void op_indmerge2(uint4 indx) +{ + lv_val *lv; + opctype oc; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + if (OC_SAVLVN == (oc = SLOT_OPCODE(indx))) /* note assignment */ + { /* lvn */ + lv = op_rfrshlvn(indx, OC_PUTINDX); + op_merge_arg(MARG1_LCL, lv); + } else if (OC_NOOP != oc) + { /* gvn */ + op_rfrshgvn(indx, oc); + op_merge_arg(MARG1_GBL, NULL); + } + return; +} diff --git a/sr_port/op_indsavglvn.c b/sr_port/op_indsavglvn.c new file mode 100644 index 0000000..1e4bad9 --- /dev/null +++ b/sr_port/op_indsavglvn.c @@ -0,0 +1,121 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +error_def(ERR_VAREXPECTED); + +/* [Used by SET] Saves an indirect variable in the glvn pool and returns its index. Maintain in parallel with op_indsavlvn. */ +void op_indsavglvn(mval *target, uint4 slot, uint4 do_ref) +{ + icode_str indir_src; + int rval; + mstr *obj, object; + oprtype v, getdst; + opctype put_oc; + triple *s, *s1, *sub, *share; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + MV_FORCE_STR(target); + indir_src.str = target->str; + indir_src.code = do_ref ? indir_savglvn1 : indir_savglvn0; /* must differenitate the 2 code variants */ + if (NULL == (obj = cache_get(&indir_src))) + { + obj = &object; + comp_init(&target->str, &getdst); + share = maketriple(OC_SHARESLOT); + share->operand[0] = getdst; + switch (TREF(window_token)) + { + case TK_IDENT: + if (EXPR_FAIL != (rval = lvn(&v, OC_SAVLVN, NULL))) /* NOTE assignment */ + { + s = v.oprval.tref; + if (OC_SAVLVN != s->opcode) + { /* No subscripts. Still, let's do savindx */ + s = newtriple(OC_SAVLVN); + s->operand[0] = put_ilit(1); + s->operand[1] = v; + } + share->operand[1] = put_ilit(OC_SAVLVN); + dqins(s->exorder.bl, exorder, share); + } + break; + case TK_CIRCUMFLEX: + s1 = (TREF(curtchain))->exorder.bl; + if (EXPR_FAIL != (rval = gvn())) /* NOTE assignment */ + { + for (sub = (TREF(curtchain))->exorder.bl; sub != s1; sub = sub->exorder.bl) + { + put_oc = sub->opcode; + if ((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc) || (OC_GVEXTNAM == put_oc)) + break; + } + assert((OC_GVNAME == put_oc) || (OC_GVNAKED == put_oc) || (OC_GVEXTNAM == put_oc)); + if (!do_ref) + sub->opcode = OC_SAVGVN; /* steal gv bind action to suppress global reference */ + else + { /* or replicate it to cause bind to update $R before save */ + s = maketriple(OC_SAVGVN); + s->operand[0] = sub->operand[0]; + s->operand[1] = sub->operand[1]; + dqins(sub, exorder, s); + } + share->operand[1] = put_ilit(put_oc); + dqins(sub->exorder.bl, exorder, share); + } + break; + case TK_ATSIGN: + if (EXPR_FAIL != (rval = indirection(&v))) /* NOTE assignment */ + { + s = newtriple(OC_INDSAVGLVN); + s->operand[0] = v; + s1 = newtriple(OC_PARAMETER); + s->operand[1] = put_tref(s1); + s1->operand[0] = getdst; + s1->operand[1] = put_ilit(do_ref); /* pass along flag to control global reference */ + } + break; + default: + stx_error(ERR_VAREXPECTED); + rval = EXPR_FAIL; + break; + } + if (EXPR_FAIL == comp_fini(rval, obj, OC_RET, NULL, NULL, target->str.len)) + return; + indir_src.str.addr = target->str.addr; + cache_put(&indir_src, obj); + assert(NULL != cache_get(&indir_src)); + } + TREF(ind_result) = (mval *)(UINTPTR_T)slot; + comp_indr(obj); +} diff --git a/sr_port/op_indsavlvn.c b/sr_port/op_indsavlvn.c new file mode 100644 index 0000000..eecb408 --- /dev/null +++ b/sr_port/op_indsavlvn.c @@ -0,0 +1,93 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +error_def(ERR_VAREXPECTED); + +/* [Used by FOR] Same as op_indsavglvn, but only allows local variables. Compare with op_indlvadr. */ +void op_indsavlvn(mval *target, uint4 slot) +{ + icode_str indir_src; + int rval; + mstr *obj, object; + oprtype v, getdst; + triple *s, *share; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + MV_FORCE_STR(target); + indir_src.str = target->str; + indir_src.code = indir_savlvn; + if (NULL == (obj = cache_get(&indir_src))) + { + obj = &object; + comp_init(&target->str, &getdst); + share = maketriple(OC_SHARESLOT); + share->operand[0] = getdst; + switch (TREF(window_token)) + { + case TK_IDENT: + if (EXPR_FAIL != (rval = lvn(&v, OC_SAVLVN, NULL))) /* NOTE assignment */ + { + s = v.oprval.tref; + if (OC_SAVLVN != s->opcode) + { /* No subscripts. Still, let's do savindx */ + s = newtriple(OC_SAVLVN); + s->operand[0] = put_ilit(1); + s->operand[1] = v; + } + share->operand[1] = put_ilit(OC_SAVLVN); + dqins(s->exorder.bl, exorder, share); + } + break; + case TK_ATSIGN: + if (EXPR_FAIL != (rval = indirection(&v))) /* NOTE assignment */ + { + s = newtriple(OC_INDSAVLVN); + s->operand[0] = v; + s->operand[1] = getdst; + } + break; + default: + stx_error(ERR_VAREXPECTED); + rval = EXPR_FAIL; + break; + } + if (EXPR_FAIL == comp_fini(rval, obj, OC_RET, NULL, NULL, target->str.len)) + return; + indir_src.str.addr = target->str.addr; + cache_put(&indir_src, obj); + assert(NULL != cache_get(&indir_src)); + } + TREF(ind_result) = (mval *)(UINTPTR_T)slot; + comp_indr(obj); +} diff --git a/sr_port/op_litc.c b/sr_port/op_litc.c new file mode 100644 index 0000000..132b3b3 --- /dev/null +++ b/sr_port/op_litc.c @@ -0,0 +1,34 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "cmd_qlf.h" +#include "op.h" +#include +#include "stack_frame.h" +#include "stringpool.h" + +GBLREF stack_frame *frame_pointer; + +void op_litc(mval *dst, mval *src) +{ +# ifdef USHBIN_SUPPORTED + assert(DYNAMIC_LITERALS_ENABLED(frame_pointer->rvector)); + assert((char *)frame_pointer->literal_ptr == (char *)frame_pointer->rvector->literal_adr); + assert(MVAL_IN_RANGE(src, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* src is a literal mval */ + assert(!MVAL_IN_RANGE(dst, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* dst is NOT a literal */ + *dst = *src; + dst->str.addr += (INTPTR_T)(frame_pointer->rvector->literal_text_adr); +# else + assert(FALSE); +# endif + return; +} diff --git a/sr_port/op_rfrshgvn.c b/sr_port/op_rfrshgvn.c new file mode 100644 index 0000000..d5d59b9 --- /dev/null +++ b/sr_port/op_rfrshgvn.c @@ -0,0 +1,47 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "compiler.h" +#include "opcode.h" +#include "op.h" +#include "gtm_string.h" +#include "callg.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "glvn_pool.h" + +/* [Used by SET] */ +void op_rfrshgvn(uint4 indx, opctype oc) +{ + glvn_pool_entry *slot; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + slot = &(TREF(glvn_pool_ptr))->slot[indx]; + assert(MAX_ACTUALS >= slot->glvn_info.n); + switch (oc) + { + case OC_GVNAME: + callg((callgfnptr)op_gvname, (gparam_list *)&slot->glvn_info); + break; + case OC_GVNAKED: + callg((callgfnptr)op_gvnaked, (gparam_list *)&slot->glvn_info); + break; + case OC_GVEXTNAM: + callg((callgfnptr)op_gvextnam, (gparam_list *)&slot->glvn_info); + break; + default: + GTMASSERT; + } +} diff --git a/sr_port/op_rfrshlvn.c b/sr_port/op_rfrshlvn.c new file mode 100644 index 0000000..483f704 --- /dev/null +++ b/sr_port/op_rfrshlvn.c @@ -0,0 +1,86 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +GBLREF bool undef_inhibit; +GBLREF symval *curr_symval; + +error_def(ERR_UNDEF); + +/* [Used by FOR, SET and $ORDER()] Looks up a saved local variable. */ +lv_val *op_rfrshlvn(uint4 indx, opctype oc) +{ + glvn_pool_entry *slot; + ht_ent_mname *tabent; + mname_entry targ_key; + lv_val *lv; + lvname_info *lvn_info; + unsigned char buff[512], *end; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + slot = &(TREF(glvn_pool_ptr))->slot[indx]; + assert(OC_SAVLVN == slot->sav_opcode); + targ_key.var_name = slot->lvname->str; + COMPUTE_HASH_MNAME(&targ_key); + targ_key.marked = FALSE; + if (add_hashtab_mname_symval(&curr_symval->h_symtab, &targ_key, NULL, &tabent)) + lv_newname(tabent, curr_symval); + lvn_info = (lvname_info *)&slot->glvn_info; + lvn_info->start_lvp = (lv_val *)tabent->value; + switch (oc) + { + case OC_RFRSHLVN: /* no UNDEF for $ORDER()/$GET() from srchindx nor bogus opcode, so borrow "impossible" opcode */ + return (lv_val *)callg((callgfnptr)op_srchindx, (gparam_list *)lvn_info); + break; + case OC_PUTINDX: + lv = (lv_val *)callg((callgfnptr)op_putindx, (gparam_list *)lvn_info); + break; + case OC_SRCHINDX: + lv = (lv_val *)callg((callgfnptr)op_srchindx, (gparam_list *)lvn_info); + if (NULL == lv) + { /* This path is currently only used by FOR. Issue UNDEF error even if NOUNDEF is enabled. */ + end = format_key_mvals(buff, SIZEOF(buff), lvn_info); + rts_error(VARLSTCNT(4) ERR_UNDEF, 2, end - buff, buff); + assert(FALSE); + } + break; + case OC_M_SRCHINDX: + /* not currently used */ + lv = (lv_val *)callg((callgfnptr)op_m_srchindx, (gparam_list *)lvn_info); + break; + default: + GTMASSERT; + } + assert(lv); + return lv; +} diff --git a/sr_port/op_savgvn.c b/sr_port/op_savgvn.c new file mode 100644 index 0000000..ac57ee6 --- /dev/null +++ b/sr_port/op_savgvn.c @@ -0,0 +1,68 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +GBLREF spdesc stringpool; + +/* [Used by SET] Saves a global in the glvn pool and returns its index. */ +void op_savgvn(UNIX_ONLY_COMMA(int argcnt) mval *val_arg, ...) +{ + va_list var; + mval *m, *key; + glvn_pool_entry *slot; + gparam_list *gvn_info; + int i; + VMS_ONLY(int argcnt;) + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + VAR_START(var, val_arg); + VMS_ONLY(va_count(argcnt)); + ENSURE_GLVN_POOL_SPACE(argcnt); + GET_GLVN_POOL_STATE(slot, m); + gvn_info = (gparam_list *)&slot->glvn_info; + gvn_info->n = argcnt; + key = val_arg; + for (i = 0; ; ) + { + *m = *key; + gvn_info->arg[i] = m; + (TREF(glvn_pool_ptr))->mval_top++; + if (MV_IS_STRING(m) && !IS_IN_STRINGPOOL(m->str.addr, m->str.len)) + s2pool(&m->str); + m++; + if (++i < argcnt) + key = va_arg(var, mval *); + else + break; + } +} diff --git a/sr_port/op_savlvn.c b/sr_port/op_savlvn.c new file mode 100644 index 0000000..b07f5c1 --- /dev/null +++ b/sr_port/op_savlvn.c @@ -0,0 +1,79 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +GBLREF spdesc stringpool; + +/* [Used by FOR, SET and $ORDER()] Saves a local in the glvn pool and returns its index. */ +void op_savlvn(UNIX_ONLY_COMMA(int argcnt) lv_val *start, ...) +{ + glvn_pool_entry *slot; + int i; + VMS_ONLY(int argcnt;) + lvname_info *lvn_info; + mident *lvent; + mname_entry *targ_key; + mval *m, *key; + unsigned char *c, *ptr; + va_list var; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + VAR_START(var, start); + VMS_ONLY(va_count(argcnt)); + ENSURE_GLVN_POOL_SPACE(argcnt); + /* Get variable name and store it in the stringpool. */ + GET_GLVN_POOL_STATE(slot, m); + assert(OC_SAVLVN == slot->sav_opcode); + ENSURE_STP_FREE_SPACE(SIZEOF(mident_fixed)); + slot->lvname = m; + m->mvtype = MV_STR; /* needs to be protected if garbage collection happens during s2pool below */ + lvent = &slot->lvname->str; + ptr = stringpool.free; + c = format_lvname(start, ptr, SIZEOF(mident_fixed)); + lvent->addr = (char *)ptr; + lvent->len = (char *)c - (char *)ptr; + stringpool.free = c; + m++; + (TREF(glvn_pool_ptr))->mval_top++; + lvn_info = (lvname_info *)&slot->glvn_info; + lvn_info->total_lv_subs = argcnt--; + for (i = 0; i < argcnt; i++, m++) + { /* now all the pieces of the key */ + key = va_arg(var, mval *); + *m = *key; + lvn_info->lv_subs[i] = m; + (TREF(glvn_pool_ptr))->mval_top++; + if (MV_IS_STRING(m) && !IS_IN_STRINGPOOL(m->str.addr, m->str.len)) + s2pool(&m->str); + } +} diff --git a/sr_port/op_shareslot.c b/sr_port/op_shareslot.c new file mode 100644 index 0000000..5b4825c --- /dev/null +++ b/sr_port/op_shareslot.c @@ -0,0 +1,43 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +void op_shareslot(uint4 indx, opctype opcode) +{ + glvn_pool_entry *slot; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + (TREF(glvn_pool_ptr))->share_slot = indx; + slot = &(TREF(glvn_pool_ptr))->slot[indx]; + slot->sav_opcode = opcode; +} diff --git a/sr_port/op_stoglvn.c b/sr_port/op_stoglvn.c new file mode 100644 index 0000000..284fcfa --- /dev/null +++ b/sr_port/op_stoglvn.c @@ -0,0 +1,52 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "lv_val.h" +#include "toktyp.h" +#include "compiler.h" +#include "opcode.h" +#include "indir_enum.h" +#include "cache.h" +#include "op.h" +#include +#include "valid_mname.h" +#include "gtm_string.h" +#include "cachectl.h" +#include "gtm_text_alloc.h" +#include "callg.h" +#include "mdq.h" +#include "stack_frame.h" +#include "stringpool.h" +#include "mv_stent.h" +#include "min_max.h" +#include "glvn_pool.h" + +/* [Used by SET] Store a value in a saved local or global variable. */ +void op_stoglvn(uint4 indx, mval *value) +{ + lv_val *lv; + opctype oc; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + oc = (TREF(glvn_pool_ptr))->slot[indx].sav_opcode; + if (OC_SAVLVN == oc) + { /* lvn */ + lv = op_rfrshlvn(indx, OC_PUTINDX); + lv->v = *value; + } else if (OC_NOOP != oc) /* if indirect error blew set up, skip this */ + { /* gvn */ + op_rfrshgvn(indx, oc); + op_gvput(value); + } +} diff --git a/sr_port/op_stolitc.c b/sr_port/op_stolitc.c new file mode 100644 index 0000000..45f9bbe --- /dev/null +++ b/sr_port/op_stolitc.c @@ -0,0 +1,32 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "cmd_qlf.h" +#include "op.h" +#include +#include "stack_frame.h" +#include "stringpool.h" + +GBLREF stack_frame *frame_pointer; + +void op_stolitc(mval *val) +{ +# ifdef USHBIN_SUPPORTED + assert(DYNAMIC_LITERALS_ENABLED(frame_pointer->rvector)); + assert((char *)frame_pointer->literal_ptr == (char *)frame_pointer->rvector->literal_adr); + assert(!MVAL_IN_RANGE(val, frame_pointer->literal_ptr, frame_pointer->rvector->literal_len)); /* val is NOT a literal */ + val->str.addr += (INTPTR_T)(frame_pointer->rvector->literal_text_adr); +# else + assert(FALSE); +# endif + return; +} diff --git a/sr_port/preemptive_db_clnup.c b/sr_port/preemptive_db_clnup.c new file mode 100644 index 0000000..5492f18 --- /dev/null +++ b/sr_port/preemptive_db_clnup.c @@ -0,0 +1,145 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" /* for the RESET_GV_TARGET macro which in turn uses "memcmp" */ + +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "probe.h" +#include "gdsfhead.h" +#include "error.h" +#include "gdskill.h" +#include "filestruct.h" +#include "jnl.h" +#include "buddy_list.h" /* needed for tp.h */ +#include "gdscc.h" +#include "hashtab_int4.h" /* needed for tp.h */ +#include "tp.h" +#include "interlock.h" +#include "preemptive_db_clnup.h" +#include "add_inter.h" +#include "gtmimagename.h" +#include "t_abort.h" +#include "dpgbldir.h" + +GBLREF gv_namehead *reset_gv_target; +GBLREF gv_namehead *gv_target; +GBLREF sgmnt_addrs *kip_csa; +GBLREF uint4 dollar_tlevel; +GBLREF sgmnt_addrs *cs_addrs; +GBLREF sgmnt_data_ptr_t cs_data; +GBLREF sgm_info *first_sgm_info; +GBLREF boolean_t need_kip_incr; +GBLREF uint4 update_trans; + +/* container for all the common chores that need to be performed on error conditions */ + +#define CLEAR_CSE(GVNH) \ +{ \ + gv_namehead *gvnh; \ + srch_blk_status *s; \ + \ + gvnh = GVNH; \ + if (NULL != gvnh) \ + { \ + for (s = &gvnh->hist.h[0]; s->blk_num; s++) \ + s->cse = NULL; \ + } \ +} + +void preemptive_db_clnup(int preemptive_severe) +{ + sgmnt_addrs *csa; + sgm_info *si; + gd_region *r_top, *reg; + gd_addr *addr_ptr; + + if (!dollar_tlevel && update_trans) + { /* It's possible we hit an error in the middle of an update, at which point we have + * a valid clue and non-NULL cse. However, this causes problems for subsequent + * transactions (see comment in t_begin). In particular we could end up pinning buffers + * unnecessarily. So clear the cse of any histories that may have been active during the update. + */ + CLEAR_CSE(gv_target); + if ((NULL != gv_target) && (NULL != gv_target->gd_csa)) + { + CLEAR_CSE(gv_target->gd_csa->dir_tree); + GTMTRIG_ONLY(CLEAR_CSE(gv_target->gd_csa->hasht_tree)); + } + } + if (INVALID_GV_TARGET != reset_gv_target) + { + if (SUCCESS != preemptive_severe && INFO != preemptive_severe) + { + /* We know of a few cases in Unix where gv_target and gv_currkey could be out of sync at this point. + * a) If we are inside trigger code which in turn does an update that does + * reads of ^#t global and ends up in a restart. This restart would + * in turn do a rts_error(TPRETRY) which would invoke mdb_condition_handler + * that would in turn invoke preemptive_db_clnup which invokes this macro. + * In this tp restart case though, it is ok for gv_target and gv_currkey + * to be out of sync because they are going to be reset by tp_clean_up anyways. + * So skip the dbg-only in-sync check. + * b) If we are in gvtr_init reading the ^#t global and detect an error (e.g. TRIGINVCHSET) + * gv_target after the reset would be pointing to a regular global whereas gv_currkey + * would be pointing to ^#t. It is ok to be out-of-sync since in this case, we expect + * mdb_condition_handler to be calling us. That has code to reset gv_currkey (and + * cs_addrs/cs_data etc.) to reflect gv_target (i.e. get them back in sync). + * Therefore in Unix we pass SKIP_GVT_GVKEY_CHECK to skip the gvtarget/gvcurrkey out-of-sync check + * in RESET_GV_TARGET. In VMS we pass DO_GVT_GVKEY_CHECK as we dont yet know of an out-of-sync situation. + */ + RESET_GV_TARGET(UNIX_ONLY(SKIP_GVT_GVKEY_CHECK) VMS_ONLY(DO_GVT_GVKEY_CHECK)); + } + } + need_kip_incr = FALSE; /* in case we got an error in t_end (e.g. GBLOFLOW), dont want this global variable to get + * carried over to the next non-TP transaction that this process does (e.g. inside an error trap). + */ + if (dollar_tlevel) + { + for (si = first_sgm_info; si != NULL; si = si->next_sgm_info) + { + if (NULL != si->kip_csa) + { + csa = si->tp_csa; + assert(si->tp_csa == si->kip_csa); + CAREFUL_DECR_KIP(csa->hdr, csa, si->kip_csa); + } + } + } else if (NULL != kip_csa && (NULL != kip_csa->hdr) && (NULL != kip_csa->nl)) + CAREFUL_DECR_KIP(kip_csa->hdr, kip_csa, kip_csa); + if (IS_DSE_IMAGE) + { /* Release crit on any region that was obtained for the current erroring DSE operation. + * Take care NOT to release crits obtained by a previous CRIT -SEIZE command. + */ + for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr)) + { + for (reg = addr_ptr->regions, r_top = reg + addr_ptr->n_regions; reg < r_top; reg++) + { + if (reg->open && !reg->was_open) + { + csa = &FILE_INFO(reg)->s_addrs; + assert(csa->hold_onto_crit || !csa->dse_crit_seize_done); + assert(!csa->hold_onto_crit || csa->now_crit); + if (csa->now_crit && (!csa->hold_onto_crit || !csa->dse_crit_seize_done)) + { + rel_crit(reg); + csa->hold_onto_crit = FALSE; + t_abort(reg, csa); /* cancel mini-transaction if any in progress */ + } + } + } + } + } +} diff --git a/sr_port/preemptive_db_clnup.h b/sr_port/preemptive_db_clnup.h new file mode 100644 index 0000000..bacb9d0 --- /dev/null +++ b/sr_port/preemptive_db_clnup.h @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef PREEMPTIVE_DB_CLNUP_INCLUDED +#define PREEMPTIVE_DB_CLNUP_INCLUDED + +void preemptive_db_clnup(int preemptive_severe); + +#endif /* PREEMPTIVE_DB_CLNUP_INCLUDED */ diff --git a/sr_port/reorg_funcs.c b/sr_port/reorg_funcs.c new file mode 100644 index 0000000..2f5807d --- /dev/null +++ b/sr_port/reorg_funcs.c @@ -0,0 +1,184 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "cdb_sc.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gdsblkops.h" +#include "gdskill.h" +#include "gdscc.h" +#include "copy.h" +#include "mu_reorg.h" +#include "util.h" +#include "min_max.h" + +GBLREF sgmnt_data_ptr_t cs_data; +GBLREF unsigned int t_tries; + +#ifdef DEBUG +# define DBG_VERIFY_ACCESS(PTR) \ +{ /* Ensure accessible pointer (no SIG-11) */ \ + unsigned char c; \ + \ + c = *(unsigned char *)(PTR); \ +} +#else +# define DBG_VERIFY_ACCESS(PTR) +#endif + +/* + * Get length of the global variable name contained in the key starting at KEY_BASE. + * NOTE: If keys reside outside a GDS block (e.g. in cs_data), allocated buffer should have capacity at least MAX_KEY_SZ. + * Input: + * BLK_BASE := if non-NULL, base of current block + * if NULL, it means we're dealing with a key that is not within a database block + * KEY_BASE := starting address of key + * Output: + * GBLNAME_LEN := length of global variable name + */ +int get_gblname_len(sm_uc_ptr_t blk_base, sm_uc_ptr_t key_base) +{ + sm_uc_ptr_t rPtr1, blk_end; + + blk_end = (NULL != blk_base) ? (blk_base + cs_data->blk_size) : (key_base + MAX_KEY_SZ); + DBG_VERIFY_ACCESS(blk_end - 1); + for (rPtr1 = key_base; ; ) + { + if (blk_end <= rPtr1) + break; + if (KEY_DELIMITER == *rPtr1++) + break; + } + return (int)(rPtr1 - key_base); +} + +/* + * Get length of the key starting at KEY_BASE. + * NOTE: If keys reside outside a GDS block (e.g. in cs_data), allocated buffer should have capacity at least MAX_KEY_SZ. + * Currently, all get_key_len() calls take a key in shared memory; the only "allocated buffer" is csd->reorg_restart_key. + * Input: + * BLK_BASE := if non-NULL, base of current block + * if NULL, it means we're dealing with a key that is not within a database block + * KEY_BASE := starting address of key + * Output: + * KEY_LEN := length of key, including 2 null bytes at the end + */ +int get_key_len(sm_uc_ptr_t blk_base, sm_uc_ptr_t key_base) +{ + sm_uc_ptr_t rPtr1, blk_end; + + blk_end = (NULL != blk_base) ? (blk_base + cs_data->blk_size) : (key_base + MAX_KEY_SZ); + DBG_VERIFY_ACCESS(blk_end - 1); + for (rPtr1 = key_base; ; ) + { + if (blk_end <= rPtr1 + 1) + break; + if ((KEY_DELIMITER == *rPtr1++) && (KEY_DELIMITER == *rPtr1)) + break; + } + return (int)(rPtr1 + 1 - key_base); +} + +/* + * Get compression count of SECOND_KEY with respect to FIRST_KEY. + * NOTE: Each key should reside in a private buffer with capacity at least MAX_KEY_SZ. + */ +int get_cmpc(sm_uc_ptr_t first_key, sm_uc_ptr_t second_key) +{ + sm_uc_ptr_t rPtr1, rPtr2; + int cmpc; + + DBG_VERIFY_ACCESS(first_key + MAX_KEY_SZ - 1); + DBG_VERIFY_ACCESS(second_key + MAX_KEY_SZ - 1); + /* We don't expect the inputs to be equal, hence the assert. It shouldn't matter, though. If the keys' contents are equal, + * we return an indeterminate value between the key length and MAX_KEY_SZ. The value depends on the garbage bytes past the + * terminating null bytes. But we don't care because we don't compress a key off an identical key in the final retry. + */ + assert(first_key != second_key); + for (rPtr1 = first_key, rPtr2 = second_key, cmpc = 0; cmpc < MAX_KEY_SZ; cmpc++) + { + if (*rPtr1++ != *rPtr2++) + break; + } + return cmpc; +} + +/* + * Copy record info (record size and key) out of a block. + * Input: + * LEVEL := level of current block + * BLK_BASE := base of current block + * REC_BASE := starting address of record in current block + * KEY := previous key; first KEY_CMPC bytes are retained in output KEY + * Output: + * STATUS := status of read + * REC_SIZE := record size + * KEY_CMPC := key compression count + * KEY_LEN := key length + * KEY := local copy of key copied out of record + */ +enum cdb_sc read_record(int *rec_size_ptr, int *key_cmpc_ptr, int *key_len_ptr, sm_uc_ptr_t key, + int level, sm_uc_ptr_t blk_base, sm_uc_ptr_t rec_base) +{ + sm_uc_ptr_t rPtr1, rPtr2, blk_end, rPtr1_end, rPtr2_end; + unsigned short temp_ushort; + int key_cmpc, rec_size, key_len; + boolean_t invalid; + + blk_end = blk_base + cs_data->blk_size; + DBG_VERIFY_ACCESS(blk_end - 1); + if (blk_end <= (rec_base + SIZEOF(rec_hdr))) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_blkmod; + } + GET_USHORT(temp_ushort, &(((rec_hdr_ptr_t)rec_base)->rsiz)); + rec_size = temp_ushort; + key_cmpc = EVAL_CMPC((rec_hdr_ptr_t)rec_base); + if ((0 != level) && (BSTAR_REC_SIZE == rec_size)) + { + key_len = 0; + *key_cmpc_ptr = key_cmpc; + *rec_size_ptr = rec_size; + *key_len_ptr = key_len; + return cdb_sc_starrecord; + } + rPtr1_end = key + MAX_KEY_SZ - 1; + DBG_VERIFY_ACCESS(rPtr1_end); + rPtr2_end = MIN(blk_end - 1, rec_base + SIZEOF(rec_hdr) + MAX_KEY_SZ - 1); + for (rPtr1 = key + key_cmpc, rPtr2 = rec_base + SIZEOF(rec_hdr); (rPtr1 < rPtr1_end) && (rPtr2 < rPtr2_end); ) + { + if ((KEY_DELIMITER == (*rPtr1++ = *rPtr2++)) && (KEY_DELIMITER == *rPtr2)) /* note assignment */ + break; + } + *rPtr1++ = *rPtr2++; + key_len = (int)(rPtr2 - rec_base - SIZEOF(rec_hdr)); + invalid = INVALID_RECORD(level, rec_size, key_len, key_cmpc); + if (invalid || ((KEY_DELIMITER != *(rPtr1 - 1)) || (KEY_DELIMITER != *(rPtr1 - 2)))) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_blkmod; + } + *key_cmpc_ptr = key_cmpc; + *rec_size_ptr = rec_size; + *key_len_ptr = key_len; + return cdb_sc_normal; +} diff --git a/sr_port/trim.mpt b/sr_port/trim.mpt new file mode 100644 index 0000000..b5604d0 --- /dev/null +++ b/sr_port/trim.mpt @@ -0,0 +1,24 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; ; +; Copyright 2012 Fidelity Information Services, Inc. ; +; ; +; This source code contains the intellectual property ; +; of its copyright holder(s), and is made available ; +; under a license. If you do not know the terms of ; +; the license, please stop and do not read further. ; +; ; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +%TRIM ; routine to strip of leading and trailing spaces/tabs + for quit:$zeof read line write !,$$FUNC(line),! + quit + +FUNC(s) quit $$L($$R(s)) + +L(s) new i,l,tmp + set l=$length(s) + for set tmp=$extract(s,$increment(i)) quit:" "'=tmp&($c(9)'=tmp)!'$length(tmp) + quit $extract(s,i,$length(s)) + +R(s) new i,l,tmp + set i=$length(s)+1 for set tmp=$extract(s,$increment(i,-1)) quit:" "'=tmp&($c(9)'=tmp)!'i + quit $extract(s,1,i) diff --git a/sr_port/underr_strict.c b/sr_port/underr_strict.c new file mode 100644 index 0000000..33b895d --- /dev/null +++ b/sr_port/underr_strict.c @@ -0,0 +1,33 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include + +#include "lv_val.h" +#include "undx.h" + +error_def(ERR_UNDEF); + +mval *underr_strict(mval *start, ...) +{ + mident_fixed name; + unsigned char *end; + va_list var; + + /* Variation of underr in which we ignore NOUNDEF */ + va_start (var, start); + end = format_lvname((lv_val *)start, (uchar_ptr_t)name.c, SIZEOF(name)); + va_end(var); + rts_error(VARLSTCNT(4) ERR_UNDEF, 2, ((char *)end - name.c), name.c); + return (mval *)NULL; /* To keep compiler happy */ +} diff --git a/sr_unix/CMakeLists.txt b/sr_unix/CMakeLists.txt new file mode 100644 index 0000000..9f3b229 --- /dev/null +++ b/sr_unix/CMakeLists.txt @@ -0,0 +1,788 @@ +################################################################# +# # +# Copyright 2012, 2013 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +# CMake 2.8.4 introduced LINK_DEPENDS target property +# CMake 2.8.4 introduced generator expressions in custom commands +# CMake 2.8.5 introduced use of C compiler as the assembler +cmake_minimum_required(VERSION 2.8.5) +project(GTM C ASM) + +# Max optimization level is -O2 +get_property(languages GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(lang ${languages}) + get_property(flags CACHE CMAKE_${lang}_FLAGS_RELEASE PROPERTY VALUE) + if("${flags}" MATCHES "-O[3-9]") + string(REGEX REPLACE "-O[3-9]" "-O2" flags "${flags}") + set_property(CACHE CMAKE_${lang}_FLAGS_RELEASE PROPERTY VALUE "${flags}") + endif() +endforeach() + +# Defaults +set(version GTM_RELEASE_VERSION) +if("${version}" STREQUAL "") + set(version V9.9-0) +endif() + +# If CMAKE_BUILD_TYPE is not defined make it a Release build +if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE) +endif() + +# If it's a debug build make sure GT.M uses all of its debug options +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG") + +set(install_permissions_script + OWNER_READ OWNER_EXECUTE OWNER_WRITE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) + +set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG) + +# Only IA64 and x86_64 architectures use this option +set(gen_xfer_desc 0) + +# Platform specific libs +set(gtm_osarch_libs "") + +# Define these ahead of establishing platforms +set(gt_src_list) +set(sources_used "") +set(extralibs "") +set(is_encryption_supported 1) +set(libmumpsrestoreregex "") +message("--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}") +# Establish platform +# Except for Solaris, CMAKE_COMPILER_IS_GNUCC is true +if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") + include(sr_linux/platform.cmake) +elseif("${CMAKE_SYSTEM_NAME}" MATCHES "HP-UX") + include(sr_hpux/platform.cmake) +elseif("${CMAKE_SYSTEM_NAME}" MATCHES "AIX") + include(sr_aix/platform.cmake) +elseif("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS") + include(sr_sun/platform.cmake) +else() + message(FATAL_ERROR "--> OS = ${CMAKE_SYSTEM_NAME} / ARCH = ${CMAKE_SYSTEM_PROCESSOR}") +endif() + +# Choose where to get bootstrap sources. +set(GTM_DIST "" CACHE PATH "Existing GT.M Distribution") +if(GTM_DIST) + # Bootstrap using already-installed mumps. + message(STATUS "Using existing gtm_dist=${GTM_DIST} to generate sources.") + set(gen_bootstrap 1) + set(gen_bootstrap_dist "${GTM_DIST}") + set(gen_bootstrap_mumps "${GTM_DIST}/mumps") + set(gen_bootstrap_depend "${gen_bootstrap_mumps}") +else() + # Bootstrap using pre-generated bootstrap sources. + # We generate them again only for comparison. + set(gen_bootstrap 0) + set(gen_bootstrap_dist "${GTM_BINARY_DIR}") + set(gen_bootstrap_mumps "$") + set(gen_bootstrap_depend mumps) +endif() + +set(GTM_INSTALL_DIR lib/fis-gtm/${version}_${arch} CACHE STRING "Install directory (under CMAKE_PREFIX_PATH if relative)") +if(NOT GTM_INSTALL_DIR) + set(GTM_INSTALL_DIR .) +endif() + +#----------------------------------------------------------------------------- + +# Source files are organized into subdirectories named by platform. +# Store in 'gt_src_list' a list of directory names selected and +# ordered based on the target platform. A given source file name may +# appear in multiple directories but only the instance found earliest +# in the search path will be used. Later instances of the same source +# file name will be ignored. +list(APPEND gt_src_list + sr_unix_gnp + sr_unix_cm + sr_unix + sr_port_cm + sr_port + ) + +# Collect the source file names belonging to each directory. Store +# the full path to a directory in 'source_dir_${d}' and the list of +# source file names in the directory in 'sources_${d}'. +foreach(d ${gt_src_list}) + set(source_dir_${d} ${GTM_SOURCE_DIR}/${d}) + file(GLOB sources_${d} RELATIVE ${source_dir_${d}} + ${d}/*.c ${d}/*.s ${d}/*.si) +endforeach() +if(gen_bootstrap) + # Prefer generated sources over all other locations. + set(gt_src_list gen ${gt_src_list}) + set(source_dir_gen ${GTM_BINARY_DIR}/gen) + # Hard-code list since we cannot glob files that do not exist. + set(sources_gen cmerrors_ctl.c cmierrors_ctl.c gdeerrors_ctl.c merrors_ctl.c ttt.c) +endif() + +# The C preprocessor include search path consists of every source +# directory ordered by 'gt_src_list'. +set(includes) +foreach(d ${gt_src_list}) + list(APPEND includes ${source_dir_${d}}) +endforeach() +include_directories(${includes}) +# We generate some uniquely-named headers in the top of the build tree. +include_directories(${GTM_BINARY_DIR}) + +# Function to select the first instance of a given source file name +# found in the ordered 'gt_src_list' search path. +function(select_file src_var name) + set(found "") + foreach(d ${gt_src_list}) + set(src "${source_dir_${d}}/${name}") + if(EXISTS "${src}") + set(found "${src}") + break() + endif() + endforeach() + if(NOT found) + message(FATAL_ERROR "Cannot find \"${name}\" as ${ARGN}") + endif() + set("${src_var}" "${found}" PARENT_SCOPE) +endfunction() + +# Macro to search directories ordered by 'gt_src_list' for a given +# list of source file names, assign them to a target, and exclude the +# source file names from inclusion in libmumps. +macro(set_source_list target) + foreach(name ${ARGN}) + set(src "") + foreach(d ${gt_src_list}) + if(";${sources_${d}};" MATCHES ";(${name}\\.(c|s|si));") + set(fname ${CMAKE_MATCH_1}) + set(src ${d}/${fname}) + set("source_used_${fname}" 1) + list(APPEND sources_used ${source_dir_${d}}/${fname}) + if(NOT "${libmumpsrestoreregex}" STREQUAL "") + if(";${name};" MATCHES ";(${libmumpsrestoreregex});") + set("source_used_${fname}" 0) + endif() + endif() + break() + endif() + endforeach() + if(src) + list(APPEND ${target}_SOURCES ${src}) + else() + message(FATAL_ERROR "No source \"${name}\" available!") + endif() + endforeach() +endmacro() + +# Macro like set_source_list but that loads the list of source file +# names from a file. +macro(load_source_list target listfile) + file(STRINGS "${listfile}" names) + set_source_list(${target} ${names}) +endmacro() + +#----------------------------------------------------------------------------- + +# Assign sources to libraries. +load_source_list(libcmisockettcp sr_unix_gnp/libcmisockettcp.list) +load_source_list(libdbcertify sr_unix/libdbcertify.list) +load_source_list(libdse sr_unix/libdse.list) +load_source_list(libgnpclient sr_unix_gnp/libgnpclient.list) +load_source_list(libgnpserver sr_unix_gnp/libgnpserver.list) +load_source_list(libgtcm sr_unix_cm/libgtcm.list) +load_source_list(liblke sr_unix/liblke.list) +load_source_list(libmupip sr_unix/libmupip.list) +load_source_list(libstub sr_unix/libstub.list) +if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") + load_source_list(libgtmrpc sr_sun/libgtmrpc.list) +endif() + +# Assign sources to executables. +set_source_list(gtm_threadgbl_deftypes gtm_threadgbl_deftypes) +set_source_list(dbcertify dbcertify dbcertify_cmd) +set_source_list(dse dse dse_cmd) +set_source_list(ftok ftok) +set_source_list(geteuid geteuid) +set_source_list(gtcm_gnp_server gtcm_gnp_server) +set_source_list(gtcm_pkdisp gtcm_pkdisp) +set_source_list(gtcm_play gtcm_play omi_srvc_xct) +set_source_list(gtcm_server gtcm_main omi_srvc_xct) +set_source_list(gtcm_shmclean gtcm_shmclean) +set_source_list(gtmsecshr gtmsecshr_wrapper) +set_source_list(gtmsecshr_real gtmsecshr) +set_source_list(libgtmcrypt gtmcrypt_ref gtmcrypt_pk_ref gtmcrypt_dbk_ref) +set_source_list(libgtmshr gtm_main) +set_source_list(lke lke lke_cmd) +set_source_list(maskpass maskpass) +set_source_list(mumps gtm) +set_source_list(mupip mupip mupip_cmd) +set_source_list(semstat2 semstat2) +if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") + set_source_list(gtm_svc gtm_svc gtm_rpc_init gtm_dal_svc) +endif() + +#----------------------------------------------------------------------------- +# libmumps gets leftover sources, so compute the remaining list. +set(source_used_dtgbldir.c 1) # exclude unused source +set(libmumps_SOURCES "") +foreach(d ${gt_src_list}) + foreach(s ${sources_${d}}) + if(NOT source_used_${s}) + list(APPEND libmumps_SOURCES ${d}/${s}) + set(source_used_${s} 1) + list(APPEND sources_used ${source_dir_${d}}/${s}) + endif() + endforeach() +endforeach() + +#----------------------------------------------------------------------------- +# Generate files depending on gtm + +# Copy generation routines to a working directory. +foreach(m chk2lev.m chkop.m gendash.m genout.m loadop.m loadvx.m msg.m tttgen.m tttscan.m) + add_custom_command( + OUTPUT gen/${m} + DEPENDS ${GTM_SOURCE_DIR}/sr_port/${m} + COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/sr_port/${m} ${GTM_BINARY_DIR}/gen/${m} + ) +endforeach() + +foreach(f ttt.txt opcode_def.h vxi.h) + select_file(src ${f}) + list(APPEND tttfiles ${src}) +endforeach() +set(mumps_ttt_args -run tttgen ${tttfiles}) +add_custom_command( + OUTPUT gen/ttt.c + DEPENDS ${tttfiles} + gen/chk2lev.m gen/chkop.m gen/gendash.m gen/genout.m gen/loadop.m + gen/loadvx.m gen/tttgen.m gen/tttscan.m + ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake ${gen_bootstrap_depend} + WORKING_DIRECTORY ${GTM_BINARY_DIR}/gen + COMMAND ${CMAKE_COMMAND} + -D gtm_dist=${gen_bootstrap_dist} + -D gtmroutines=. + -D mumps=${gen_bootstrap_mumps} + -D "args=${mumps_ttt_args}" + -D output_file=ttt.log + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + VERBATIM + ) +list(APPEND gen_bootstrap_files gen/ttt.c) + +set(gen_merrors_extra gen/merrors_ansi.h) +foreach(msg + sr_port/cmerrors.msg + sr_port/gdeerrors.msg + sr_port/merrors.msg + sr_unix_gnp/cmierrors.msg + ) + get_filename_component(name ${msg} NAME_WE) + set(mumps_msg_args -run msg ${GTM_SOURCE_DIR}/${msg} unix) + set(outputs gen/${name}_ctl.c ${gen_${name}_extra}) + add_custom_command( + OUTPUT ${outputs} + DEPENDS gen/msg.m ${GTM_SOURCE_DIR}/${msg} + ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake ${gen_bootstrap_depend} + WORKING_DIRECTORY ${GTM_BINARY_DIR}/gen + COMMAND ${CMAKE_COMMAND} + -D gtm_dist=${gen_bootstrap_dist} + -D gtmroutines=. + -D mumps=${gen_bootstrap_mumps} + -D "args=${mumps_msg_args}" + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + VERBATIM + ) + list(APPEND gen_bootstrap_files ${outputs}) +endforeach() + +add_custom_target(gen_bootstrap ALL DEPENDS ${gen_bootstrap_files}) + +#----------------------------------------------------------------------------- + +if(gen_xfer_desc) + list(SORT sources_used) + set(CMAKE_CONFIGURABLE_FILE_CONTENT "") + foreach(src ${sources_used}) + set(CMAKE_CONFIGURABLE_FILE_CONTENT "${CMAKE_CONFIGURABLE_FILE_CONTENT}${src}\n") + endforeach() + configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in ${GTM_BINARY_DIR}/sources.list) + add_custom_command( + OUTPUT xfer_desc.i + WORKING_DIRECTORY ${GTM_BINARY_DIR} + DEPENDS ${GTM_SOURCE_DIR}/sr_unix/gen_xfer_desc.cmake + ${GTM_BINARY_DIR}/sources.list + COMMAND ${CMAKE_COMMAND} + -D CMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -D "arch=${arch}" + -D "includes=${includes}" + -P ${GTM_SOURCE_DIR}/sr_unix/gen_xfer_desc.cmake + VERBATIM + ) + add_custom_target(gen_xfer_desc DEPENDS xfer_desc.i) + if(gen_bootstrap) + add_dependencies(gen_xfer_desc gen_bootstrap) + endif() +endif() + +#----------------------------------------------------------------------------- + +add_executable(gtm_threadgbl_deftypes ${gtm_threadgbl_deftypes_SOURCES}) +if(gen_xfer_desc) + add_dependencies(gtm_threadgbl_deftypes gen_xfer_desc) +elseif(gen_bootstrap) + add_dependencies(gtm_threadgbl_deftypes gen_bootstrap) +endif() + +add_custom_command( + OUTPUT gtm_threadgbl_deftypes.h + DEPENDS gtm_threadgbl_deftypes + COMMAND gtm_threadgbl_deftypes > gtm_threadgbl_deftypes.h.tmp + COMMAND ${CMAKE_COMMAND} -E rename gtm_threadgbl_deftypes.h.tmp gtm_threadgbl_deftypes.h + ) +add_custom_target(gen_gtm_threadgbl_deftypes DEPENDS gtm_threadgbl_deftypes.h) + +foreach(exp exe shr) + set(out gtm${exp}_symbols.export) + set(in ${GTM_SOURCE_DIR}/sr_unix/gtm${exp}_symbols.exp) + add_custom_command( + OUTPUT ${out} + DEPENDS ${in} + COMMAND tcsh -f ${GTM_SOURCE_DIR}/sr_linux/genexport.csh ${in} ${out} + ) +endforeach() + +add_custom_target(gen_export DEPENDS gtmexe_symbols.export gtmshr_symbols.export) + +foreach(lib + gtcm + cmisockettcp + gnpclient + gnpserver + dbcertify + dse + lke + mupip + stub + mumps + ${extralibs} + ) + add_library(lib${lib} STATIC ${lib${lib}_SOURCES}) + set_property(TARGET lib${lib} PROPERTY OUTPUT_NAME ${lib}) + add_dependencies(lib${lib} gen_gtm_threadgbl_deftypes) +endforeach() + +# TODO: find_package or find_library for system libs? +include_directories ("/usr/local/include") +target_link_libraries(libmumps ${libmumpslibs}) + +add_executable(mumps ${mumps_SOURCES}) +target_link_libraries(mumps libmumps) + +add_executable(dse ${dse_SOURCES}) +target_link_libraries(dse libdse libmumps libstub) +list(APPEND with_export dse) + +add_executable(dbcertify ${dbcertify_SOURCES}) +target_link_libraries(dbcertify libdbcertify libmupip libmumps libstub) + +add_executable(geteuid ${geteuid_SOURCES}) + +add_executable(gtmsecshr ${gtmsecshr_SOURCES}) +add_dependencies(gtmsecshr gen_gtm_threadgbl_deftypes) + +add_executable(gtmsecshr_real ${gtmsecshr_real_SOURCES}) +target_link_libraries(gtmsecshr_real libmumps) +set_target_properties(gtmsecshr_real PROPERTIES + OUTPUT_NAME gtmsecshr + RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/gtmsecshrdir + ) +add_dependencies(gtmsecshr_real gen_gtm_threadgbl_deftypes) + +add_executable(mupip ${mupip_SOURCES}) +target_link_libraries(mupip libmupip libmumps libstub) +list(APPEND with_export mupip) + +add_executable(lke ${lke_SOURCES}) +target_link_libraries(lke liblke libmumps libgnpclient libmumps libgnpclient libcmisockettcp) +list(APPEND with_export lke) + + +add_executable(gtcm_server ${gtcm_server_SOURCES}) +target_link_libraries(gtcm_server libgtcm libmumps libstub) +list(APPEND with_export gtcm_server) + +add_executable(gtcm_gnp_server ${gtcm_gnp_server_SOURCES}) +target_link_libraries(gtcm_gnp_server libgnpserver liblke libmumps libcmisockettcp libstub) +list(APPEND with_export gtcm_gnp_server) + +add_executable(gtcm_play ${gtcm_play_SOURCES}) +target_link_libraries(gtcm_play libgtcm libmumps libstub) +list(APPEND with_export gtcm_play) + +add_executable(gtcm_pkdisp ${gtcm_pkdisp_SOURCES}) +target_link_libraries(gtcm_pkdisp libgtcm libmumps libstub) + +add_executable(gtcm_shmclean ${gtcm_shmclean_SOURCES}) +target_link_libraries(gtcm_shmclean libgtcm libmumps libstub) + +add_executable(semstat2 ${semstat2_SOURCES}) + +add_executable(ftok ${ftok_SOURCES}) +target_link_libraries(ftok libmumps libstub) + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS") + add_executable(gtm_svc ${gtm_svc_SOURCES}) + target_link_libraries(gtm_svc libmumps libgnpclient libcmisockettcp libgtmrpc) +endif() +foreach(t ${with_export}) + set_target_properties(${t} PROPERTIES + LINK_FLAGS "${gtm_link}" + LINK_DEPENDS "${gtm_dep}" + ) + add_dependencies(${t} gen_export) +endforeach() + +add_library(libgtmshr MODULE ${libgtmshr_SOURCES}) +set_property(TARGET libgtmshr PROPERTY OUTPUT_NAME gtmshr) +target_link_libraries(libgtmshr libmumps libgnpclient libcmisockettcp) +set_target_properties(libgtmshr PROPERTIES + LINK_FLAGS "${libgtmshr_link}" + LINK_DEPENDS "${libgtmshr_dep}" + ) +add_dependencies(libgtmshr gen_export) +add_dependencies(mumps libgtmshr) + +if(is_encryption_supported) + # Iterate over the list of GPG related libraries + foreach(gpglib gpg-error gpgme gcrypt) + # For each library, we need a new CMake variable, hence GPGLIB_${gpglib} + find_library(GPGLIB_${gpglib} NAME ${gpglib} PATHS ${CMAKE_LIBRARY_PATH}) + # Append the found library to the list + set(GPG_LIBRARIES ${GPG_LIBRARIES} ${GPGLIB_${gpglib}}) + endforeach() + + add_library(libgtmcrypt MODULE ${libgtmcrypt_SOURCES}) + set_target_properties(libgtmcrypt PROPERTIES + OUTPUT_NAME gtmcrypt + COMPILE_DEFINITIONS "USE_GCRYPT -DUSE_AES256CFB" + LIBRARY_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin + ) + target_link_libraries(libgtmcrypt ${GPG_LIBRARIES}) + install(TARGETS libgtmcrypt DESTINATION ${GTM_INSTALL_DIR}/plugin) + + add_executable(maskpass ${maskpass_SOURCES}) + target_link_libraries(maskpass ${GPG_LIBRARIES}) + set_target_properties(maskpass PROPERTIES + COMPILE_DEFINITIONS USE_GCRYPT + RUNTIME_OUTPUT_DIRECTORY ${GTM_BINARY_DIR}/plugin/gtmcrypt + ) + install(TARGETS maskpass DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt) + + foreach(f + add_db_key.sh + build.sh + encrypt_sign_db_key.sh + gen_keypair.sh + gen_sym_hash.sh + gen_sym_key.sh + gtmcrypt.tab + gtmcrypt_dbk_ref.c + gtmcrypt_dbk_ref.h + gtmcrypt_interface.h + gtmcrypt_pk_ref.c + gtmcrypt_pk_ref.h + gtmcrypt_dbk_ref.c + gtmcrypt_dbk_ref.h + gtmcrypt_ref.c + gtmcrypt_ref.h + gtmcrypt_sym_ref.h + gtmxc_types.h + import_and_sign_key.sh + install.sh + maskpass.c + pinentry-gtm.sh + pinentry.m + pinentry.m + show_install_config.sh + ) + set(f_in "${GTM_SOURCE_DIR}/sr_unix/${f}") + set(f_out "${GTM_BINARY_DIR}/plugin/gtmcrypt/${f}") + add_custom_command( + OUTPUT "${f_out}" + DEPENDS "${f_in}" + COMMAND ${CMAKE_COMMAND} -E copy "${f_in}" "${f_out}" + ) + if("${f}" MATCHES "\\.sh$") + set(permissions PERMISSIONS ${install_permissions_script}) + else() + set(permissions "") + endif() + install(FILES "${f_out}" DESTINATION ${GTM_INSTALL_DIR}/plugin/gtmcrypt ${permissions}) + list(APPEND files_to_place "${f_out}") + endforeach() +endif() + +install(TARGETS + mumps + dse + lke + geteuid + gtcm_server + gtcm_gnp_server + gtcm_pkdisp + gtcm_play + gtcm_shmclean + semstat2 + ftok + gtmsecshr + mupip + libgtmshr + DESTINATION ${GTM_INSTALL_DIR} + ) +install(TARGETS gtmsecshr_real DESTINATION ${GTM_INSTALL_DIR}/gtmsecshrdir) + +# .m -> .m +#file(GLOB m_files_sr_port RELATIVE ${GTM_SOURCE_DIR}/sr_port ${GTM_SOURCE_DIR}/sr_port/*.m) +set(m_files_sr_port + gde.m + gdeadd.m + gdechang.m + gdedelet.m + gdeexit.m + gdehelp.m + gdeinit.m + gdelocks.m + gdelog.m + gdemap.m + gdemsgin.m + gdeparse.m + gdequit.m + gderenam.m + gdescan.m + gdesetgd.m + gdeshow.m + gdespawn.m + gdetempl.m + ) +file(GLOB m_files_sr_unix RELATIVE ${GTM_SOURCE_DIR}/sr_unix ${GTM_SOURCE_DIR}/sr_unix/*.m) +file(GLOB mpt_files_sr_port RELATIVE ${GTM_SOURCE_DIR}/sr_port ${GTM_SOURCE_DIR}/sr_port/*.mpt) +file(GLOB mpt_files_sr_unix RELATIVE ${GTM_SOURCE_DIR}/sr_unix ${GTM_SOURCE_DIR}/sr_unix/*.mpt) + +set(gtm_chset_dir_ "") +set(gtm_chset_dir_UTF-8 "/utf8") + +foreach(d sr_port sr_unix) + foreach(m ${m_files_${d}}) + get_filename_component(m_name "${m}" NAME_WE) + string(TOUPPER "${m_name}" m_upper) + if("${m}" MATCHES "^gde") + foreach(gtm_chset "" "UTF-8") + set(m_out "${GTM_BINARY_DIR}${gtm_chset_dir_${gtm_chset}}/${m_upper}.m") + add_custom_command( + OUTPUT "${m_out}" + DEPENDS ${GTM_SOURCE_DIR}/${d}/${m} + COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}" + ) + list(APPEND files_to_place "${m_out}") + list(APPEND gtm_chset_routines_${gtm_chset} "${m_out}") + endforeach() + else() + set(m_out "${GTM_BINARY_DIR}/${m_upper}.m") + add_custom_command( + OUTPUT "${m_out}" + DEPENDS ${GTM_SOURCE_DIR}/${d}/${m} + COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}" + ) + install(FILES "${m_out}" DESTINATION ${GTM_INSTALL_DIR}) + list(APPEND files_to_place "${m_out}") + endif() + endforeach() + foreach(m ${mpt_files_${d}}) + string(TOUPPER "_${m}" m_upper) + string(REGEX REPLACE "MPT$" "m" m_out "${GTM_BINARY_DIR}/${m_upper}") + add_custom_command( + OUTPUT "${m_out}" + DEPENDS ${GTM_SOURCE_DIR}/${d}/${m} + COMMAND ${CMAKE_COMMAND} -E copy ${GTM_SOURCE_DIR}/${d}/${m} "${m_out}" + ) + install(FILES "${m_out}" DESTINATION ${GTM_INSTALL_DIR}) + list(APPEND files_to_place "${m_out}") + endforeach() +endforeach() + +set(files) +foreach(f + gtm_descript.h + gtm_limits.h + gtm_sizeof.h + gtm_stdio.h + gtm_stdlib.h + gtm_string.h + gtm_strings.h + gtmxc_types.h + main_pragma.h + arch.gtc + gtcm_run.gtc + gtcm_slist.gtc + gdedefaults.gtc + gtmcshrc.gtc + gtmprofile.gtc + gtmprofile_preV54000.gtc + gtmstart.gtc + gtmstop.gtc + dse.hlp + gde.hlp + lke.hlp + mumps.hlp + mupip.hlp + custom_errors_sample.txt + ) + select_file(src ${f}) + list(APPEND files ${src}) +endforeach() +install(FILES ${files} DESTINATION ${GTM_INSTALL_DIR}) + +set(scripts) +foreach(f + gtm.gtc + gtmbase.gtc + ) + select_file(src ${f}) + list(APPEND scripts ${src}) +endforeach() +install(FILES ${scripts} + DESTINATION ${GTM_INSTALL_DIR} + PERMISSIONS ${install_permissions_script} + ) + +find_program(ICUCONFIG NAMES icu-config) +if(ICUCONFIG) + execute_process( + COMMAND ${ICUCONFIG} --version + OUTPUT_VARIABLE icu_version + RESULT_VARIABLE icu_failed + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(icu_failed) + message(FATAL_ERROR "Command\n ${ICUCONFIG} --version\nfailed (${icu_failed}).") + elseif("x${icu_version}" MATCHES "^x([0-9]+\\.[0-9]+)") + set(gtm_icu_version "${CMAKE_MATCH_1}") + else() + message(FATAL_ERROR "Command\n ${ICUCONFIG} --version\nproduced unrecognized output:\n ${icu_version}") + endif() +else() + message(FATAL_ERROR "Unable to find 'icu-config'. Set ICUCONFIG in CMake cache.") +endif() + +if (gtm_icu_version GREATER 10) + message("libicu version ${gtm_icu_version} > 10") + string(REGEX REPLACE "([0-9])([0-9]).*" "\\1.\\2" gtm_icu_version "${gtm_icu_version}") + message("Fixing gtm_icu_version to ${gtm_icu_version}.\nThis had better be the default") +endif() + +foreach(gtm_chset "" "UTF-8") + foreach(in ${gtm_chset_routines_${gtm_chset}}) + string(REPLACE ".m" ".o" out "${in}") + get_filename_component(out_dir "${out}" PATH) + add_custom_command( + OUTPUT ${out} + DEPENDS ${in} ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake mumps + COMMAND ${CMAKE_COMMAND} + -D gtm_dist=${GTM_BINARY_DIR} + -D gtmroutines=. + -D gtm_chset=${gtm_chset} + -D gtm_icu_version=${gtm_icu_version} + -D mumps=$ + -D "args=${in}" + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + WORKING_DIRECTORY ${out_dir} + VERBATIM + ) + list(APPEND files_to_place ${out}) + install(FILES "${out}" DESTINATION ${GTM_INSTALL_DIR}${gtm_chset_dir_${gtm_chset}}) + endforeach() +endforeach() + +#----------------------------------------------------------------------------- +set(gtm_hlp mumps.hlp) +set(gde_hlp gde.hlp) +set(mupip_hlp mupip.hlp) +set(dse_hlp dse.hlp) +set(lke_hlp lke.hlp) +foreach(help gtm gde mupip dse lke) + set(CMAKE_CONFIGURABLE_FILE_CONTENT + "Change -segment DEFAULT -block=2048 -file=\$gtm_dist/${help}help.dat +Change -region DEFAULT -record=1020 -key=255 +exit") + configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in + ${GTM_BINARY_DIR}/${help}help.in1) + set(CMAKE_CONFIGURABLE_FILE_CONTENT + "Do ^GTMHLPLD +${GTM_SOURCE_DIR}/sr_port/${${help}_hlp} +Halt") + configure_file(${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in + ${GTM_BINARY_DIR}/${help}help.in2) + set(env + -D gtm_dist=${GTM_BINARY_DIR} + -D gtmroutines=. + -D gtmgbldir=${GTM_BINARY_DIR}/${help}help + ) + add_custom_command( + OUTPUT ${help}help.dat ${help}help.gld + DEPENDS ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake mumps mupip + ${GTM_BINARY_DIR}/${help}help.in1 + ${GTM_BINARY_DIR}/${help}help.in2 + COMMAND ${CMAKE_COMMAND} -E remove ${help}help.dat ${help}help.gld + COMMAND ${CMAKE_COMMAND} ${env} + -D mumps=$ -D "args=-run;GDE" + -D input_file=${GTM_BINARY_DIR}/${help}help.in1 + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + COMMAND ${CMAKE_COMMAND} ${env} + -D mumps=$ -D "args=create" + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + COMMAND ${CMAKE_COMMAND} ${env} + -D mumps=$ -D "args=-direct" + -D input_file=${GTM_BINARY_DIR}/${help}help.in2 + -P ${GTM_SOURCE_DIR}/sr_unix/mumps.cmake + VERBATIM + ) + list(APPEND files_to_place ${help}help.dat) + install(FILES ${GTM_BINARY_DIR}/${help}help.dat DESTINATION ${GTM_INSTALL_DIR}) +endforeach() +#----------------------------------------------------------------------------- + +set(GTM_TOP "${GTM_BINARY_DIR}") +configure_file(sr_unix/gpgagent.tab.in plugin/gpgagent.tab @ONLY) +set(GTM_TOP "${CMAKE_INSTALL_PREFIX}/${GTM_INSTALL_DIR}") +configure_file(sr_unix/gpgagent.tab.in CMakeFiles/plugin/gpgagent.tab @ONLY) +install(FILES ${GTM_BINARY_DIR}/CMakeFiles/plugin/gpgagent.tab DESTINATION ${GTM_INSTALL_DIR}/plugin) + +install(FILES sr_unix/configure.gtc DESTINATION ${GTM_INSTALL_DIR} + PERMISSIONS ${install_permissions_script} + RENAME configure + ) + +install(FILES sr_unix/gtminstall.sh DESTINATION ${GTM_INSTALL_DIR} + PERMISSIONS ${install_permissions_script} + RENAME gtminstall + ) + +install(FILES sr_unix/lowerc_cp.sh DESTINATION ${GTM_INSTALL_DIR} + RENAME lowerc_cp + ) + +install(FILES COPYING DESTINATION ${GTM_INSTALL_DIR}) + +add_custom_target(place_files ALL DEPENDS ${files_to_place}) + diff --git a/sr_unix/anticipatory_freeze.c b/sr_unix/anticipatory_freeze.c new file mode 100644 index 0000000..98cd4a3 --- /dev/null +++ b/sr_unix/anticipatory_freeze.c @@ -0,0 +1,393 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include +#include "gtm_stdio.h" +#include "gtm_ctype.h" + +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "repl_msg.h" +#include "gtmsource.h" +#include "error.h" +#include "repl_sem.h" +#include "gtmimagename.h" +#include "hashtab_str.h" +#include "eintr_wrappers.h" +#include "gtmmsg.h" +#include "anticipatory_freeze.h" +#ifdef DEBUG +#include "dpgbldir.h" +#include "is_proc_alive.h" +#endif + +#define MAX_TAG_LEN 128 /* Maximum size of an error mnemonic */ +#define MAX_READ_SZ 1024 /* Mnemonic + flags shouldn't exceed this limit */ +#define COMMENT_DELIMITER ';' +#define NEWLINE 0x0A +#define EOL_REACHED (char *)(-1) +#define EOF_REACHED (char *)(-2) + +#define EXHAUST_CURRENT_LINE(BUFF, HANDLE, FGETS_RC) \ +{ \ + assert(NEWLINE != BUFF[STRLEN(BUFF) - 1]); \ + while (TRUE) \ + { \ + FGETS_FILE(BUFF, MAX_READ_SZ, HANDLE, FGETS_RC); \ + if ((NULL == FGETS_RC) || NEWLINE == BUFF[STRLEN(BUFF) - 1]) \ + break; \ + } \ +} + +error_def(ERR_ASSERT); +error_def(ERR_CUSTERRNOTFND); +error_def(ERR_CUSTERRSYNTAX); +error_def(ERR_CUSTOMFILOPERR); +error_def(ERR_DSKSPCAVAILABLE); +error_def(ERR_ENOSPCQIODEFER); +error_def(ERR_REPLINSTFREEZECOMMENT); +error_def(ERR_REPLINSTFROZEN); +error_def(ERR_TEXT); +error_def(ERR_INSTFRZDEFER); + +GBLREF jnlpool_addrs jnlpool; +GBLREF jnlpool_ctl_ptr_t jnlpool_ctl; +GBLREF boolean_t is_src_server; +GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS]; +#ifdef DEBUG +GBLREF uint4 process_id; +GBLREF volatile boolean_t timer_in_handler; +#endif + +/* Typically prototypes are included in the header file. But, in this case the static function - get_mnemonic_offset - has the + * hash_table_str as one of the function parameters which means all the files which includes anticipatory_freeze.h needs to include + * hashtab_str.h and since there are lot of such C files, we chose to define static function prototypes in the C file itself. + */ +STATICFNDCL char *scan_space(FILE *handle, char *buff, char *buffptr, char *buff_top); +STATICFNDCL int get_mnemonic_offset(hash_table_str **err_hashtab, char *mnemonic_buf, int mnemonic_len); + +/* Scan through whitespace in the current buffer (read more if required) */ +STATICFNDEF char *scan_space(FILE *handle, char *buff, char *buffptr, char *buff_top) +{ + char *fgets_rc; + + while (TRUE) + { + for (; (buffptr < buff_top) && (ISSPACE_ASCII(*buffptr)); buffptr++) + ; + if (buffptr < buff_top) + return buffptr; /* first non-whitespace character */ + if (NEWLINE == *(buffptr - 1)) + return EOL_REACHED; + /* current buffer is exhausted and we haven't seen a newline; read more */ + FGETS_FILE(buff, MAX_READ_SZ, handle, fgets_rc); + if (NULL == fgets_rc) + break; + buffptr = buff; + buff_top = buffptr + STRLEN(buff); + } + return EOF_REACHED; +} + +STATICFNDEF int get_mnemonic_offset(hash_table_str **err_hashtab, char *mnemonic_buf, int mnemonic_len) +{ + const err_msg *msg_beg, *msg_top; + hash_table_str *tmp_err_hashtab; + ht_ent_str *err_htent; + stringkey key; + err_msg *msg_info; + boolean_t added; + DEBUG_ONLY(int idx;) + + msg_beg = merrors_ctl.fst_msg; + msg_top = msg_beg + merrors_ctl.msg_cnt; + assert('\0' == mnemonic_buf[mnemonic_len]); + if (NULL == (tmp_err_hashtab = *err_hashtab)) + { /* create and populate hash-table for future lookups */ + tmp_err_hashtab = (hash_table_str *)malloc(SIZEOF(hash_table_str)); + DEBUG_ONLY(tmp_err_hashtab->base = NULL); + init_hashtab_str(tmp_err_hashtab, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE); + assert(tmp_err_hashtab->base); + for (msg_info = (err_msg *)msg_beg; msg_info < msg_top; msg_info++) + { + key.str.addr = msg_info->tag; + key.str.len = STRLEN(msg_info->tag); + COMPUTE_HASH_STR(&key); + added = add_hashtab_str(tmp_err_hashtab, &key, msg_info, &err_htent); + assert(added); + assert(err_htent->value); + assert(msg_info->tag == ((err_msg *)(err_htent->value))->tag); + } + *err_hashtab = tmp_err_hashtab; + } + assert(NULL != tmp_err_hashtab); + /* lookup for the mnemonic */ + key.str.addr = mnemonic_buf; + key.str.len = mnemonic_len; + COMPUTE_HASH_STR(&key); + if (NULL == (err_htent = lookup_hashtab_str(tmp_err_hashtab, &key))) + return -1; + msg_info = (err_msg *)(err_htent->value); + assert(msg_info >= msg_beg && msg_info < msg_top); + return msg_info - msg_beg; +} + +/* Determine whether a given msg_id qualifies for an anticipatory freeze or not */ +boolean_t is_anticipatory_freeze_needed(sgmnt_addrs *csa, int msg_id) +{ + const err_ctl *ctl; + int idx; + + assert(NULL != jnlpool.jnlpool_ctl); + /* Certain error messages should NOT trigger a freeze even if they are so configured in the custom errors file as they might + * result in instance freezes that can be set indefinitely. Currently, we know of at least 3 such messages: + * 1. ENOSPCQIODEFER and INSTFRZDEFER : To ensure we don't set anticipatory freeze if we don't/can't hold crit + * (due to possible deadlock) + * 2. DSKSPCAVAILABLE : To ensure we don't set anticipatory freeze if the disk space becomes available after an initial + * lack of space. + * These messages have csa == NULL so they are guarranteed to not trigger a freeze. + */ + + assert(((ERR_ENOSPCQIODEFER != msg_id) && (ERR_DSKSPCAVAILABLE != msg_id) && (ERR_INSTFRZDEFER != msg_id)) + || (NULL == csa)); + if (!csa || !csa->nl || !csa->hdr || !csa->hdr->freeze_on_fail) + return FALSE; + ctl = err_check(msg_id); + if (NULL != ctl) + { + GET_MSG_IDX(msg_id, ctl, idx); + assert(idx < ARRAYSIZE(jnlpool_ctl->merrors_array)); + if (jnlpool_ctl->merrors_array[idx] & AFREEZE_MASK) + return TRUE; + } + return FALSE; +} + +/* set the anticipatory freeze in the journal pool */ +void set_anticipatory_freeze(sgmnt_addrs *csa, int msg_id) +{ + boolean_t was_crit; + sgmnt_addrs *repl_csa; + const err_msg *msginfo; +# ifdef DEBUG + qw_off_t write_addr; + uint4 write; +# endif + + assert(is_anticipatory_freeze_needed(csa, msg_id)); + DEBUG_ONLY( + write_addr = jnlpool_ctl->write_addr; + write = jnlpool_ctl->write; + ) + assert(write == write_addr % jnlpool_ctl->jnlpool_size); + repl_csa = &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs; + assert(NULL != repl_csa); + was_crit = repl_csa->now_crit; + if (!was_crit) + { + if (csa->now_crit) + grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, GRAB_LOCK_ONLY); + else if (FALSE == grab_lock(jnlpool.jnlpool_dummy_reg, FALSE, GRAB_LOCK_ONLY)) + { + MSGID_TO_ERRMSG(msg_id, msginfo); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_INSTFRZDEFER, 4, LEN_AND_STR(msginfo->tag), + REG_LEN_STR(csa->region)); + return; + } + } + /* Now that we hold necessary locks, set the freeze and the comment field */ + jnlpool.jnlpool_ctl->freeze = TRUE; + GENERATE_INST_FROZEN_COMMENT(jnlpool.jnlpool_ctl->freeze_comment, SIZEOF(jnlpool.jnlpool_ctl->freeze_comment), msg_id); + /* TODO : Do we need a SHM_WRITE_MEMORY_BARRIER ? */ + if (!was_crit) + rel_lock(jnlpool.jnlpool_dummy_reg); +} + +/* initialize jnlpool_ctl->merrors_array to set up the list of errors that should trigger anticipatory freeze errors */ +boolean_t init_anticipatory_freeze_errors() +{ + int idx, save_errno, status, mnemonic_len, offset, line_no; + FILE *handle; + char *fgets_rc; + char buff[MAX_READ_SZ], mnemonic_buf[MAX_TAG_LEN]; + char *buffptr, *buff_top, *errptr, *errptr_top; + mstr custom_err_file; + hash_table_str *err_hashtab = NULL; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + /* TODO : Currently, we process errors that belong to merrors[] as those are the ones related to database/journal. Need + * to check if cmerrors/cmierrors also need to be included in this list or not. + */ + assert(IS_MUPIP_IMAGE); /* is_src_server is not initialized at this point */ + assert(jnlpool_ctl && !jnlpool_ctl->pool_initialized); /* should be invoked BEFORE the journal pool is fully-initialized */ + assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); /* should hold journal pool access control semaphore */ + /* Now, read the custom errors file and populate the journal pool */ + custom_err_file = TREF(gtm_custom_errors); + handle = Fopen(custom_err_file.addr, "r"); + if (NULL == handle) + { + save_errno = errno; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fopen"), custom_err_file.len, + custom_err_file.addr, save_errno); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fopen"), custom_err_file.len, + custom_err_file.addr, save_errno); + return FALSE; + } + line_no = 0; + /* The code below parses a custom errors file in the following format. + * + * file ::= line* + * line ::= mnemonic SPACE* comment? EOL | + * comment EOL + * mnemonic ::= ALNUM+ + * comment ::= COMMENT_DELIMITER ANY* + * + * SPACE ::= any ASCII white space character + * COMMENT_DELIMITER ::= ';' + * ANY ::= any ASCII character except end of line + * EOL ::= ASCII end of line character + * ALNUM ::= any ASCII alphanumeric character + * + * NOTES: + * "*" denotes zero-or-more of the previous item + * "?" denotes zero-or-one of the previous item + * "+" denotes one-or-more of the previous item + * "|" denotes multiple alternatives + * The mnemonic must match an entry in the GT.M error message list. + * Anything between the COMMENT_DELIMITER and EOL is ignored. + * Each iteration of the loop parses one line. + */ + while (TRUE) + { + FGETS_FILE(buff, MAX_READ_SZ, handle, fgets_rc); + line_no++; + if (NULL == fgets_rc) + break; + buffptr = buff; + buff_top = buffptr + STRLEN(buff); + errptr = &mnemonic_buf[0]; + errptr_top = errptr + MAX_TAG_LEN; + /* The first character has to be alpha-numeric or a comment */ + if (!ISALNUM_ASCII(*buffptr) && (COMMENT_DELIMITER != *buffptr)) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr, + line_no, ERR_TEXT, 2, + LEN_AND_LIT("First character should be comment (;) or alpha numeric")); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr, + line_no, ERR_TEXT, 2, + LEN_AND_LIT("First character should be comment (;) or alpha numeric")); + return FALSE; + } + while (ISALNUM_ASCII(*buffptr)) + { + *errptr++ = *buffptr++; + if (errptr > errptr_top) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, + custom_err_file.addr, line_no, ERR_TEXT, 2, LEN_AND_LIT("Mnemonic too long")); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, + custom_err_file.addr, line_no, ERR_TEXT, 2, LEN_AND_LIT("Mnemonic too long")); + return FALSE; + } + assert(buffptr < buff_top); /* errptr > errptr_top should fail before this */ + } + *errptr = '\0'; + if (0 < (mnemonic_len = (errptr - &mnemonic_buf[0]))) + { /* Non-empty error mnemonic found; look it up */ + if (-1 == (offset = get_mnemonic_offset(&err_hashtab, mnemonic_buf, mnemonic_len))) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CUSTERRNOTFND, 2, mnemonic_len, mnemonic_buf); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_CUSTERRNOTFND, 2, mnemonic_len, mnemonic_buf); + return FALSE; + } + jnlpool_ctl->merrors_array[offset] |= AFREEZE_MASK; /* duplicate entries are not considered an error */ + } + assert(ISSPACE_ASCII(*buffptr) || (COMMENT_DELIMITER == *buffptr)); + if (EOL_REACHED == (buffptr = scan_space(handle, buff, buffptr, buff_top))) + continue; + else if (EOF_REACHED == buffptr) + break; + assert(buffptr < buff_top); + if (COMMENT_DELIMITER != *buffptr) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr, + line_no, ERR_TEXT, 2, LEN_AND_LIT("Unexpected character found after mnemonic")); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(9) ERR_CUSTERRSYNTAX, 3, custom_err_file.len, custom_err_file.addr, + line_no, ERR_TEXT, 2, LEN_AND_LIT("Unexpected character found after mnemonic")); + return FALSE; + } + /* Need to ignore the rest of the current buffer and exhaust the current line */ + if (NEWLINE != *(buff_top - 1)) + EXHAUST_CURRENT_LINE(buff, handle, fgets_rc); + } + if (err_hashtab) + { + free_hashtab_str(err_hashtab); + free(err_hashtab); + } + if (!feof(handle)) + { + save_errno = errno; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fgets"), custom_err_file.len, + custom_err_file.addr, save_errno); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fgets"), custom_err_file.len, + custom_err_file.addr, save_errno); + return FALSE; + } + FCLOSE(handle, status); + if (SS_NORMAL != status) + { + save_errno = errno; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fclose"), custom_err_file.len, + custom_err_file.addr, save_errno); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_CUSTOMFILOPERR, 4, LEN_AND_LIT("fclose"), custom_err_file.len, + custom_err_file.addr, save_errno); + return FALSE; + } + jnlpool_ctl->instfreeze_environ_inited = TRUE; + return TRUE; +} + +#ifdef DEBUG +void clear_fake_enospc_if_master_dead(void) +{ + gd_addr *addr_ptr; + gd_region *r_top, *r_local; + sgmnt_addrs *csa; + + if((jnlpool_ctl->jnlpool_creator_pid != process_id) && !is_proc_alive(jnlpool_ctl->jnlpool_creator_pid, 0)) + { + for (addr_ptr = get_next_gdr(NULL); addr_ptr; addr_ptr = get_next_gdr(addr_ptr)) + { + for (r_local = addr_ptr->regions, r_top = r_local + addr_ptr->n_regions; r_local < r_top; r_local++) + { + if ((dba_bg != r_local->dyn.addr->acc_meth) && (dba_mm != r_local->dyn.addr->acc_meth)) + continue; + csa = REG2CSA(r_local); + if ((NULL != csa) && (NULL != csa->nl)) + if (csa->nl->fake_db_enospc || csa->nl->fake_jnl_enospc) + { + csa->nl->fake_db_enospc = FALSE; + csa->nl->fake_jnl_enospc = FALSE; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_TEXT, 2, DB_LEN_STR(r_local), ERR_TEXT, + 2, LEN_AND_LIT("Resetting fake_db_enospc and fake_jnl_enospc because " + "fake ENOSPC master is dead")); + } + } + } + } +} +#endif diff --git a/sr_unix/condstk_expand.c b/sr_unix/condstk_expand.c new file mode 100644 index 0000000..1229d4e --- /dev/null +++ b/sr_unix/condstk_expand.c @@ -0,0 +1,95 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#include "mdef.h" + +#include "gtm_string.h" +#include "gtm_stdio.h" + +#include "gtmio.h" +#include "error.h" +#include "mv_stent.h" + +GBLREF unsigned char *stackbase; + +#ifdef DEBUG_CONDSTK +# define DBGCSTK(x) DBGFPF(x) +#else +# define DBGCSTK(x) +#endif + +/* Expands the condition handler stack copying old stack to new expanded stack. + * + * Note, chnd_end is always set 2 entries from the actual true top of the stack. Consider what can happen + * if we go to expand the stack but storage is not available. We will fail but when running things down, + * we ALSO need to install handlers. So once process_exiting is set, we are allowed to use the extra handlers. + */ +void condstk_expand(void) +{ + condition_handler *new_chnd, *new_chnd_end, *ctxt_ent; + int new_size, old_len, old_size, cnt; + UINTPTR_T delta; + mv_stent *mvs; + + DBGEHND((stderr, "condstk_expand: old: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr + " chnd_incr: %d\n", chnd, chnd_end, ctxt, active_ch, chnd_incr)); + /* Make sure we are allowed to expand */ + old_len = INTCAST((char *)chnd_end - (char *)chnd); + old_size = old_len / SIZEOF(condition_handler); + new_size = old_size + chnd_incr + CONDSTK_RESERVE; /* New count of entries in cond handlr stack */ + /* Nothing known should allow/require stack to get this large */ + assertpro(new_size <= CONDSTK_MAX_STACK); + new_chnd = malloc(new_size * SIZEOF(condition_handler)); /* Allocate new condition handler stack */ + new_chnd_end = &new_chnd[new_size]; + delta = (UINTPTR_T)((char *)new_chnd - (char *)chnd); + memcpy(new_chnd, chnd, old_len); /* Copy occupied part of old stack */ + assert(chnd < chnd_end); + /* Modify the address of save_active_ch so points to relevant entry in new condition handler stack. Note first + * entry back pointer remains unmodified (as NULL). + */ + for (cnt = 2, ctxt_ent = new_chnd + 1; cnt <= old_size; cnt++, ctxt_ent++) + { + assert(ctxt_ent >= new_chnd); + assert(ctxt_ent < new_chnd_end); + DBGEHND((stderr, "condstk_expand: cnt: %d, chptr: 0x"lvaddr" save_active_ch from 0x"lvaddr + " to 0x"lvaddr"\n", cnt, ctxt_ent, ctxt_ent->save_active_ch, ((char *)ctxt_ent->save_active_ch + delta))); + ctxt_ent->save_active_ch = (condition_handler *)((char *)ctxt_ent->save_active_ch + delta); + assert((1 == cnt) || (ctxt_ent->save_active_ch >= new_chnd)); + assert((1 == cnt) || (ctxt_ent->save_active_ch < new_chnd_end)); + } +# ifdef GTM_TRIGGER + /* Trigger type mv_stent (MVST_TRIGR) save/restore the value of ctxt so look through the stack to locate those and + * fix them up too. + */ + for (mvs = mv_chain; mvs < (mv_stent *)stackbase; mvs = (mv_stent *)((char *)mvs + mvs->mv_st_next)) + { + if (MVST_TRIGR != mvs->mv_st_type) + continue; + DBGEHND((stderr, "condstk_expand: Trigger saved ctxt modified from 0x"lvaddr" to 0x"lvaddr"\n", + mvs->mv_st_cont.mvs_trigr.ctxt_save, (char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta)); + /* Have a trigger mv_stent - appropriately modify the saved ctxt value (high water mark for condition handlers */ + mvs->mv_st_cont.mvs_trigr.ctxt_save = (condition_handler *)((char *)mvs->mv_st_cont.mvs_trigr.ctxt_save + delta); + } +# endif + /* Condition handler stack now reset - modify globals of record accordingly */ + free(chnd); /* Old version no longer needed */ + chnd = new_chnd; + chnd_end = new_chnd_end; + if (CONDSTK_MAX_INCR > chnd_incr) + chnd_incr = chnd_incr * 2; + ctxt = (condition_handler *)((char *)ctxt + delta); + active_ch = (condition_handler *)((char *)active_ch + delta); + assert(ctxt >= chnd); + assert(ctxt < chnd_end); + assert(active_ch >= chnd); + assert(active_ch < chnd_end); + DBGEHND((stderr, "condstk_expand: new: chnd: "lvaddr" chnd_end: "lvaddr" ctxt: "lvaddr" active_ch: "lvaddr + " chnd_incr: %d delta: "lvaddr"\n", chnd, chnd_end, ctxt, active_ch, chnd_incr, delta)); +} diff --git a/sr_unix/custom_errors_sample.txt b/sr_unix/custom_errors_sample.txt new file mode 100644 index 0000000..b289103 --- /dev/null +++ b/sr_unix/custom_errors_sample.txt @@ -0,0 +1,33 @@ +DBBMLCORRUPT +DBDANGER +DBFSYNCERR +DBIOERR +DSKNOSPCAVAIL +GBLOFLOW +GVDATAFAIL +GVDATAGETFAIL ; This is currently reported as TPFAIL and invisible to the user. +GVGETFAIL +GVINCRFAIL +GVKILLFAIL +GVORDERFAIL +GVPUTFAIL +GVQUERYFAIL +GVQUERYGETFAIL +GVZTRIGFAIL ; This is currently reported as TPFAIL and invisible to the user. +JNLACCESS +JNLCLOSE +JNLCLOSED +JNLCNTRL +JNLEXTEND +JNLFILECLOSERR +JNLFILEXTERR +JNLFILOPN +JNLFLUSH +JNLFSYNCERR +JNLRDERR +JNLREAD +JNLVSIZE +JNLWRERR +JRTNULLFAIL +OUTOFSPACE +TRIGDEFBAD diff --git a/sr_unix/file_head_write_secshr.c b/sr_unix/file_head_write_secshr.c new file mode 100644 index 0000000..2023d33 --- /dev/null +++ b/sr_unix/file_head_write_secshr.c @@ -0,0 +1,79 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include +#include "gtm_unistd.h" +#include "gtm_fcntl.h" +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "gtm_stdio.h" +#include "gtm_stdlib.h" +#include "gtm_string.h" +#include "gtmio.h" +#include "iosp.h" +#include "eintr_wrappers.h" +#include "file_head_write.h" +#include "gtmmsg.h" +#ifdef __MVS__ +#include "gtm_zos_io.h" +#endif + +error_def(ERR_DBFILOPERR); +error_def(ERR_DBNOTGDS); +error_def(ERR_TEXT); +ZOS_ONLY(error_def(ERR_BADTAG);) + +/* + * This is a plain way to write file header to database. + * Caller needs to take care of concurrency issue etc. + * Parameters : + * fn : full name of a database file. + * header: Pointer to database file header structure (may not be in shared memory) + * len: length of header to write (should be either SGMNT_HDR_LEN or SIZEOF_FILE_HDR(header)) + */ +boolean_t file_head_write_secshr(char *fn, sgmnt_data_ptr_t header, int4 len) +{ + int save_errno, fd, header_size; + ZOS_ONLY(int realfiletag;) + + header_size = (int)SIZEOF_FILE_HDR(header); + assert(SGMNT_HDR_LEN == len || header_size == len); + OPENFILE(fn, O_RDWR, fd); + if (FD_INVALID == fd) + { + save_errno = errno; + gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno); + return FALSE; + } +#ifdef __MVS__ + if (-1 == gtm_zos_tag_to_policy(fd, TAG_BINARY, &realfiletag)) + TAG_POLICY_GTM_PUTMSG(fn, errno, realfiletag, TAG_BINARY); +#endif + LSEEKWRITE(fd, 0, header, len, save_errno); + if (0 != save_errno) + { + gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno); + return FALSE; + } + CLOSEFILE_RESET(fd, save_errno); /* resets "fd" to FD_INVALID */ + if (0 != save_errno) + { + gtm_putmsg(VARLSTCNT(5) ERR_DBFILOPERR, 2, LEN_AND_STR(fn), save_errno); + return FALSE; + } + return TRUE; +} diff --git a/sr_unix/gds_rundown_ch.c b/sr_unix/gds_rundown_ch.c new file mode 100644 index 0000000..4106189 --- /dev/null +++ b/sr_unix/gds_rundown_ch.c @@ -0,0 +1,39 @@ +/**************************************************************** +* * +* Copyright 2013 Fidelity Information Services, Inc * +* * +* This source code contains the intellectual property * +* of its copyright holder(s), and is made available * +* under a license. If you do not know the terms of * +* the license, please stop and do not read further. * +* * +****************************************************************/ + +#include "mdef.h" +#include "error.h" + +GBLREF boolean_t created_core, need_core, dont_want_core; +#ifdef DEBUG +#include "have_crit.h" +GBLREF boolean_t ok_to_UNWIND_in_exit_handling; +#endif + +CONDITION_HANDLER(gds_rundown_ch) +{ + START_CH; + /* To get as virgin a state as possible in the core, take the core now if we + * would be doing so anyway. This will set created_core so it doesn't happen again. + */ + if (DUMPABLE && !SUPPRESS_DUMP) + { + need_core = TRUE; + gtm_fork_n_core(); + } + assert(INTRPT_IN_GDS_RUNDOWN == intrpt_ok_state); + PRN_ERROR; + DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = TRUE); + UNWIND(NULL, NULL); +} + + + diff --git a/sr_unix/gds_rundown_err_cleanup.c b/sr_unix/gds_rundown_err_cleanup.c new file mode 100644 index 0000000..a25ba36 --- /dev/null +++ b/sr_unix/gds_rundown_err_cleanup.c @@ -0,0 +1,91 @@ +/**************************************************************** +* * +* Copyright 2013 Fidelity Information Services, Inc * +* * +* This source code contains the intellectual property * +* of its copyright holder(s), and is made available * +* under a license. If you do not know the terms of * +* the license, please stop and do not read further. * +* * +****************************************************************/ +#include "mdef.h" +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "gds_rundown.h" +#include "jnl.h" +#include "gtm_semutils.h" +#include "do_semop.h" +#include "add_inter.h" +#include "ftok_sems.h" +#include +#include "wcs_clean_dbsync.h" +#include "interlock.h" +#include "wbox_test_init.h" +#include "gds_rundown_err_cleanup.h" + +GBLREF gd_region *gv_cur_region; +GBLREF jnl_gbls_t jgbl; +GBLREF uint4 process_id; + +error_def(ERR_TEXT); +error_def(ERR_DBRNDWN); + +void gds_rundown_err_cleanup(boolean_t have_standalone_access) +{ + pid_t sem_pid; + int semop_res; + unix_db_info *udi; + sgmnt_addrs *csa; + boolean_t cancelled_timer, cancelled_dbsync_timer; + + udi = FILE_INFO(gv_cur_region); + csa = &udi->s_addrs; + /* We got here on an error and are going to close the region. Cancel any pending flush timer for this region by this task*/ + CANCEL_DB_TIMERS(gv_cur_region, csa, cancelled_timer, cancelled_dbsync_timer); + if (csa->now_crit) /* Might hold crit if wcs_flu or other failure */ + { + assert(!csa->hold_onto_crit || jgbl.onlnrlbk); + if (NULL != csa->nl) + rel_crit(gv_cur_region); /* also sets csa->now_crit to FALSE */ + else + csa->now_crit = FALSE; + } + if (!have_standalone_access) + { + if (udi->grabbed_access_sem) + { /* release the access control semaphore, if you hold it */ + sem_pid = semctl(udi->semid, 0, GETPID); + assert(sem_pid == process_id); + if (0 != (semop_res = do_semop(udi->semid, DB_CONTROL_SEM, -1, SEM_UNDO | IPC_NOWAIT))) + send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region), + ERR_TEXT, 2, RTS_ERROR_TEXT("Error releasing access semaphore"), semop_res); + udi->grabbed_access_sem = FALSE; + } + if (udi->counter_acc_incremented) + { + if (0 != (semop_res = do_semop(udi->semid, DB_COUNTER_SEM, -1, SEM_UNDO | IPC_NOWAIT))) + send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region), + ERR_TEXT, 2, RTS_ERROR_TEXT("Error decreasing access semaphore counter"), semop_res); + udi->counter_acc_incremented = FALSE; + } + } + if (udi->grabbed_ftok_sem) + { /* Decrease counter and release ftok */ + assert(!have_standalone_access); + ftok_sem_release(gv_cur_region, !have_standalone_access, TRUE); + } else if (udi->counter_ftok_incremented) /* Just decrease ftok counter */ + { + if (0 != (semop_res = do_semop(udi->ftok_semid, DB_COUNTER_SEM, -1, SEM_UNDO | IPC_NOWAIT))) + send_msg_csa(CSA_ARG(csa) VARLSTCNT(9) ERR_CRITSEMFAIL, 2, DB_LEN_STR(gv_cur_region), + ERR_TEXT, 2, RTS_ERROR_TEXT("Error decreasing ftok semaphore counter"), semop_res); + udi->counter_ftok_incremented = FALSE; + } + gv_cur_region->open = FALSE; + csa->nl = NULL; + REMOVE_CSA_FROM_CSADDRSLIST(csa); /* remove "csa" from list of open regions (cs_addrs_list) */ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DBRNDWN, 2, REG_LEN_STR(gv_cur_region)); +} diff --git a/sr_unix/gds_rundown_err_cleanup.h b/sr_unix/gds_rundown_err_cleanup.h new file mode 100644 index 0000000..14759cd --- /dev/null +++ b/sr_unix/gds_rundown_err_cleanup.h @@ -0,0 +1,16 @@ +/**************************************************************** +* * +* Copyright 2013 Fidelity Information Services, Inc * +* * +* This source code contains the intellectual property * +* of its copyright holder(s), and is made available * +* under a license. If you do not know the terms of * +* the license, please stop and do not read further. * +* * +****************************************************************/ +#ifndef GDS_RUNDOWN_ERR_CLEANUP_INCLUDED +#define GDS_RUNDOWN_ERR_CLEANUP_INCLUDED + +void gds_rundown_err_cleanup(boolean_t have_standalone_access); + +#endif diff --git a/sr_unix/grab_crit_immediate.c b/sr_unix/grab_crit_immediate.c new file mode 100644 index 0000000..4fb4d4e --- /dev/null +++ b/sr_unix/grab_crit_immediate.c @@ -0,0 +1,108 @@ +/**************************************************************** + * * + * Copyright 2001, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include /* for VSIG_ATOMIC_T type */ + +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "gdsbgtr.h" +#include "filestruct.h" +#include "send_msg.h" +#include "mutex.h" +#include "deferred_signal_handler.h" +#include "wcs_recover.h" +#include "caller_id.h" +#include "is_proc_alive.h" +#include "gtmimagename.h" +#include "error.h" + +GBLREF short crash_count; +GBLREF volatile int4 crit_count; +GBLREF uint4 process_id; +GBLREF node_local_ptr_t locknl; +GBLREF boolean_t mupip_jnl_recover; + +error_def(ERR_CRITRESET); +error_def(ERR_DBCCERR); +error_def(ERR_DBFLCORRP); + +boolean_t grab_crit_immediate(gd_region *reg) +{ + unix_db_info *udi; + sgmnt_addrs *csa; + sgmnt_data_ptr_t csd; + node_local_ptr_t cnl; + enum cdb_sc status; + mutex_spin_parms_ptr_t mutex_spin_parms; + + udi = FILE_INFO(reg); + csa = &udi->s_addrs; + csd = csa->hdr; + cnl = csa->nl; + if (!csa->now_crit) + { + assert(0 == crit_count); + crit_count++; /* prevent interrupts */ + DEBUG_ONLY(locknl = cnl;) /* for DEBUG_ONLY LOCK_HIST macro */ + mutex_spin_parms = (mutex_spin_parms_ptr_t)&csd->mutex_spin_parms; + status = mutex_lockwim(reg, mutex_spin_parms, crash_count); + DEBUG_ONLY(locknl = NULL;) /* restore "locknl" to default value */ + if (status != cdb_sc_normal) + { + crit_count = 0; + switch (status) + { + case cdb_sc_nolock: + return(FALSE); + case cdb_sc_critreset: + rts_error(VARLSTCNT(4) ERR_CRITRESET, 2, REG_LEN_STR(reg)); + case cdb_sc_dbccerr: + rts_error(VARLSTCNT(4) ERR_DBCCERR, 2, REG_LEN_STR(reg)); + default: + GTMASSERT; + } + return(FALSE); + } + /* There is only one case we know of when cnl->in_crit can be non-zero and that is when a process holding + * crit gets kill -9ed and another process ends up invoking "secshr_db_clnup" which in turn clears the + * crit semaphore (making it available for waiters) but does not also clear cnl->in_crit since it does not + * hold crit at that point. But in that case, the pid reported in cnl->in_crit should be dead. Check that. + */ + assert((0 == cnl->in_crit) || (FALSE == is_proc_alive(cnl->in_crit, 0))); + cnl->in_crit = process_id; + CRIT_TRACE(crit_ops_gw); /* see gdsbt.h for comment on placement */ + crit_count = 0; + } + else + assert(FALSE); + if (csd->file_corrupt && !mupip_jnl_recover) + { + if (!IS_DSE_IMAGE) + rts_error(VARLSTCNT(4) ERR_DBFLCORRP, 2, DB_LEN_STR(reg)); + else + gtm_putmsg(VARLSTCNT(4) MAKE_MSG_WARNING(ERR_DBFLCORRP), 2, DB_LEN_STR(reg)); + } + /* Ideally we do not want to do wcs_recover if we are in interrupt code (as opposed to mainline code). + * This is easily accomplished in VMS with a library function lib$ast_in_prog but in Unix there is no way + * to tell mainline code from interrupt code without the caller providing that information. Hence we + * currently do the cache recovery even in case of interrupt code even though it is a heavyweight operation. + * If it is found to cause issues, this logic has to be re-examined. + */ + if (cnl->wc_blocked) + wcs_recover(reg); + return(TRUE); +} + diff --git a/sr_unix/gt_timers_add_safe_hndlrs.c b/sr_unix/gt_timers_add_safe_hndlrs.c new file mode 100644 index 0000000..736b668 --- /dev/null +++ b/sr_unix/gt_timers_add_safe_hndlrs.c @@ -0,0 +1,29 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gt_timer.h" +#include "gt_timers_add_safe_hndlrs.h" +#include "heartbeat_timer.h" +#include "semwt2long_handler.h" +#include "secshr_client.h" + +/* This optional routine adds entries to the safe_handlers[] array. It is separate because while most executables need + * these timers listed, there is one executable (gtmsecshr) that decidedly does not - gtmsecshr. If these routines are + * part of gtmsecshr, they cause large numers of other routines that should definitely not be part of a root privileged + * executable to be pulled in. + */ + +void gt_timers_add_safe_hndlrs(void) +{ + add_safe_timer_handler(3, semwt2long_handler, client_timer_handler, heartbeat_timer); +} diff --git a/sr_unix/gt_timers_add_safe_hndlrs.h b/sr_unix/gt_timers_add_safe_hndlrs.h new file mode 100644 index 0000000..e28ad28 --- /dev/null +++ b/sr_unix/gt_timers_add_safe_hndlrs.h @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef GT_TIMERS_ADD_SAFE_HNDLRS_INCLUDED +#define GT_TIMERS_ADD_SAFE_HNDLRS_INCLUDED + +void gt_timers_add_safe_hndlrs(void); + +#endif diff --git a/sr_unix/gtm_asm_establish.c b/sr_unix/gtm_asm_establish.c new file mode 100644 index 0000000..b80f7d0 --- /dev/null +++ b/sr_unix/gtm_asm_establish.c @@ -0,0 +1,24 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#include "mdef.h" + +#include "error.h" /* Declares all needed globals */ + +void gtm_asm_establish(void); /* Only needs to be declared here as is only called from assembler routines */ + +/* This routine is called from assembler routines (basically dm_start) who need to do an ESTABLISH. We do all of the ESTABLISH + * here except for the actual setjmp() call which needs to be in the assembler macro itself. + */ + +void gtm_asm_establish(void) +{ + GTM_ASM_ESTABLISH; +} diff --git a/sr_unix/gtm_c_stack_trace.c b/sr_unix/gtm_c_stack_trace.c new file mode 100644 index 0000000..83e5203 --- /dev/null +++ b/sr_unix/gtm_c_stack_trace.c @@ -0,0 +1,147 @@ +/**************************************************************** +* * +* Copyright 2012, 2013 Fidelity Information Services, Inc * +* * +* This source code contains the intellectual property * +* of its copyright holder(s), and is made available * +* under a license. If you do not know the terms of * +* the license, please stop and do not read further. * +* * +****************************************************************/ + +#include "mdef.h" + +#include +#include +#include +#include +#include "gtm_stdio.h" /* For SPRINTF */ +#include "gtm_string.h" +#include "send_msg.h" +#include "wbox_test_init.h" +#include "gt_timer.h" +#include "gtm_logicals.h" +#include "trans_log_name.h" +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "gtm_c_stack_trace.h" +#include "jobsp.h" /* for MAX_PIDSTR_LEN */ +#include "gtm_limits.h" + +error_def(ERR_STUCKACT); +error_def(ERR_SYSCALL); +error_def(ERR_TEXT); + +/* This looks up the environment variable gtm_procstuckexec, adds the calling information to it, passes it to a SYSTEM call + * and checks the returns from both the system and the invoked shell command + */ +void gtm_c_stack_trace(char *message, pid_t waiting_pid, pid_t blocking_pid, uint4 count) +{ + int4 messagelen, arr_len; + char *command; + char *currpos; + int save_errno; + mstr envvar_logical, trans; + char buf[GTM_PATH_MAX]; + int status; +# ifdef _BSD + union wait wait_stat; +# else + int4 wait_stat; +# endif + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + messagelen = STRLEN(message); + assert(SIZEOF(count) <= SIZEOF(pid_t)); + arr_len = GTM_MAX_DIR_LEN + messagelen + (3 * MAX_PIDSTR_LEN) + 5; /* 4 spaces and a terminator */ + if (!(TREF(gtm_waitstuck_script)).len) + { /* uninitialized buffer - translate logical and move it to the buffer */ + envvar_logical.addr = GTM_PROCSTUCKEXEC; + envvar_logical.len = SIZEOF(GTM_PROCSTUCKEXEC) - 1; + if (SS_NORMAL == (status = TRANS_LOG_NAME(&envvar_logical, &trans, buf, SIZEOF(buf), do_sendmsg_on_log2long))) + { /* the environmental variable is defined */ + assert(SIZEOF(buf) > trans.len); + if (0 != trans.len) + { /* and it has a value - stick the length of the translation in char_len of mstr */ + (TREF(gtm_waitstuck_script)).len = trans.len + arr_len; + (TREF(gtm_waitstuck_script)).addr + = (char *)malloc((TREF(gtm_waitstuck_script)).len); + memcpy((TREF(gtm_waitstuck_script)).addr, trans.addr, trans.len); + *(char *)((TREF(gtm_waitstuck_script)).addr + trans.len) = ' '; + trans.len += 1; + (TREF(gtm_waitstuck_script)).char_len = trans.len; /* abuse of mstr to hold second length */ + } + } + } else + { /* already have a pointer to the shell command get its length */ + trans.len = (TREF(gtm_waitstuck_script)).char_len; + assert(0 < trans.len); + if ((trans.len + arr_len) > (TREF(gtm_waitstuck_script)).len) + { /* new message doesn't fit - malloc fresh space and free the old */ + (TREF(gtm_waitstuck_script)).len = trans.len + arr_len; + trans.addr = (char *)malloc((TREF(gtm_waitstuck_script)).len); + memcpy(trans.addr, (TREF(gtm_waitstuck_script)).addr, trans.len); + free((TREF(gtm_waitstuck_script)).addr); + (TREF(gtm_waitstuck_script)).addr = trans.addr; + } + } + if (0 != (TREF(gtm_waitstuck_script)).len) + { /* have a command and a message */ + command = (TREF(gtm_waitstuck_script)).addr; + currpos = command + trans.len; + memcpy(currpos, message, messagelen); + currpos += messagelen; + *currpos++ = ' '; + currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)waiting_pid); + *currpos++ = ' '; + currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)blocking_pid); + *currpos++ = ' '; + currpos = (char *)i2asc((unsigned char*)currpos, (unsigned int)count); + *currpos++ = 0; + assert(currpos - (TREF(gtm_waitstuck_script)).addr <= (TREF(gtm_waitstuck_script)).len); + status = SYSTEM(((char *)((TREF(gtm_waitstuck_script)).addr))); + if (-1 == status) + { /* SYSTEM failed */ + save_errno = errno; + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, LEN_AND_LIT("FAILURE"), LEN_AND_STR(command)); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT("system"), CALLFROM, save_errno); + } else + { /* check on how the command did */ + assert(SIZEOF(wait_stat) == SIZEOF(int4)); +# ifdef _BSD + wait_stat.w_status = status; +# else + wait_stat = status; +# endif + if (WIFEXITED(wait_stat)) + { + status = WEXITSTATUS(wait_stat); + if (!status) + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, + LEN_AND_LIT("SUCCESS"), LEN_AND_STR(command)); + else + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, + LEN_AND_LIT("FAILURE"), LEN_AND_STR(command)); + if (WIFSIGNALED(wait_stat)) + { + status = WTERMSIG(wait_stat); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + LEN_AND_LIT("PROCSTUCK terminated by signal"), CALLFROM, status); + } else + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + LEN_AND_LIT("PROCSTUCK"), CALLFROM, status); + } + } else + { /* it's gone rogue' */ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(6) ERR_STUCKACT, 4, + LEN_AND_LIT("FAILURE"), LEN_AND_STR(command)); + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(8) ERR_SYSCALL, 5, + LEN_AND_LIT("PROCSTUCK did not report status"), CALLFROM, status); + assert(FALSE); + } + } + } +} diff --git a/sr_unix/gtm_conv_init.c b/sr_unix/gtm_conv_init.c new file mode 100644 index 0000000..b1b58e9 --- /dev/null +++ b/sr_unix/gtm_conv_init.c @@ -0,0 +1,100 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "gtm_caseconv.h" +#include "gtm_utf8.h" +#include "gtm_conv.h" + +GBLREF UConverter *chset_desc[CHSET_MAX_IDX]; +GBLREF casemap_t casemaps[MAX_CASE_IDX]; +GBLREF u_casemap_t gtm_strToTitle_ptr; /* Function pointer for gtm_strToTitle */ + +LITREF mstr chset_names[CHSET_MAX_IDX_ALL]; + +/* Note these routines are separated from gtm_conv.c to avoid pulling into gtmsecshr all the stuff the conversion modules use */ + +error_def(ERR_ICUERROR); + +/* Startup initializations of conversion data */ +void gtm_conv_init(void) +{ + assert(gtm_utf8_mode); + /* Implicitly created CHSET descriptor for UTF-8 */ + get_chset_desc(&chset_names[CHSET_UTF8]); + assert(NULL != chset_desc[CHSET_UTF8]); + /* initialize the case conversion disposal functions */ + casemaps[0].u = u_strToUpper; + casemaps[1].u = u_strToLower; + casemaps[2].u = gtm_strToTitle_ptr; +} + +UConverter* get_chset_desc(const mstr* chset) +{ + int chset_indx; + UErrorCode status; + + if ((0 >= (chset_indx = verify_chset(chset))) || (CHSET_MAX_IDX <= chset_indx)) + return NULL; + if (NULL == chset_desc[chset_indx]) + { + status = U_ZERO_ERROR; + chset_desc[chset_indx] = ucnv_open(chset_names[chset_indx].addr, &status); + if (U_FAILURE(status)) + rts_error(VARLSTCNT(3) ERR_ICUERROR, 1, status); /* strange and unexpected ICU unhappiness */ + /* Initialize the callback for illegal/invalid characters, so that conversion + * stops at the first illegal character rather than continuing with replacement */ + status = U_ZERO_ERROR; + ucnv_setToUCallBack(chset_desc[chset_indx], &callback_stop, NULL, NULL, NULL, &status); + if (U_FAILURE(status)) + rts_error(VARLSTCNT(3) ERR_ICUERROR, 1, status); /* strange and unexpected ICU unhappiness */ + } + return chset_desc[chset_indx]; +} + +/* Routine to verify given parameter against supported CHSETs. + * Valid arguments (case-insensitive): + * "M", "UTF-8", "UTF-16", "UTF-16LE" and "UTF-16BE" + * Returns + * -1 (if invalid argument) or + * 0 (if "M") or + * non-zero index to an entry of chset_names[] (if valid) + */ +int verify_chset(const mstr *parm) +{ + const mstr *vptr, *vptr_top; + char mode[MAX_CHSET_LEN]; + + if ((MIN_CHSET_LEN > parm->len) || (MAX_CHSET_LEN < parm->len)) + return -1; /* Parameter is smaller or larger than any possible CHSET */ + /* Make a translated copy of the parm */ + lower_to_upper((unsigned char *)mode, (unsigned char *)parm->addr, parm->len); + /* See if any of our possibilities match */ + for (vptr = chset_names, vptr_top = vptr + CHSET_MAX_IDX_ALL; vptr < vptr_top; ++vptr) + { + if (parm->len == vptr->len && + 0 == memcmp(mode, vptr->addr, vptr->len)) + return (int)(vptr - chset_names); /* return the index */ + } + return -1; +} + +void callback_stop(const void* context, UConverterToUnicodeArgs *args, const char *codeUnits, + int32_t length, UConverterCallbackReason reason, UErrorCode *pErrorCode) +{ + /* EMPTY BODY: + * By not resetting the pErrorCode, this routine returns to ICU routine directing + * it to stop and return immediately + */ +} diff --git a/sr_unix/gtm_system.c b/sr_unix/gtm_system.c new file mode 100644 index 0000000..76f2850 --- /dev/null +++ b/sr_unix/gtm_system.c @@ -0,0 +1,88 @@ +/**************************************************************** +* * +* Copyright 2013 Fidelity Information Services, Inc * +* * +* This source code contains the intellectual property * +* of its copyright holder(s), and is made available * +* under a license. If you do not know the terms of * +* the license, please stop and do not read further. * +* * +****************************************************************/ +#include "mdef.h" +#include +#include +#include "have_crit.h" +#include "fork_init.h" +#include "gtm_unistd.h" +#include "gtm_stdlib.h" +#include "eintr_wrappers.h" + +#define RESTOREMASK \ +{ \ + sigaction(SIGINT, &old_intrpt, NULL); \ + sigaction(SIGQUIT, &old_quit, NULL); \ + sigprocmask(SIG_SETMASK, &savemask, NULL); \ +} + +int gtm_system(const char *cmdline) +{ + struct sigaction ignore, old_intrpt, old_quit; + sigset_t mask, savemask; + pid_t pid; + int stat; /* child exit status */ + int ret; /* return value from waitpid */ + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + DEFER_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + + sigemptyset(&ignore.sa_mask); + ignore.sa_handler = SIG_IGN; + ignore.sa_flags = 0; + + if (sigaction(SIGINT, &ignore, &old_intrpt)) + { + ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + return -1; + } + if (sigaction(SIGQUIT, &ignore, &old_quit)) + { + sigaction(SIGINT, &old_intrpt, NULL); + ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + return -1; + } + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &mask, &savemask)) + { + sigaction(SIGINT, &old_intrpt, NULL); + sigaction(SIGQUIT, &old_quit, NULL); + ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + return -1; + } + + /* Below FORK is not used as interrupts are already disabled at the + * beginning of this function + */ + pid = fork(); /* BYPASSOK */ + if (0 > pid) + { + RESTOREMASK; + ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + return -1; + } + else if (0 == pid) + { + RESTOREMASK; + execl("/bin/sh", "sh", "-c", cmdline, (char *)0); + _exit(127); + } else + { + ENABLE_INTERRUPTS(INTRPT_IN_FORK_OR_SYSTEM); + WAITPID(pid, &stat, 0, ret); + if ((-1 == ret) && (EINTR != errno)) + stat = -1; + RESTOREMASK; + return stat; + } +} diff --git a/sr_unix/gtmdbgflags.h b/sr_unix/gtmdbgflags.h new file mode 100644 index 0000000..6b9903f --- /dev/null +++ b/sr_unix/gtmdbgflags.h @@ -0,0 +1,49 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef _GTMDBGFLAGS_H +#define _GTMDBGFLAGS_H + +#ifdef GTMDBGFLAGS_ENABLED +# define GTMDBGFLAGS_MASK_SET(MASK) (TREF(gtmdbgflags) & MASK) +# define GTMDBGFLAGS_ONLY(MASK, ...) \ +{ \ + DCL_THREADGBL_ACCESS; \ + \ + SETUP_THREADGBL_ACCESS; \ + if (GTMDBGFLAGS_MASK_SET(MASK)) \ + { \ + (TREF(gtmdbgflags_freq_cntr))++; \ + if (TREF(gtmdbgflags_freq) == TREF(gtmdbgflags_freq_cntr)) \ + { \ + __VA_ARGS__; \ + TREF(gtmdbgflags_freq_cntr) = 0; \ + } \ + } \ +} +# define GTMDBGFLAGS_NOFREQ_ONLY(MASK, ...) \ +{ \ + DCL_THREADGBL_ACCESS; \ + \ + SETUP_THREADGBL_ACCESS; \ + if (GTMDBGFLAGS_MASK_SET(MASK)) \ + { \ + __VA_ARGS__; \ + } \ +} +# define GTMSOURCE_FORCE_READ_FILE_MODE 0x00000001 +#else +# define GTMDBGFLAGS_MASK_SET(MASK) FALSE +# define GTMDBGFLAGS_ONLY(MASK, FREQ, ...) +# define GTMDBGFLAGS_NOFREQ_ONLY(MASK, ...) +#endif + +#endif diff --git a/sr_unix/gtmsource_freeze.c b/sr_unix/gtmsource_freeze.c new file mode 100644 index 0000000..153d166 --- /dev/null +++ b/sr_unix/gtmsource_freeze.c @@ -0,0 +1,65 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "gdsroot.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "repl_msg.h" +#include "gtmsource.h" +#include "repl_sem.h" +#include "repl_shutdcode.h" +#include "filestruct.h" +#include "util.h" + +GBLREF jnlpool_addrs jnlpool; +GBLREF gtmsource_options_t gtmsource_options; +GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS]; + +error_def(ERR_REPLINSTFREEZECOMMENT); +error_def(ERR_REPLINSTFROZEN); +error_def(ERR_REPLINSTUNFROZEN); + +int gtmsource_showfreeze(void) +{ + boolean_t instance_frozen; + + assert(!holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); + instance_frozen = jnlpool.jnlpool_ctl->freeze; + util_out_print("Instance Freeze: !AZ", TRUE, instance_frozen ? "ON" : "OFF"); + if (jnlpool.jnlpool_ctl->freeze) + util_out_print(" Freeze Comment: !AZ", TRUE, jnlpool.jnlpool_ctl->freeze_comment); + return (instance_frozen ? (SRV_ERR + NORMAL_SHUTDOWN) : NORMAL_SHUTDOWN); +} + +int gtmsource_setfreeze(void) +{ + if (gtmsource_options.freezeval) + { + assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); + grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, ASSERT_NO_ONLINE_ROLLBACK); /* sets gtmsource_state */ + } else + assert(!holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); + jnlpool.jnlpool_ctl->freeze = gtmsource_options.freezeval; + if (gtmsource_options.setcomment) + STRNCPY_STR(jnlpool.jnlpool_ctl->freeze_comment, gtmsource_options.freeze_comment, + SIZEOF(jnlpool.jnlpool_ctl->freeze_comment)); + if (gtmsource_options.freezeval) + { + send_msg(VARLSTCNT(3) ERR_REPLINSTFROZEN, 1, jnlpool.repl_inst_filehdr->inst_info.this_instname); + send_msg(VARLSTCNT(3) ERR_REPLINSTFREEZECOMMENT, 1, jnlpool.jnlpool_ctl->freeze_comment); + rel_lock(jnlpool.jnlpool_dummy_reg); + } else + { + send_msg(VARLSTCNT(3) ERR_REPLINSTUNFROZEN, 1, jnlpool.repl_inst_filehdr->inst_info.this_instname); + } + return (NORMAL_SHUTDOWN); +} diff --git a/sr_unix/iott_iocontrol.c b/sr_unix/iott_iocontrol.c new file mode 100644 index 0000000..10ae0cb --- /dev/null +++ b/sr_unix/iott_iocontrol.c @@ -0,0 +1,54 @@ +/**************************************************************** + * * + * Copyright 2001, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include +#include "gtm_inet.h" + +#include "gtm_string.h" +#include "io.h" +#include "iotcpdef.h" + +GBLREF io_pair io_curr_device; + +void iott_iocontrol(mstr *d) +{ + return; +} + +void iott_dlr_device(mstr *d) +{ + io_desc *iod; + int len; + + iod = io_curr_device.out; + len = STRLEN(iod->dollar.device); + /* verify internal buffer has enough space for $DEVICE string value */ + assert((int)d->len > len); + memcpy(d->addr, iod->dollar.device, len); + d->len = len; + return; +} + +void iott_dlr_key(mstr *d) +{ + io_desc *iod; + int len; + + iod = io_curr_device.out; + len = STRLEN(iod->dollar.key); + /* verify internal buffer has enough space for $KEY string value */ + assert((int)d->len > len); + memcpy(d->addr, iod->dollar.key, len); + d->len = len; + return; +} diff --git a/sr_unix/mu_replpool_release_sem.c b/sr_unix/mu_replpool_release_sem.c new file mode 100644 index 0000000..c3e32b7 --- /dev/null +++ b/sr_unix/mu_replpool_release_sem.c @@ -0,0 +1,186 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_ipc.h" +#include "gtm_unistd.h" +#include "gtm_string.h" +#include "gtm_inet.h" +#include "gtm_fcntl.h" + +#include +#include +#include + +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "iosp.h" +#include "gtmrecv.h" +#include "repl_msg.h" +#include "gtmsource.h" +#include "gtm_logicals.h" +#include "jnl.h" +#include "repl_sem.h" +#include "repl_shutdcode.h" +#include "io.h" +#include "trans_log_name.h" +#include "repl_instance.h" +#include "gtmmsg.h" +#include "gtm_sem.h" +#include "mu_rndwn_replpool.h" +#include "ftok_sems.h" +#include "anticipatory_freeze.h" + +#define DO_CLNUP_AND_RETURN(SAVE_ERRNO, INSTFILENAME, INSTFILELEN, SEM_ID, FAILED_OP) \ +{ \ + gtm_putmsg(VARLSTCNT(5) ERR_REPLACCSEM, 3, SEM_ID, INSTFILELEN, INSTFILENAME); \ + gtm_putmsg(VARLSTCNT(8) ERR_SYSCALL, 5, LEN_AND_LIT(FAILED_OP), CALLFROM, SAVE_ERRNO); \ + return -1; \ +} + +GBLREF jnlpool_addrs jnlpool; +GBLREF recvpool_addrs recvpool; +GBLREF gd_region *gv_cur_region; +GBLREF jnl_gbls_t jgbl; +GBLREF boolean_t holds_sem[NUM_SEM_SETS][NUM_SRC_SEMS]; +GBLREF boolean_t argumentless_rundown; + +error_def(ERR_REPLACCSEM); + +int mu_replpool_release_sem(repl_inst_hdr_ptr_t repl_inst_filehdr, char pool_type, boolean_t remove_sem) +{ + int save_errno, instfilelen, status, sem_id, semval; + uint4 semnum; + char *instfilename; + gd_region *replreg; +# ifdef DEBUG + unix_db_info *udi; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; +# endif + assert((NULL != jnlpool.jnlpool_dummy_reg) && (jnlpool.jnlpool_dummy_reg == recvpool.recvpool_dummy_reg)); + replreg = jnlpool.jnlpool_dummy_reg; + DEBUG_ONLY(udi = FILE_INFO(jnlpool.jnlpool_dummy_reg)); + assert(udi->grabbed_ftok_sem || jgbl.mur_rollback); /* Rollback already holds standalone access so no need for ftok lock */ + instfilename = (char *)replreg->dyn.addr->fname; + instfilelen = replreg->dyn.addr->fname_len; + assert((NULL != instfilename) && (0 != instfilelen) && ('\0' == instfilename[instfilelen])); + assert((JNLPOOL_SEGMENT == pool_type) || (RECVPOOL_SEGMENT == pool_type)); + if (JNLPOOL_SEGMENT == pool_type) + { + sem_id = repl_inst_filehdr->jnlpool_semid; + semval = semctl(sem_id, SRC_SERV_COUNT_SEM, GETVAL); + /* mu_replpool_grab_sem always increments the counter semaphore. So, it should be 1 at this point. In addition, + * if not ONLINE ROLLBACK or RUNDOWN with Anticipatory Freeze, we wait for the counter to become zero before + * grabbing it. The only exception where semval can be greater than 1 is if we are ONLINE ROLLBACK or RUNDOWN -REG + * with anticipatory freeze scheme in effect. + */ + assert((1 == semval) || ((1 <= semval) + && (jgbl.onlnrlbk || (!jgbl.mur_rollback && !argumentless_rundown && ANTICIPATORY_FREEZE_AVAILABLE)))); + remove_sem &= (1 == semval); /* we can remove the sem if the caller intends to and the counter semaphore is 1 */ + if (0 < semval) + { + status = decr_sem(SOURCE, SRC_SERV_COUNT_SEM); + if (SS_NORMAL != status) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()"); + } + } else if (-1 == semval) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()"); + } + holds_sem[SOURCE][SRC_SERV_COUNT_SEM] = FALSE; + assert(holds_sem[SOURCE][JNL_POOL_ACCESS_SEM]); + assert(1 == semctl(sem_id, JNL_POOL_ACCESS_SEM, GETVAL)); /* we hold the access control semaphore */ + status = rel_sem_immediate(SOURCE, JNL_POOL_ACCESS_SEM); + assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */ + holds_sem[SOURCE][JNL_POOL_ACCESS_SEM] = FALSE; + /* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the + * system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be + * 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are + * ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server + * startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting + * on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access + * control and let the waiting process do the clean up. + */ + if (remove_sem) + { + status = remove_sem_set(SOURCE); + if (SS_NORMAL != status) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()"); + } + repl_inst_filehdr->jnlpool_semid = INVALID_SEMID; + repl_inst_filehdr->jnlpool_semid_ctime = 0; + } + } else + { + sem_id = repl_inst_filehdr->recvpool_semid; + for (semnum = RECV_SERV_COUNT_SEM; semnum <= UPD_PROC_COUNT_SEM; semnum++) + { + semval = semctl(sem_id, semnum, GETVAL); + assert((1 == semval) || jgbl.onlnrlbk); + remove_sem &= (1 == semval); + if (0 < semval) + { + status = decr_sem(RECV, semnum); + if (SS_NORMAL != status) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semop()"); + } + } else if (-1 == semval) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "semctl()"); + } + holds_sem[RECV][semnum] = FALSE; + } + assert(holds_sem[RECV][RECV_POOL_ACCESS_SEM] && holds_sem[RECV][RECV_SERV_OPTIONS_SEM]); + assert(1 == semctl(sem_id, RECV_POOL_ACCESS_SEM, GETVAL) && (1 == semctl(sem_id, RECV_SERV_OPTIONS_SEM, GETVAL))); + status = rel_sem_immediate(RECV, RECV_SERV_OPTIONS_SEM); + assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */ + status = rel_sem_immediate(RECV, RECV_POOL_ACCESS_SEM); + assert(SS_NORMAL == status); /* We hold it. So, we should be able to release it */ + holds_sem[RECV][RECV_POOL_ACCESS_SEM] = FALSE; + holds_sem[RECV][RECV_SERV_OPTIONS_SEM] = FALSE; + /* Now that we have released the access control semaphore, see if we can remove the semaphore altogether from the + * system. For this, we should be holding the FTOK on the replication instance AND the counter semaphore should be + * 0. If we are called from mu_rndwn_repl_instance, we are guaranteed we will be holding the FTOK. But, if we are + * ROLLBACK (online or noonline), we need not hold the FTOK, if somebody else (possibly a source or receiver server + * startup command) is holding it. In that case, we don't remove the semaphore, because any process that is waiting + * on the access control will now get an EIDRM error which is NOT user friendly. So, just release the access + * control and let the waiting process do the clean up. + */ + if (remove_sem) + { + status = remove_sem_set(RECV); + if (SS_NORMAL != status) + { + save_errno = errno; + DO_CLNUP_AND_RETURN(save_errno, instfilename, instfilelen, sem_id, "sem_rmid()"); + } + repl_inst_filehdr->recvpool_semid = INVALID_SEMID; + repl_inst_filehdr->recvpool_semid_ctime = 0; + } + } + return SS_NORMAL; +} diff --git a/sr_unix/mu_size_arsample.c b/sr_unix/mu_size_arsample.c new file mode 100644 index 0000000..fdcf001 --- /dev/null +++ b/sr_unix/mu_size_arsample.c @@ -0,0 +1,400 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "cdb_sc.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gdsblkops.h" +#include "gdskill.h" +#include "gdscc.h" +#include "copy.h" +#include "interlock.h" +#include "muextr.h" +#include "mu_reorg.h" + +/* Include prototypes */ +#include "t_end.h" +#include "t_retry.h" +#include "mupip_size.h" +#include "util.h" +#include "t_begin.h" +#include "op.h" +#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */ +#include "gvcst_bmp_mark_free.h" +#include "gvcst_kill_sort.h" +#include "gtmmsg.h" +#include "add_inter.h" +#include "t_abort.h" +#include "sleep_cnt.h" +#include "wcs_sleep.h" +#include "memcoherency.h" + +#include "gtm_time.h" +#include "mvalconv.h" +#include "t_qread.h" +#include "longset.h" /* needed for cws_insert.h */ +#include "hashtab_int4.h" +#include "cws_insert.h" +#include "min_max.h" +#include + +error_def(ERR_GBLNOEXIST); +error_def(ERR_MUSIZEFAIL); + +GBLREF bool mu_ctrlc_occurred; +GBLREF bool mu_ctrly_occurred; +GBLREF sgmnt_addrs *cs_addrs; +GBLREF sgmnt_data_ptr_t cs_data; +GBLREF gv_namehead *gv_target; +GBLREF unsigned int t_tries; +GBLREF int4 process_id; +GBLREF inctn_opcode_t inctn_opcode; +GBLREF unsigned char rdfail_detail; + +#define MAX_RECS_PER_BLK 65535 +#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */ +#define EPS 1e-6 +#define APPROX_F_MAX 500 /* Approximate upper bound for the number of records per index block in + * a realistic database. + */ +#define DYNAMIC_F_MAX 10 /* Choice of these two constants relates to choice of APPROX_F_MAX */ +#define EXTRA_F_MAX 50 +#define SQR(X) ((double)(X) * (double)(X)) +#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */ + +typedef struct +{ /* cumulative running stats */ + int n; /* number of previous traversals */ + int N[MAX_BT_DEPTH + 1]; /* number of accepted samples at each given level (more are likely for higher levels) */ + double M[MAX_BT_DEPTH + 1]; /* M[j] := mean of r[j]'s over previous n traversals + * Note: M_n = M_{n-1} + (r_n - M_{n-1}) / n + */ + double S[MAX_BT_DEPTH + 1]; /* S[j] := sum of (r_i[j] - M[j])^2 over each previous traversal, i=1..n + * Note: S_n = S_{n-1} + (r_n - M_n) * (r_n - M_{n-1}) + * Later, S values are divided by number of samples to give a plugin estimate of variance + * and subsequently are divided by the sample size to give the variance of the mean + */ + double f_max[MAX_BT_DEPTH + 1]; /* estimated max fanning factor */ + double r_max[MAX_BT_DEPTH + 1]; /* max records found in a block at a given level */ + /* Final estimates */ + double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */ + double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */ + double rectot[MAX_BT_DEPTH + 1]; /* estimated #records at each level */ + double B; /* estimated total blocks */ + double error; /* approximate error in estimate B */ + double R; /* estimated total records */ +} stat_t; + +STATICFNDCL void finalize_stats_ar(stat_t *stat, boolean_t ar); +STATICFNDCL void accum_stats_ar(stat_t *stat, double *r, boolean_t ar); + +#define CLEAR_VECTOR(v) \ +{ \ + int j; \ + \ + for (j = 0; j <= MAX_BT_DEPTH; j++) \ + v[j] = 0; \ +} +#define INIT_STATS(stat) \ +{ \ + int j; \ + \ + stat.n = 0; \ + for (j = 0; j <= MAX_BT_DEPTH; j++) \ + { \ + stat.f_max[j] = APPROX_F_MAX; \ + stat.r_max[j] = 1; \ + } \ + CLEAR_VECTOR(stat.N); \ + CLEAR_VECTOR(stat.M); \ + CLEAR_VECTOR(stat.S); \ + CLEAR_VECTOR(stat.blktot); \ + CLEAR_VECTOR(stat.blkerr); \ + CLEAR_VECTOR(stat.rectot); \ +} + + +int4 mu_size_arsample(mval *gn, uint4 M, boolean_t ar, int seed) +{ + enum cdb_sc status; + trans_num ret_tn; + int k, h; + boolean_t verify_reads; + boolean_t tn_aborted; + unsigned int lcl_t_tries; + double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */ + stat_t rstat, ustat; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + inctn_opcode = inctn_invalid_op; + op_gvname(VARLSTCNT(1) gn); + if (0 == gv_target->root) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + if (!seed) + seed = (int4)(time(0) * process_id); + srand48(seed); + + /* do random traversals until M of them are accepted at level 1 */ + INIT_STATS(rstat); + for (k = 1; rstat.N[1] < M; k++) + { + if (mu_ctrlc_occurred || mu_ctrly_occurred) + return EXIT_ERR; + t_begin(ERR_MUSIZEFAIL, 0); + for (;;) + { + CLEAR_VECTOR(r); + if (cdb_sc_normal != (status = rand_traverse(r))) + { + assert(CDB_STAGNATE > t_tries); + t_retry(status); + continue; + } + gv_target->clue.end = 0; + gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */ + DEBUG_ONLY(lcl_t_tries = t_tries); + if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED))) + { + ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); + if (tn_aborted) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + continue; + } + accum_stats_ar(&rstat, r, ar); + break; + } + } + finalize_stats_ar(&rstat, ar); + + /* display rstat data */ + /* Showing the error as 2 standard deviations which is a 95% confidence interval for the mean number of blocks at + * each level*/ + util_out_print("!/Number of generated samples = !UL", FLUSH, rstat.n); + util_out_print("Number of accepted samples = !UL", FLUSH, rstat.N[1]); + util_out_print("Level Blocks 2 sigma(+/-) % Accepted", FLUSH); + for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--); + for ( ; h > 0; h--) + util_out_print("!5UL !15UL !15UL ~ !3UL% !15UL", FLUSH, h, (int)ROUND(rstat.blktot[h]), + (int)ROUND(sqrt(rstat.blkerr[h])*2), + (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100), + (int)ROUND(100.0*rstat.N[h]/rstat.n) + ); + util_out_print("!5UL !15UL !15UL ~ !3UL% N/A", FLUSH, h, (int)ROUND(rstat.blktot[h]), + (int)ROUND(sqrt(rstat.blkerr[h])*2), + (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0) + ); + util_out_print("Total !15UL !15UL ~ !3UL% N/A", FLUSH, (int)ROUND(rstat.B), + (int)ROUND(sqrt(rstat.error)*2), + (int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0) + ); + + return EXIT_NRM; +} + + +void accum_stats_ar(stat_t *stat, double *r, boolean_t ar) +{ + int j, depth, n; + double random, M0, accept[MAX_BT_DEPTH + 1]; + + ++stat->n; + for (j = MAX_BT_DEPTH; (j >= 0) && (r[j] < EPS); j--) + accept[j] = 0; + depth = j; + assert(depth >= 0); /* r[0] should remain zero since we don't maintain it */ + accept[depth] = 1; /* always accept the root */ + for (j = depth - 1; j >= 1; j--) + { + if (!ar) + accept[j] = 1; /* don't reject anything */ + else if (j == depth - 1) + accept[j] = accept[j + 1]; /* always accept level beneath root, too */ + else + accept[j] = accept[j + 1] * (r[j + 1] / stat->f_max[j + 1]); + } + accept[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */ + + random = drand48(); + for (j = 0; j <= MAX_BT_DEPTH; j++) + { + if (random < accept[j]) + { + n = ++stat->N[j]; + M0 = stat->M[j]; + stat->M[j] += (r[j] - stat->M[j]) / n; + stat->S[j] += (r[j] - stat->M[j]) * (r[j] - M0); + if (n > DYNAMIC_F_MAX) + stat->f_max[j] = stat->r_max[j] + EXTRA_F_MAX; + } + stat->r_max[j] = MAX(stat->r_max[j], r[j]); + } +} + + +void finalize_stats_ar(stat_t *stat, boolean_t ar) +{ + int j; + double factor; + + for (j = 0; j <= MAX_BT_DEPTH; j++) + /* Variance of the mean (mean referes to avg number of records per block) is Var(R)/N where N is samples size */ + if (stat->N[j] > 0) + { + stat->S[j] /= stat->N[j]; + stat->S[j] /= stat->N[j]; + } + stat->N[0] = stat->n; /* for arithmetic below */ + for (j = MAX_BT_DEPTH; (j >= 0) && (stat->M[j] < EPS); j--); + assert(j >= 0); /* stat->M[0] should remain zero since we don't maintain it */ + stat->blktot[j] = 1; + stat->blkerr[j] = 0; + for (j-- ; j >= 0; j--) + { + if (stat->M[j + 1] == 0) + stat->M[j + 1] = EPS; /* remove any chance of division by zero */ + stat->blktot[j] = stat->blktot[j + 1] * stat->M[j + 1]; + /* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */ + stat->blkerr[j] = SQR(stat->M[j + 1])*stat->blkerr[j + 1] + + SQR(stat->blktot[j + 1])*stat->S[j + 1] + stat->blkerr[j + 1]*stat->S[j + 1]; + } + stat->B = 0; + stat->error = 0; + for (j = 0; j <= MAX_BT_DEPTH; j++) + { + stat->B += stat->blktot[j]; + stat->error += stat->blkerr[j]; + } + stat->R = 0; + for (j = 0; j <= MAX_BT_DEPTH; j++) + { + stat->rectot[j] = stat->blktot[j] * stat->M[j]; + stat->R += stat->rectot[j]; + } +} + + +/* + * Performs a random traversal for the sampling methods + */ +enum cdb_sc rand_traverse(double *r) +{ + sm_uc_ptr_t pVal, pTop, pRec, pBlkBase; + register gv_namehead *pTarg; + register srch_blk_status *pCurr; + register srch_hist *pTargHist; + block_id nBlkId; + block_id valBlk[MAX_RECS_PER_BLK]; /* valBlk[j] := value in j-th record of current block */ + unsigned char nLevl; + cache_rec_ptr_t cr; + int cycle; + trans_num tn; + sm_uc_ptr_t buffaddr; + unsigned short nRecLen; + uint4 tmp; + boolean_t is_mm; + int4 random; + int4 rCnt; /* number of entries in valBlk */ + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + is_mm = (dba_mm == cs_data->acc_meth); + pTarg = gv_target; + pTargHist = &gv_target->hist; + /* The following largely mimics gvcst_search/gvcst_search_blk */ + nBlkId = pTarg->root; + tn = cs_addrs->ti->curr_tn; + if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr))) + return (enum cdb_sc)rdfail_detail; + nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl; + if (MAX_BT_DEPTH < (int)nLevl) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_maxlvl; + } + if (0 == (int)nLevl) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_badlvl; + } + pTargHist->depth = (int)nLevl; + pCurr = &pTargHist->h[nLevl]; + (pCurr + 1)->blk_num = 0; + pCurr->tn = tn; + pCurr->cycle = cycle; + pCurr->cr = cr; + for (;;) + { + assert(pCurr->level == nLevl); + pCurr->cse = NULL; + pCurr->blk_num = nBlkId; + pCurr->buffaddr = pBlkBase; + for ( rCnt = 0, pRec = pBlkBase + SIZEOF(blk_hdr), pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz; + pRec != pTop && rCnt < MAX_RECS_PER_BLK; + rCnt++, pRec += nRecLen ) + { /* enumerate records in block */ + GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz); + pVal = pRec + nRecLen - SIZEOF(block_id); + if (nRecLen == 0) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_badoffset; + } + if (pRec + nRecLen > pTop) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_blklenerr; + } + GET_LONG(tmp, pVal); + valBlk[rCnt] = tmp; + } + r[nLevl] = rCnt; + /* randomly select next block */ + random = (int4)(rCnt * drand48()); + random = random & 0x7fffffff; /* to make sure that the sign bit(msb) is off */ + nBlkId = valBlk[random]; + if (is_mm && (nBlkId > cs_addrs->total_blks)) + { + if (cs_addrs->total_blks < cs_addrs->ti->total_blks) + return cdb_sc_helpedout; + else + return cdb_sc_blknumerr; + } + --pCurr; --nLevl; + if (nLevl < 1) + break; + pCurr->tn = cs_addrs->ti->curr_tn; + if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&pCurr->cycle, &pCurr->cr))) + return (enum cdb_sc)rdfail_detail; + if (((blk_hdr_ptr_t)pBlkBase)->levl != nLevl) + { + assert(CDB_STAGNATE > t_tries); + return cdb_sc_badlvl; + } + } + return cdb_sc_normal; +} diff --git a/sr_unix/mu_size_impsample.c b/sr_unix/mu_size_impsample.c new file mode 100644 index 0000000..73a7620 --- /dev/null +++ b/sr_unix/mu_size_impsample.c @@ -0,0 +1,281 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "cdb_sc.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gdsblkops.h" +#include "gdskill.h" +#include "gdscc.h" +#include "copy.h" +#include "interlock.h" +#include "muextr.h" +#include "mu_reorg.h" + +/* Include prototypes */ +#include "t_end.h" +#include "t_retry.h" +#include "mupip_size.h" +#include "util.h" +#include "t_begin.h" +#include "op.h" +#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */ +#include "gvcst_bmp_mark_free.h" +#include "gvcst_kill_sort.h" +#include "gtmmsg.h" +#include "add_inter.h" +#include "t_abort.h" +#include "sleep_cnt.h" +#include "wcs_sleep.h" +#include "memcoherency.h" + +#include "gtm_time.h" +#include "mvalconv.h" +#include "t_qread.h" +#include "longset.h" /* needed for cws_insert.h */ +#include "hashtab_int4.h" +#include "cws_insert.h" +#include + +error_def(ERR_GBLNOEXIST); +error_def(ERR_MUSIZEFAIL); + +GBLREF bool mu_ctrlc_occurred; +GBLREF bool mu_ctrly_occurred; +GBLREF gv_namehead *gv_target; +GBLREF unsigned int t_tries; +GBLREF int4 process_id; +GBLREF inctn_opcode_t inctn_opcode; + +#define MAX_RECS_PER_BLK 65535 +#define MAX_RELIABLE 10000 /* Used to tweak the error estimates */ +#define EPS 1e-6 +#define SQR(X) ((double)(X) * (double)(X)) +#define ROUND(X) ((int)((X) + 0.5)) /* c89 does not have round() and some Solaris machines uses that compiler */ + +typedef struct +{ /* cumulative stats */ + int4 n; /* number of samples */ + double W[MAX_BT_DEPTH + 1]; /* Sum of the importance values of samples for each depth level */ + double w_mu[MAX_BT_DEPTH + 1]; /* The mean of importance values. It is used to calculate w_variance */ + double w_variance[MAX_BT_DEPTH + 1];/* The variance of importance values. It is used to calculate effective sample size */ + double mu[MAX_BT_DEPTH + 1]; /* mu[j] := mean of weighted r[j]'s over previous n traversals. + It is the expected number of records at depth j + * Note: mu_n = mu_{n-1} + w_n/W_n*(r_n - M_{n-1}) + */ + double S[MAX_BT_DEPTH + 1]; /* S[j] := sum of w_i*(r_i[j] - M[j])^2 over previous traversals. + * Note: S_n = S_{n-1} + w_n*(r_n - M_n)*(r_n - M_{n-1}) + * Later, S values are divided by W values to give plugin estimate of the variance. + * Subsequently they are divided by the effective sample size to give the variance + * of the mean + */ + /* Final estimates */ + double blktot[MAX_BT_DEPTH + 1]; /* estimated #blocks at each level */ + double blkerr[MAX_BT_DEPTH + 1]; /* approximate variance of blktot */ + double rectot[MAX_BT_DEPTH + 1]; /* estimated #records at each level */ + double B; /* estimated total blocks */ + double error; /* approximate error in estimate B */ + double R; /* estimated total records */ +} stat_t; + +STATICFNDCL void clear_vector_impsmpl(double *v); +STATICFNDCL void init_stats_impsmpl(stat_t *stat); +STATICFNDCL void finalize_stats_impsmpl(stat_t *stat); +STATICFNDCL void accum_stats_impsmpl(stat_t *stat, double *r); + +STATICFNDEF void clear_vector_impsmpl(double *v) +{ + int j; + for (j = 0; j <= MAX_BT_DEPTH; j++) + v[j] = 0; +} + + +STATICFNDEF void init_stats_impsmpl(stat_t *stat) +{ + stat->n = 0; + clear_vector_impsmpl(stat->W); + clear_vector_impsmpl(stat->w_mu); + clear_vector_impsmpl(stat->w_variance); + clear_vector_impsmpl(stat->mu); + clear_vector_impsmpl(stat->S); + clear_vector_impsmpl(stat->blktot); + clear_vector_impsmpl(stat->blkerr); + clear_vector_impsmpl(stat->rectot); +} + +/* + * Importance Sampling + */ +int4 mu_size_impsample(mval *gn, int4 M, int4 seed) +{ + enum cdb_sc status; + trans_num ret_tn; + int k, h; + boolean_t verify_reads; + boolean_t tn_aborted; + unsigned int lcl_t_tries; + double r[MAX_BT_DEPTH + 1]; /* r[j] is #records in level j block of current traversal */ + stat_t rstat, ustat; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + inctn_opcode = inctn_invalid_op; + op_gvname(VARLSTCNT(1) gn); + if (0 == gv_target->root) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + if (!seed) + seed = (int4)(time(0) * process_id); + srand48(seed); + + /* do M random traversals */ + init_stats_impsmpl(&rstat); + for (k = 1; k <= M; k++) + { + if (mu_ctrlc_occurred || mu_ctrly_occurred) + return EXIT_ERR; + t_begin(ERR_MUSIZEFAIL, 0); + for (;;) + { + clear_vector_impsmpl(r); + if (cdb_sc_normal != (status = rand_traverse(r))) + { + assert(CDB_STAGNATE > t_tries); + t_retry(status); + continue; + } + gv_target->clue.end = 0; + gv_target->hist.h[0] = gv_target->hist.h[1]; /* No level 0 block to validate */ + DEBUG_ONLY(lcl_t_tries = t_tries); + if ((trans_num)0 == (ret_tn = t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED))) + { + ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); + if (tn_aborted) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + continue; + } + accum_stats_impsmpl(&rstat, r); + break; + } + } + finalize_stats_impsmpl(&rstat); + + /* display rstat data + * Showing the error as 2 standard deviations which is a 95% confidence interval for the + * mean number of blocks at each level + */ + util_out_print("Number of generated samples = !UL", FLUSH, rstat.n); + util_out_print("Level Blocks 2 sigma(+/-)", FLUSH); + for (h = MAX_BT_DEPTH; (h >= 0) && (rstat.blktot[h] < EPS); h--); + for ( ; h > 0; h--) + util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]), + (int)ROUND(sqrt(rstat.blkerr[h])*2), + (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0) + ); + util_out_print("!5UL !15UL !15UL ~ !3UL%", FLUSH, h, (int)ROUND(rstat.blktot[h]), + (int)ROUND(sqrt(rstat.blkerr[h])*2), + (int)ROUND(sqrt(rstat.blkerr[h])*2/rstat.blktot[h]*100.0) + ); + util_out_print("Total !15UL !15UL ~ !3UL%", FLUSH, (int)ROUND(rstat.B), + (int)ROUND(sqrt(rstat.error)*2), + (int)ROUND(sqrt(rstat.error)*2/rstat.B*100.0) + ); + + return EXIT_NRM; +} + + +STATICFNDEF void accum_stats_impsmpl(stat_t *stat, double *r) +{ + int l, root_level, n; + double mu0, w_mu0, w[MAX_BT_DEPTH + 1] /* importance */; + + ++stat->n; + for (l = MAX_BT_DEPTH; (l >= 0) && (r[l] < EPS); l--) + w[l] = 0; + root_level = l; + assert(root_level >= 0); + w[root_level] = 1; + for (l = root_level - 1; l >= 1; l--) + w[l] = w[l + 1] * r[l + 1]; /* TODO consider using log to avoid overflow if it becomes an issue */ + w[0] = 0; /* computing #blks (e.g #recs in lvl 1+), not #recs in lvl 0+ */ + + for (l = 1; l <= root_level; l++) + { + stat->W[l] += w[l]; + w_mu0 = stat->w_mu[l]; + stat->w_mu[l] += (w[l] - stat->w_mu[l])/stat->n; + stat->w_variance[l] += (w[l] - stat->w_mu[l])*(w[l] - w_mu0); + mu0 = stat->mu[l]; + stat->mu[l] += w[l]/stat->W[l]*(r[l] - stat->mu[l]); + stat->S[l] += w[l]*(r[l] - stat->mu[l])*(r[l] - mu0); + } +} + + +STATICFNDEF void finalize_stats_impsmpl(stat_t *stat) +{ + int h; + double ess; /* effective sample size */ + + for (h = 1; h <= MAX_BT_DEPTH; h++) + if (stat->W[h] > 0) + { + /* ess = n / ( 1 + Var( w/mu(w) ) ). + * This comes from effective sample size for importance sampling in the literature*/ + ess = stat->n / ( 1 + (stat->w_variance[h]/stat->n)/SQR(stat->w_mu[h]) ); + /* Variance of the mean (mean referes to avg number of records per block) is + * Var(R)/N where N is effective sample size */ + stat->S[h] /= stat->W[h]; + stat->S[h] /= (ess + 1); + } + stat->W[0] = stat->n; /* for arithmetic below */ + for (h = MAX_BT_DEPTH; (h >= 0) && (stat->mu[h] < EPS); h--); + assert(h >= 0); /* stat->mu[0] should remain zero */ + stat->blktot[h] = 1; + stat->blkerr[h] = 0; + for (h-- ; h >= 0; h--) + { + stat->blktot[h] = stat->blktot[h + 1] * stat->mu[h + 1]; + /* Var(XY) assuming X and Y are independent = E[X]^2*Var(Y) + E[Y]^2*Var(X) + Var(X)*Var(Y) */ + stat->blkerr[h] = SQR(stat->mu[h + 1])*stat->blkerr[h + 1] + SQR(stat->blktot[h + 1])*stat->S[h + 1] + + stat->blkerr[h + 1]*stat->S[h + 1]; + } + stat->B = 0; + stat->error = 0; + for (h = 0; h <= MAX_BT_DEPTH; h++) + { + stat->B += stat->blktot[h]; + stat->error += stat->blkerr[h]; + } + stat->R = 0; + for (h = 0; h <= MAX_BT_DEPTH; h++) + { + stat->rectot[h] = stat->blktot[h] * stat->mu[h]; + stat->R += stat->rectot[h]; + } +} diff --git a/sr_unix/mu_size_scan.c b/sr_unix/mu_size_scan.c new file mode 100644 index 0000000..0f7d96d --- /dev/null +++ b/sr_unix/mu_size_scan.c @@ -0,0 +1,354 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "cdb_sc.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gdsblkops.h" +#include "gdskill.h" +#include "gdscc.h" +#include "copy.h" +#include "interlock.h" +#include "muextr.h" + +/* Include prototypes */ +#include "t_end.h" +#include "t_retry.h" +#include "mupip_size.h" +#include "util.h" +#include "t_begin.h" +#include "op.h" +#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */ +#include "gvcst_bmp_mark_free.h" +#include "gvcst_kill_sort.h" +#include "gtmmsg.h" +#include "add_inter.h" +#include "t_abort.h" +#include "sleep_cnt.h" +#include "wcs_sleep.h" +#include "memcoherency.h" + +#include "gtm_time.h" +#include "mvalconv.h" +#include "t_qread.h" +#include "longset.h" /* needed for cws_insert.h */ +#include "hashtab_int4.h" +#include "cws_insert.h" +#include "min_max.h" +#include + +error_def(ERR_GBLNOEXIST); +error_def(ERR_MUSIZEFAIL); +error_def(ERR_MUSIZEINVARG); + +GBLREF bool mu_ctrlc_occurred; +GBLREF bool mu_ctrly_occurred; +GBLREF sgmnt_addrs *cs_addrs; +GBLREF sgmnt_data_ptr_t cs_data; +GBLREF gv_namehead *gv_target; +GBLREF unsigned int t_tries; +GBLREF int4 process_id; +GBLREF inctn_opcode_t inctn_opcode; +GBLREF unsigned char rdfail_detail; + +GBLDEF uint4 total_recs; +GBLDEF uint4 total_scans; +GBLDEF int targ_levl; +GBLDEF INTPTR_T saveoff[MAX_BT_DEPTH + 1]; + +#define ANY_ROOT_LEVL (MAX_BT_DEPTH + 5) /* overload invalid level value */ +#define MAX_RECS_PER_BLK 65535 +#define MAX_SCANS 200000000 /* catch infinite loops */ + +#define GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop) \ +{ \ + status = cdb_sc_normal; \ + GET_USHORT(nRecLen, &((rec_hdr_ptr_t)pRec)->rsiz); \ + if (nRecLen == 0) \ + status = cdb_sc_badoffset; \ + else if (pRec + nRecLen > pTop) \ + status = cdb_sc_blklenerr; \ +} + +#define GET_AND_CHECK_LEVL(status, nLevl, desired_levl, pBlkBase) \ +{ \ + status = cdb_sc_normal; \ + nLevl = ((blk_hdr_ptr_t)pBlkBase)->levl; \ + if (MAX_BT_DEPTH < (int)nLevl) \ + status = cdb_sc_maxlvl; \ + else if (ANY_ROOT_LEVL == desired_levl) \ + { \ + if (0 == (int)nLevl) \ + status = cdb_sc_badlvl; \ + } else if (desired_levl !=(int)nLevl) \ + status = cdb_sc_badlvl; \ +} + +#define BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen) for (pTop = pBlkBase + ((blk_hdr_ptr_t)pBlkBase)->bsiz, \ + pRec = pBlkBase + SIZEOF(blk_hdr), i = 0; \ + i < MAX_RECS_PER_BLK && (pRec != pTop); i++, pRec += nRecLen) + +enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs); +enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl); + +int4 mu_size_scan(mval *gn, int4 level) +{ + enum cdb_sc status; + trans_num ret_tn; + int k, h; + boolean_t verify_reads; + boolean_t tn_aborted; + boolean_t equal; + unsigned int lcl_t_tries; + block_id nBlkId; + int4 nLevl; + sm_uc_ptr_t pBlkBase; + int i; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + inctn_opcode = inctn_invalid_op; + op_gvname(VARLSTCNT(1) gn); + if (0 == gv_target->root) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + gv_target->alt_hist->depth = MAX_BT_DEPTH; /* initialize: don't copy to saveoff if restart before a single success */ + total_recs = total_scans = 0; + for (k = 0; k <= MAX_BT_DEPTH; k++) + { + saveoff[k] = 0; + gv_target->hist.h[k].cr = NULL; /* initialize for optimization in read_block which bumps cr refer bits */ + } + targ_levl = 0; + /* Read the root block and convert negative levels to positive. Negative levels are defined to be counted from root with + * -1 being children of root */ + t_begin(ERR_MUSIZEFAIL, 0); + for(;;) + { /* retry loop */ + status = read_block(gv_target->root, &pBlkBase, &nLevl, ANY_ROOT_LEVL); + if (cdb_sc_normal != status) + { + assert(CDB_STAGNATE > t_tries); + t_retry(status); + continue; + } + memcpy(&gv_target->hist.h[0], &gv_target->hist.h[nLevl], SIZEOF(srch_blk_status)); + gv_target->hist.h[1].blk_num = 0; + if ((trans_num)0 == t_end(&gv_target->hist, NULL, TN_NOT_SPECIFIED)){ + lcl_t_tries = TREF(prev_t_tries); + ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); + if (tn_aborted) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + continue; + } + break; + } + if (level < 0) + level += nLevl; + if (level < 0 || nLevl < level) + { + gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.LEVEL")); + return EXIT_ERR; + } + targ_levl = level; + /* Run the dfs down to targ_levl to count records and blocks. Validate every path from root to blocks at targ_levl */ + t_begin(ERR_MUSIZEFAIL, 0); + for (;;) + { /* retry loop. note that multiple successful read transactions can occur within a single iteration */ + nBlkId = gv_target->root; + nLevl = ANY_ROOT_LEVL; + status = read_block(nBlkId, &pBlkBase, &nLevl, ANY_ROOT_LEVL); + if (cdb_sc_normal == status) + status = dfs(nLevl, pBlkBase, TRUE, TRUE); + if (cdb_sc_endtree != status) + { + assert(cdb_sc_normal != status); /* should have continued recursive search */ + if (cdb_sc_restarted != status) + t_retry(status); + lcl_t_tries = TREF(prev_t_tries); + ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); + if (tn_aborted) + { /* Global does not exist (online rollback). Not an error. */ + gtm_putmsg(VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return EXIT_NRM; + } + /* update saveoff */ + if (gv_target->alt_hist->depth < MAX_BT_DEPTH) + { + for (i = targ_levl; i <= gv_target->alt_hist->depth; i++) + saveoff[i] = gv_target->alt_hist->h[i - targ_levl].curr_rec.offset; + } + continue; + } + break; + } + util_out_print("Level Blocks Records", FLUSH); + util_out_print("!5UL !15UL !16UL", FLUSH, level, total_scans, total_recs); + if (mu_ctrlc_occurred || mu_ctrly_occurred) + return EXIT_ERR; + return EXIT_NRM; +} + +enum cdb_sc dfs(int lvl, sm_uc_ptr_t pBlkBase, boolean_t endtree, boolean_t skiprecs) +{ + int incr_recs = 0, incr_scans = 0; + boolean_t first_iter, last_rec, next_endtree, next_skiprecs; + trans_num ret_tn; + sm_uc_ptr_t pVal, pTop, pRec, child_pBlkBase; + int4 child_nLevl; + unsigned short nRecLen; + int4 i; + enum cdb_sc status; + block_id nBlkId; + int curroff; + cache_rec_ptr_t cr; + srch_hist sibhist; + + assert(total_scans < MAX_SCANS); + if (lvl == targ_levl) + { /* reached the bottom. count records in this block and validate */ + BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen) + { + GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop); + if (cdb_sc_normal != status) + { + assert(CDB_STAGNATE > t_tries); + return status; + } + } + incr_recs = i; + incr_scans = 1; + } else if (lvl > targ_levl) + { /* visit each child */ + first_iter = TRUE; + gv_target->hist.h[lvl - targ_levl].curr_rec.offset = saveoff[lvl]; + BLK_LOOP(i, pRec, pBlkBase, pTop, nRecLen) + { + GET_AND_CHECK_RECLEN(status, nRecLen, pRec, pTop); + if (cdb_sc_normal != status) + { + assert(CDB_STAGNATE > t_tries); + return status; + } + curroff = (INTPTR_T)(pRec - pBlkBase); + gv_target->hist.h[lvl - targ_levl].curr_rec.offset = curroff; + if (skiprecs && (curroff < saveoff[lvl])) + continue; /* skip these guys, we've already counted over there */ + pVal = pRec + nRecLen - SIZEOF(block_id); + GET_LONG(nBlkId, pVal); + status = read_block(nBlkId, &child_pBlkBase, &child_nLevl, lvl - 1); + if (status != cdb_sc_normal) + { + assert(CDB_STAGNATE > t_tries); + return status; + } + last_rec = ((pRec + nRecLen) == pTop); + first_iter = (curroff == saveoff[lvl]); + next_endtree = endtree && last_rec; + next_skiprecs = skiprecs && first_iter; + status = dfs(lvl - 1, child_pBlkBase, next_endtree, next_skiprecs); + if (status != cdb_sc_normal) + return status; + first_iter = FALSE; + } + } + /* make sure we can really move on from this block to the next: validate all blocks down to here */ + memcpy(&sibhist.h[0], &gv_target->hist.h[lvl], SIZEOF(srch_blk_status) * (gv_target->hist.depth - lvl + 2)); + if ((trans_num)0 == (ret_tn = t_end(&sibhist, NULL, TN_NOT_SPECIFIED))) + return cdb_sc_restarted; + total_recs += incr_recs; + total_scans += incr_scans; + if (endtree || mu_ctrlc_occurred || mu_ctrly_occurred) + return cdb_sc_endtree; /* note: usage slightly different from elsewhere, since we've already done validation */ + assert(lvl >= targ_levl); + memcpy(gv_target->alt_hist, &gv_target->hist, SIZEOF(srch_hist)); /* take a copy of most recently validated history */ + gv_target->alt_hist->h[lvl - targ_levl + 1].curr_rec.offset++; /* don't recount the previously validated/counted path */ + for (i = 0; i <= (lvl - targ_levl); i++) + gv_target->alt_hist->h[i].curr_rec.offset = 0; + /* Free up the cache record for the block we're done with. I.e. mark it available to whoever makes the next pass through + * db_csh_getn. + */ + cr = gv_target->alt_hist->h[lvl - targ_levl].cr; + assert((NULL != cr) || (dba_mm == cs_data->acc_meth)); + if (NULL != cr) + cr->refer = FALSE; + gv_target->clue.end = 1; /* to set start_tn to earliest tn in history */ + t_begin(ERR_MUSIZEFAIL, 0); /* start a new transaction and continue recursive search */ + gv_target->clue.end = 0; + return cdb_sc_normal; +} + +enum cdb_sc read_block(block_id nBlkId, sm_uc_ptr_t *pBlkBase_ptr, int *nLevl_ptr, int desired_levl) +{ + sm_uc_ptr_t pBlkBase; + register srch_blk_status *pCurr; + register srch_hist *pTargHist; + unsigned char nLevl; + cache_rec_ptr_t cr; + int cycle; + trans_num tn; + enum cdb_sc status; + int i; + + pTargHist = &gv_target->hist; + tn = cs_addrs->ti->curr_tn; + if ((dba_mm != cs_data->acc_meth) && (ANY_ROOT_LEVL != desired_levl)) + { /* avoid reading into a cache record we're already using in this transaction. prevents self-induced restarts. */ + for (i = 0; i <= MAX_BT_DEPTH; i++) + if (pTargHist->h[i].blk_num && (NULL != (cr = pTargHist->h[i].cr))) /* note: assignment */ + cr->refer = TRUE; + } +# ifdef DEBUG + /* restart occasionally */ + if ((nBlkId % ((process_id % 25) + 25) == 0) && (t_tries == 0)) + return cdb_sc_blkmod; +# endif + if (NULL == (pBlkBase = t_qread(nBlkId, (sm_int_ptr_t)&cycle, &cr))) + return (enum cdb_sc)rdfail_detail; + GET_AND_CHECK_LEVL(status, nLevl, desired_levl, pBlkBase); + if (cdb_sc_normal != status) + { + assert(CDB_STAGNATE > t_tries); + return status; + } + pCurr = &pTargHist->h[nLevl - targ_levl]; /* No blocks to read beneath input level */ + if (ANY_ROOT_LEVL == desired_levl) + { + if (nLevl < targ_levl) + pCurr = &pTargHist->h[0]; + (pCurr + 1)->blk_num = 0; + pTargHist->depth = (int)nLevl; + } + pCurr->cse = NULL; + pCurr->blk_num = nBlkId; + pCurr->buffaddr = pBlkBase; + pCurr->tn = tn; + pCurr->cycle = cycle; + pCurr->cr = cr; + *nLevl_ptr = nLevl; + *pBlkBase_ptr = pBlkBase; + return cdb_sc_normal; +} diff --git a/sr_unix/mu_swap_root.c b/sr_unix/mu_swap_root.c new file mode 100644 index 0000000..4043154 --- /dev/null +++ b/sr_unix/mu_swap_root.c @@ -0,0 +1,462 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" +#include "cdb_sc.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "jnl.h" +#include "gdsblkops.h" +#include "gdskill.h" +#include "gdscc.h" +#include "copy.h" +#include "interlock.h" +#include "muextr.h" +#include "mu_reorg.h" +/* Include prototypes */ +#include "t_end.h" +#include "t_retry.h" +#include "mupip_reorg.h" +#include "util.h" +#include "t_begin.h" +#include "op.h" +#include "gvcst_protos.h" /* for gvcst_rtsib,gvcst_search prototype */ +#include "gvcst_bmp_mark_free.h" +#include "gvcst_kill_sort.h" +#include "gtmmsg.h" +#include "add_inter.h" +#include "t_abort.h" +#include "sleep_cnt.h" +#include "wcs_sleep.h" +#include "memcoherency.h" +#include "gdsbml.h" +#include "jnl_get_checksum.h" +#include "t_qread.h" +#include "t_create.h" +#include "t_write_map.h" +#include "t_write.h" +#ifdef GTM_TRIGGER +#include "hashtab_mname.h" +#include "gv_trigger.h" +#include "gv_trigger_common.h" +#include "targ_alloc.h" +#endif + +GTMTRIG_ONLY(LITREF mval literal_hasht;) + +GBLREF sgmnt_data_ptr_t cs_data; +GBLREF sgmnt_addrs *cs_addrs; +GBLREF gd_region *gv_cur_region; +GBLREF gv_key *gv_currkey, *gv_altkey; +GBLREF gv_namehead *gv_target; +GBLREF gv_namehead *reorg_gv_target; +GBLREF unsigned char cw_map_depth; +GBLREF unsigned char cw_set_depth; +GBLREF cw_set_element cw_set[]; +GBLREF uint4 t_err; +GBLREF unsigned int t_tries; +GBLREF unsigned char rdfail_detail; +GBLREF inctn_opcode_t inctn_opcode; +GBLREF kill_set *kill_set_tail; +GBLREF sgmnt_addrs *kip_csa; +GBLREF boolean_t mu_reorg_process; +GBLREF boolean_t mu_reorg_upgrd_dwngrd_in_prog; +GBLREF boolean_t need_kip_incr; +GBLREF uint4 update_trans; +GBLREF gv_key *gv_altkey; +GBLREF char *update_array, *update_array_ptr; +GBLREF uint4 update_array_size; +GBLREF inctn_opcode_t inctn_opcode; + +error_def(ERR_DBRDONLY); +error_def(ERR_GBLNOEXIST); +error_def(ERR_MAXBTLEVEL); +error_def(ERR_MUREORGFAIL); +error_def(ERR_MUTRUNCNOTBG); + +#define RETRY_SWAP (0) +#define ABORT_SWAP (1) + +boolean_t mu_swap_root(mval *gn, int *root_swap_statistic_ptr) +{ + sgmnt_data_ptr_t csd; + sgmnt_addrs *csa; + node_local_ptr_t cnl; + srch_hist *dir_hist_ptr, *gvt_hist_ptr; + gv_namehead *save_targ; + block_id root_blk_id, child_blk_id, free_blk_id; + sm_uc_ptr_t root_blk_ptr, child_blk_ptr; + kill_set kill_set_list; + trans_num curr_tn, ret_tn; + int level, root_blk_lvl; + block_id save_root; + boolean_t tn_aborted; + unsigned int lcl_t_tries; + enum cdb_sc status; +# ifdef GTM_TRIGGER + gv_namehead *hasht_tree; + mname_entry gvent; +# endif + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + assert(mu_reorg_process); + gv_target->root = 0; + gv_target->clue.end = 0; + dir_hist_ptr = gv_target->alt_hist; + gvt_hist_ptr = &(gv_target->hist); + inctn_opcode = inctn_invalid_op; +# ifdef GTM_TRIGGER + if (IS_MNAME_HASHT_GBLNAME(gn->str)) + { /* Initialize ^#t global for this region. */ + csa = cs_addrs; /* needed for SETUP_TRIGGER_GLOBAL and INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED macros */ + SETUP_TRIGGER_GLOBAL; + INITIAL_HASHT_ROOT_SEARCH_IF_NEEDED; + DBG_CHECK_GVTARGET_GVCURRKEY_IN_SYNC(CHECK_CSA_TRUE); + if (0 == gv_target->root) + return TRUE; + } else +# endif /* Initialization for current global */ + op_gvname(VARLSTCNT(1) (gn)); + csa = cs_addrs; + cnl = csa->nl; + csd = cs_data; /* Be careful to keep csd up to date. With MM, cs_data can change, and + * dereferencing an older copy can result in a SIG-11. + */ + if (0 == gv_target->root) + { /* Global does not exist (online rollback). No problem. */ + gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return TRUE; + } + if (dba_mm == csd->acc_meth) + /* return for now without doing any swapping operation because later mu_truncate + * is going to issue the MUTRUNCNOTBG message. + */ + return TRUE; + SET_GV_ALTKEY_TO_GBLNAME_FROM_GV_CURRKEY; /* set up gv_altkey to be just the gblname */ + /* ------------ Swap root block of global variable tree --------- */ + t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK); + for (;;) + { + curr_tn = csa->ti->curr_tn; + kill_set_list.used = 0; + save_root = gv_target->root; + gv_target->root = csa->dir_tree->root; + gv_target->clue.end = 0; + if (cdb_sc_normal != (status = gvcst_search(gv_altkey, dir_hist_ptr))) + { /* Assign directory tree path to dir_hist_ptr */ + assert(t_tries < CDB_STAGNATE); + gv_target->root = save_root; + t_retry(status); + continue; + } + gv_target->root = save_root; + gv_target->clue.end = 0; + if (cdb_sc_normal != (gvcst_search(gv_currkey, NULL))) + { /* Assign global variable tree path to gvt_hist_ptr */ + assert(t_tries < CDB_STAGNATE); + t_retry(status); + continue; + } + /* We've already search the directory tree in op_gvname/t_retry and obtained gv_target->root. + * Should restart with gvtrootmod2 if they don't agree. gvcst_root_search is the final arbiter. + * Really need that for debug info and also should assert(gv_currkey is global name). + */ + root_blk_lvl = gvt_hist_ptr->depth; + assert(root_blk_lvl > 0); + root_blk_ptr = gvt_hist_ptr->h[root_blk_lvl].buffaddr; + root_blk_id = gvt_hist_ptr->h[root_blk_lvl].blk_num; + assert((CDB_STAGNATE > t_tries) || (gv_target->root == gvt_hist_ptr->h[root_blk_lvl].blk_num)); + free_blk_id = swap_root_or_directory_block(0, root_blk_lvl, dir_hist_ptr, root_blk_id, + root_blk_ptr, &kill_set_list, curr_tn); + if (RETRY_SWAP == free_blk_id) + continue; + else if (ABORT_SWAP == free_blk_id) + break; + update_trans = UPDTRNS_DB_UPDATED_MASK; + inctn_opcode = inctn_mu_reorg; + assert(1 == kill_set_list.used); + need_kip_incr = TRUE; + if (!csa->now_crit) + WAIT_ON_INHIBIT_KILLS(cnl, MAXWAIT2KILL); + DEBUG_ONLY(lcl_t_tries = t_tries); + TREF(in_mu_swap_root_state) = MUSWP_INCR_ROOT_CYCLE; + assert(!TREF(in_gvcst_redo_root_search)); + if ((trans_num)0 == (ret_tn = t_end(gvt_hist_ptr, dir_hist_ptr, TN_NOT_SPECIFIED))) + { + TREF(in_mu_swap_root_state) = MUSWP_NONE; + need_kip_incr = FALSE; + assert(NULL == kip_csa); + ABORT_TRANS_IF_GBL_EXIST_NOMORE(lcl_t_tries, tn_aborted); + if (tn_aborted) + { /* It is not an error if the global (that once existed) doesn't exist anymore (due to ROLLBACK) */ + gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_GBLNOEXIST, 2, gn->str.len, gn->str.addr); + return TRUE; + } + continue; + } + TREF(in_mu_swap_root_state) = MUSWP_NONE; + /* Note that this particular process's csa->root_search_cycle is now behind cnl->root_search_cycle. + * This forces a cdb_sc_gvtrootmod2 restart in gvcst_bmp_mark_free below. + */ + assert(cnl->root_search_cycle > csa->root_search_cycle); + gvcst_kill_sort(&kill_set_list); + GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, inctn_opcode, csa); + DECR_KIP(csd, csa, kip_csa); + *root_swap_statistic_ptr += 1; + break; + } + /* ------------ Swap blocks in branch of directory tree --------- */ + for (level = 0; level <= MAX_BT_DEPTH; level++) + { + t_begin(ERR_MUREORGFAIL, UPDTRNS_DB_UPDATED_MASK); + for (;;) + { + curr_tn = csa->ti->curr_tn; + kill_set_list.used = 0; + save_root = gv_target->root; + gv_target->root = csa->dir_tree->root; + gv_target->clue.end = 0; + if (cdb_sc_normal != (status = gvcst_search(gv_altkey, dir_hist_ptr))) + { /* assign branch path of directory tree into dir_hist_ptr */ + assert(t_tries < CDB_STAGNATE); + gv_target->root = save_root; + t_retry(status); + continue; + } + gv_target->root = save_root; + gv_target->clue.end = 0; + if (level >= dir_hist_ptr->depth) + { /* done */ + t_abort(gv_cur_region, csa); + return TRUE; + } + child_blk_ptr = dir_hist_ptr->h[level].buffaddr; + child_blk_id = dir_hist_ptr->h[level].blk_num; + assert(csa->dir_tree->root != child_blk_id); + free_blk_id = swap_root_or_directory_block(level + 1, level, dir_hist_ptr, child_blk_id, + child_blk_ptr, &kill_set_list, curr_tn); + if (level == 0) + /* set level as 1 to mark this kill set is for level-0 block in directory tree. + * The kill-set level later will be used in gvcst_bmp_markfree to assign a special value to + * cw_set_element, which will be eventually used by t_end to write the block to snapshot + */ + kill_set_list.blk[kill_set_list.used - 1].level = 1; + if (RETRY_SWAP == free_blk_id) + continue; + else if (ABORT_SWAP == free_blk_id) + break; + update_trans = UPDTRNS_DB_UPDATED_MASK; + inctn_opcode = inctn_mu_reorg; + assert(1 == kill_set_list.used); + need_kip_incr = TRUE; + if (!csa->now_crit) + WAIT_ON_INHIBIT_KILLS(cnl, MAXWAIT2KILL); + DEBUG_ONLY(lcl_t_tries = t_tries); + TREF(in_mu_swap_root_state) = MUSWP_DIRECTORY_SWAP; + if ((trans_num)0 == (ret_tn = t_end(dir_hist_ptr, NULL, TN_NOT_SPECIFIED))) + { + TREF(in_mu_swap_root_state) = MUSWP_NONE; + need_kip_incr = FALSE; + assert(NULL == kip_csa); + continue; + } + TREF(in_mu_swap_root_state) = MUSWP_NONE; + gvcst_kill_sort(&kill_set_list); + TREF(in_mu_swap_root_state) = MUSWP_FREE_BLK; + GVCST_BMP_MARK_FREE(&kill_set_list, ret_tn, inctn_mu_reorg, inctn_bmp_mark_free_mu_reorg, + inctn_opcode, csa); + TREF(in_mu_swap_root_state) = MUSWP_NONE; + DECR_KIP(csd, csa, kip_csa); + break; + } + } + return TRUE; +} + +/* Finds a free block and adds information to update array and cw_set */ +block_id swap_root_or_directory_block(int parent_blk_lvl, int child_blk_lvl, srch_hist *dir_hist_ptr, block_id child_blk_id, + sm_uc_ptr_t child_blk_ptr, kill_set *kill_set_list, trans_num curr_tn) +{ + sgmnt_data_ptr_t csd; + sgmnt_addrs *csa; + node_local_ptr_t cnl; + srch_blk_status bmlhist, freeblkhist; + block_id hint_blk_num, free_blk_id, parent_blk_id; + boolean_t free_blk_recycled; + int4 master_bit, num_local_maps, free_bit, hint_bit, maxbitsthismap; + uint4 total_blks; + int blk_seg_cnt, blk_size; + sm_uc_ptr_t parent_blk_ptr, bn_ptr, saved_blk; + blk_segment *bs1, *bs_ptr; + int parent_blk_size, child_blk_size, bsiz; + int rec_size1, curr_offset, bpntr_end, hdr_len; + int tmp_cmpc; + cw_set_element *tmpcse; + jnl_buffer_ptr_t jbbp; /* jbbp is non-NULL only if before-image journaling */ + unsigned short temp_ushort; + unsigned long temp_long; + unsigned char save_cw_set_depth; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + csd = cs_data; + csa = cs_addrs; + cnl = csa->nl; + blk_size = csd->blk_size; + /* Find a free/recycled block for new block location. */ + hint_blk_num = 0; + total_blks = csa->ti->total_blks; + num_local_maps = DIVIDE_ROUND_UP(total_blks, BLKS_PER_LMAP); + master_bit = bmm_find_free((hint_blk_num / BLKS_PER_LMAP), csa->bmm, num_local_maps); + if ((NO_FREE_SPACE == master_bit)) + { + t_abort(gv_cur_region, csa); + return ABORT_SWAP; + } + bmlhist.blk_num = (block_id)master_bit * BLKS_PER_LMAP; + if (NULL == (bmlhist.buffaddr = t_qread(bmlhist.blk_num, (sm_int_ptr_t)&bmlhist.cycle, &bmlhist.cr))) + { + assert(t_tries < CDB_STAGNATE); + t_retry((enum cdb_sc)rdfail_detail); + return RETRY_SWAP; + } + hint_bit = 0; + maxbitsthismap = (master_bit != (num_local_maps - 1)) ? BLKS_PER_LMAP : total_blks - bmlhist.blk_num; + free_bit = bm_find_blk(hint_bit, bmlhist.buffaddr + SIZEOF(blk_hdr), maxbitsthismap, &free_blk_recycled); + free_blk_id = bmlhist.blk_num + free_bit; + if (DIR_ROOT >= free_blk_id) + { /* Bitmap block 0 and directory tree root block 1 should always be marked busy. */ + assert(t_tries < CDB_STAGNATE); + t_retry(cdb_sc_badbitmap); + return RETRY_SWAP; + } + if (child_blk_id <= free_blk_id) + { /* stop swapping root or DT blocks once the database is truncated well enough. A good heuristic for this is to check + * if the block is to be swapped into a higher block number and if so do not swap + */ + t_abort(gv_cur_region, csa); + return ABORT_SWAP; + } + /* ====== begin update array ====== + * Four blocks get changed. + * 1. Free block becomes busy and gains the contents of child (root block/directory tree block) + * 2. Parent block in directory tree remains busy, but points to new root block location. + * 3. Free block's corresponding bitmap reflects above change. + * 4. Child block gets marked recycled in bitmap. (GVCST_BMP_MARK_FREE) + */ + parent_blk_ptr = dir_hist_ptr->h[parent_blk_lvl].buffaddr; /* parent_blk_lvl is 0 iff we're moving a gvt root block */ + parent_blk_id = dir_hist_ptr->h[parent_blk_lvl].blk_num; + CHECK_AND_RESET_UPDATE_ARRAY; + if (free_blk_recycled) + { /* Otherwise, it's a completely free block, in which case no need to read. */ + freeblkhist.blk_num = (block_id)free_blk_id; + if (NULL == (freeblkhist.buffaddr = t_qread(free_blk_id, (sm_int_ptr_t)&freeblkhist.cycle, &freeblkhist.cr))) + { + assert(t_tries < CDB_STAGNATE); + t_retry((enum cdb_sc)rdfail_detail); + return RETRY_SWAP; + } + } + child_blk_size = ((blk_hdr_ptr_t)child_blk_ptr)->bsiz; + BLK_INIT(bs_ptr, bs1); + BLK_ADDR(saved_blk, child_blk_size, unsigned char); + memcpy(saved_blk, child_blk_ptr, child_blk_size); + BLK_SEG(bs_ptr, saved_blk + SIZEOF(blk_hdr), child_blk_size - SIZEOF(blk_hdr)); + assert(blk_seg_cnt == child_blk_size); + if (!BLK_FINI(bs_ptr, bs1)) + { + assert(t_tries < CDB_STAGNATE); + t_retry(cdb_sc_blkmod); + return RETRY_SWAP; + } + tmpcse = &cw_set[cw_set_depth]; + (free_blk_recycled) ? BIT_SET_RECYCLED_AND_CLEAR_FREE(tmpcse->blk_prior_state) + : BIT_CLEAR_RECYCLED_AND_SET_FREE(tmpcse->blk_prior_state); + t_create(free_blk_id, (unsigned char *)bs1, 0, 0, child_blk_lvl); + tmpcse->mode = gds_t_acquired; + if (!free_blk_recycled || !cs_data->db_got_to_v5_once) + tmpcse->old_block = NULL; + else + { + tmpcse->old_block = freeblkhist.buffaddr; + tmpcse->cr = freeblkhist.cr; + tmpcse->cycle = freeblkhist.cycle; + jbbp = (JNL_ENABLED(csa) && csa->jnl_before_image) ? csa->jnl->jnl_buff : NULL; + if ((NULL != jbbp) && (((blk_hdr_ptr_t)tmpcse->old_block)->tn < jbbp->epoch_tn)) + { + bsiz = ((blk_hdr_ptr_t)(tmpcse->old_block))->bsiz; + if (bsiz > blk_size) + { + assert(CDB_STAGNATE > t_tries); + t_retry(cdb_sc_lostbmlcr); + return RETRY_SWAP; + } + JNL_GET_CHECKSUM_ACQUIRED_BLK(tmpcse, csd, csa, tmpcse->old_block, bsiz); + } + } + /* 2. Parent block in directory tree remains busy, but points to new child block location. */ + curr_offset = dir_hist_ptr->h[parent_blk_lvl].curr_rec.offset; + parent_blk_size = ((blk_hdr_ptr_t)parent_blk_ptr)->bsiz; + GET_RSIZ(rec_size1, (parent_blk_ptr + curr_offset)); + if ((parent_blk_size < rec_size1 + curr_offset) || (BSTAR_REC_SIZE > rec_size1)) + { + assert(t_tries < CDB_STAGNATE); + t_retry(cdb_sc_blkmod); + return RETRY_SWAP; + } + BLK_INIT(bs_ptr, bs1); + if (0 == parent_blk_lvl) + /* There can be collation stuff in the record value after the block pointer. See gvcst_root_search. */ + hdr_len = SIZEOF(rec_hdr) + gv_altkey->end + 1 - EVAL_CMPC((rec_hdr_ptr_t)(parent_blk_ptr + curr_offset)); + else + hdr_len = rec_size1 - SIZEOF(block_id); + bpntr_end = curr_offset + hdr_len + SIZEOF(block_id); + BLK_SEG(bs_ptr, parent_blk_ptr + SIZEOF(blk_hdr), curr_offset + hdr_len - SIZEOF(blk_hdr)); + BLK_ADDR(bn_ptr, SIZEOF(block_id), unsigned char); + PUT_LONG(bn_ptr, free_blk_id); + BLK_SEG(bs_ptr, bn_ptr, SIZEOF(block_id)); + BLK_SEG(bs_ptr, parent_blk_ptr + bpntr_end, parent_blk_size - bpntr_end); + assert(blk_seg_cnt == parent_blk_size); + if (!BLK_FINI(bs_ptr, bs1)) + { + assert(t_tries < CDB_STAGNATE); + t_retry(cdb_sc_blkmod); + return RETRY_SWAP; + } + t_write(&dir_hist_ptr->h[parent_blk_lvl], (unsigned char *)bs1, 0, 0, parent_blk_lvl, FALSE, TRUE, GDS_WRITE_KILLTN); + /* To indicate later snapshot file writing process during fast_integ not to skip writing the block to snapshot file */ + BIT_SET_DIR_TREE(cw_set[cw_set_depth-1].blk_prior_state); + /* 3. Free block's corresponding bitmap reflects above change. */ + PUT_LONG(update_array_ptr, free_bit); + save_cw_set_depth = cw_set_depth; /* Bit maps go on end of cw_set (more fake acquired) */ + assert(!cw_map_depth); + t_write_map(&bmlhist, (uchar_ptr_t)update_array_ptr, curr_tn, 1); + cw_map_depth = cw_set_depth; + cw_set_depth = save_cw_set_depth; + update_array_ptr += SIZEOF(block_id); + temp_long = 0; + PUT_LONG(update_array_ptr, temp_long); + update_array_ptr += SIZEOF(block_id); + assert(1 == cw_set[cw_map_depth - 1].reference_cnt); + /* 4. Child block gets marked recycled in bitmap. (GVCST_BMP_MARK_FREE) */ + kill_set_list->blk[kill_set_list->used].flag = 0; + kill_set_list->blk[kill_set_list->used].level = 0; + kill_set_list->blk[kill_set_list->used++].block = child_blk_id; + return free_blk_id; +} diff --git a/sr_unix/mupip_size.c b/sr_unix/mupip_size.c new file mode 100644 index 0000000..8f4d1d5 --- /dev/null +++ b/sr_unix/mupip_size.c @@ -0,0 +1,210 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include "gtm_string.h" + +#include "stp_parms.h" +#include "gdsroot.h" +#include "gdsblk.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "gdskill.h" +#include "muextr.h" +#include "iosp.h" +#include "cli.h" +#include "mu_reorg.h" +#include "util.h" +#include "filestruct.h" +#include "error.h" +#include "gdscc.h" +#include "jnl.h" +#include "buddy_list.h" /* needed for tp.h */ +#include "hashtab_int4.h" /* needed for tp.h */ +#include "tp.h" + +/* Prototypes */ +#include "mupip_size.h" +#include "targ_alloc.h" +#include "mupip_exit.h" +#include "gv_select.h" +#include "mu_outofband_setup.h" +#include "gtmmsg.h" +#include "mu_getlst.h" + +error_def(ERR_NOSELECT); +error_def(ERR_MUNOFINISH); +error_def(ERR_MUNOACTION); +error_def(ERR_MUSIZEINVARG); + +GBLREF tp_region *grlist; +GBLREF bool error_mupip; +GBLREF bool mu_ctrlc_occurred; +GBLREF bool mu_ctrly_occurred; + +typedef struct { + enum {arsample, scan, impsample} heuristic; + int4 samples; + int4 level; + mval *global_name; + int4 seed; +} mupip_size_cfg_t; + +STATICFNDCL void mupip_size_check_error(void); + +/* + * This function reads command line parameters and forms a configuration for mupip size invocation. + * It later executes mupip size on each global based on the configuration + * + * MUPIP SIZE interface is described in GTM-7292 + */ +void mupip_size(void) +{ + uint4 status = EXIT_NRM; + glist gl_head, exclude_gl_head, *gl_ptr; + /* configuration default values */ + mupip_size_cfg_t mupip_size_cfg = { impsample, 1000, 1, 0, 0 }; + char cli_buff[MAX_LINE]; + int4 reg_max_rec, reg_max_key, reg_max_blk; + unsigned short n_len; + char buff[MAX_LINE]; + unsigned short BUFF_LEN = SIZEOF(buff); + char *p_end; /* used for strtol validation */ + boolean_t restrict_reg = FALSE; + + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + mu_outofband_setup(); + error_mupip = FALSE; + + /* Region qualifier */ + grlist = NULL; + if (CLI_PRESENT == cli_present("REGION")) + { + restrict_reg = TRUE; + gvinit(); /* initialize gd_header (needed by the following call to mu_getlst) */ + mu_getlst("REGION", SIZEOF(tp_region)); /* get the parameter corresponding to REGION qualifier */ + } + mupip_size_check_error(); + + /* SELECT qualifier */ + memset(cli_buff, 0, SIZEOF(cli_buff)); + n_len = SIZEOF(cli_buff); + if (CLI_PRESENT != cli_present("SELECT")) + { + n_len = 1; + cli_buff[0] = '*'; + } + else if (FALSE == cli_get_str("SELECT", cli_buff, &n_len)) + { + n_len = 1; + cli_buff[0] = '*'; + } + /* gv_select will select globals for this clause*/ + gv_select(cli_buff, n_len, FALSE, "SELECT", &gl_head, ®_max_rec, ®_max_key, ®_max_blk, restrict_reg); + if (!gl_head.next){ + error_mupip = TRUE; + gtm_putmsg(VARLSTCNT(1) ERR_NOSELECT); + } + mupip_size_check_error(); + + /* HEURISTIC qualifier */ + if (cli_present("HEURISTIC.SCAN") == CLI_PRESENT) + { + mupip_size_cfg.heuristic = scan; + if (cli_present("HEURISTIC.LEVEL")) + { + boolean_t valid = TRUE; + if (cli_get_str("HEURISTIC.LEVEL", buff, &BUFF_LEN)) + { + mupip_size_cfg.level = strtol(buff, &p_end, 10); + valid = (*p_end == '\0'); + } + else + valid = FALSE; + if (!valid || mupip_size_cfg.level <= -MAX_BT_DEPTH || MAX_BT_DEPTH <= mupip_size_cfg.level) + { + error_mupip = TRUE; + gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.LEVEL")); + } + } + /* else level is already initialized with default value */ + } + else if (cli_present("HEURISTIC.ARSAMPLE") == CLI_PRESENT || cli_present("HEURISTIC.IMPSAMPLE") == CLI_PRESENT) + { + if (cli_present("HEURISTIC.ARSAMPLE") == CLI_PRESENT) + mupip_size_cfg.heuristic = arsample; + else if (cli_present("HEURISTIC.IMPSAMPLE") == CLI_PRESENT) + mupip_size_cfg.heuristic = impsample; + if (cli_present("HEURISTIC.SAMPLES")) + { + boolean_t valid = cli_get_int("HEURISTIC.SAMPLES", &(mupip_size_cfg.samples)); + if (!valid || mupip_size_cfg.samples <= 0){ + error_mupip = TRUE; + gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.SAMPLES")); + } + } + /* else samples is already initialized with default value */ + + /* undocumented SEED parameter used for testing sampling method */ + if (cli_present("HEURISTIC.SEED")) + { + boolean_t valid = cli_get_int("HEURISTIC.SEED", &(mupip_size_cfg.seed)); + if (!valid){ + error_mupip = TRUE; + gtm_putmsg(VARLSTCNT(4) ERR_MUSIZEINVARG, 2, LEN_AND_LIT("HEURISTIC.SEED")); + } + } + /* else seed will be based on the time */ + } + mupip_size_check_error(); + + /* run mupip size on each global */ + for (gl_ptr = gl_head.next; gl_ptr; gl_ptr = gl_ptr->next) + { + util_out_print("!/Global: !AD ", FLUSH, gl_ptr->name.str.len, gl_ptr->name.str.addr); + + mupip_size_cfg.global_name = &(gl_ptr->name); + switch (mupip_size_cfg.heuristic) + { + case scan: + status |= mu_size_scan(mupip_size_cfg.global_name, mupip_size_cfg.level); + break; + case arsample: + status |= mu_size_arsample(mupip_size_cfg.global_name, mupip_size_cfg.samples, TRUE, mupip_size_cfg.seed); + break; + case impsample: + status |= mu_size_impsample(mupip_size_cfg.global_name, mupip_size_cfg.samples, mupip_size_cfg.seed); + break; + default: + GTMASSERT; + break; + } + if (mu_ctrlc_occurred || mu_ctrly_occurred) + mupip_exit(ERR_MUNOFINISH); + } + + mupip_exit(status == EXIT_NRM ? SS_NORMAL : ERR_MUNOFINISH); +} + + +STATICDEF void mupip_size_check_error(void) +{ + if (error_mupip) + { + util_out_print("!/MUPIP SIZE cannot proceed with above errors!/", FLUSH); + mupip_exit(ERR_MUNOACTION); + } +} diff --git a/sr_unix/mupip_size.h b/sr_unix/mupip_size.h new file mode 100644 index 0000000..e83feb0 --- /dev/null +++ b/sr_unix/mupip_size.h @@ -0,0 +1,23 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef __MUPIP_SIZE_H__ +#define __MUPIP_SIZE_H__ + +#include "cdb_sc.h" + +void mupip_size(void); +int4 mu_size_arsample(mval *gn, uint M, boolean_t ar, int seed); +int4 mu_size_impsample(mval *gn, int4 M, int4 seed); +int4 mu_size_scan(mval *gn, int4 level); +enum cdb_sc rand_traverse(double *r); + +#endif diff --git a/sr_unix/op_fnzpeek.c b/sr_unix/op_fnzpeek.c new file mode 100644 index 0000000..2cda909 --- /dev/null +++ b/sr_unix/op_fnzpeek.c @@ -0,0 +1,664 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#include "mdef.h" + +#include +#include +#include "gtm_unistd.h" +#include "gtm_string.h" + +#include "send_msg.h" +#include "error.h" +#include "stringpool.h" +#include "util.h" +#include "op.h" +#include "nametabtyp.h" +#include "namelook.h" +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "filestruct.h" +#include "repl_msg.h" +#include "gtmsource.h" +#include "gtmrecv.h" +#include "anticipatory_freeze.h" +#include "gtm_caseconv.h" + +error_def(ERR_BADZPEEKARG); +error_def(ERR_BADZPEEKFMT); +error_def(ERR_BADZPEEKRANGE); +error_def(ERR_MAXSTRLEN); +error_def(ERR_ZPEEKNORPLINFO); + +#define FMTHEXDGT(spfree, digit) *spfree++ = digit + ((digit <= 9) ? '0' : ('A' - 0x0A)) +#define ZPEEKDEFFMT "C" +#define ZPEEKDEFFMT_LEN (SIZEOF(ZPEEKDEFFMT) - 1) +#define ARGUMENT_MAX_LEN MAX_MIDENT_LEN + +/* Codes for peek operation mnemonics */ +#define PO_CSAREG 0 /* Region information - sgmnt_addrs struct - process private structure */ +#define PO_FHREG 1 /* Fileheader information from sgmnt_data for specified region */ +#define PO_GDRREG 2 /* Region information - gd_region struct - process private structure */ +#define PO_NLREG 3 /* Fileheader information from node_local for specified region (transient - non permanent) */ +#define PO_NLREPL 4 /* Fileheader information from node_local for replication dummy region */ +#define PO_GLFREPL 5 /* Replication information from gtmsrc_lcl_array structure */ +#define PO_GSLREPL 6 /* Replication information from gtmsource_local_array structure */ +#define PO_JPCREPL 7 /* Replication information from jnlpool_ctl structure */ +#define PO_PEEK 8 /* Generalized peek specifying (base) address argument */ +#define PO_RIHREPL 9 /* Replication information from repl_inst_hdr structure */ +#define PO_RPCREPL 10 /* Replication information from recvpool_ctl_struct */ +#define PO_UPLREPL 11 /* Replication information from upd_proc_local_struct */ +#define PO_GRLREPL 12 /* Replication information from gtmrecv_local_struct */ +#define PO_UHCREPL 13 /* Replication information from upd_helper_ctl */ + +GBLREF boolean_t created_core; +GBLREF sigset_t blockalrm; +GBLREF gd_addr *gd_header; +GBLREF boolean_t pool_init; +GBLREF boolean_t jnlpool_init_needed; +GBLREF jnlpool_addrs jnlpool; +GBLREF recvpool_addrs recvpool; +DEBUG_ONLY(GBLREF boolean_t ok_to_UNWIND_in_exit_handling;) + +LITDEF mval literal_zpeekdeffmt = DEFINE_MVAL_LITERAL(MV_STR, 0, 0, ZPEEKDEFFMT_LEN, (char *)ZPEEKDEFFMT, 0, 0); +LITREF unsigned char lower_to_upper_table[]; + +STATICFNDCL void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context); +STATICFNDCL int op_fnzpeek_stpcopy(char *zpeekadr, int len, mval *ret, char fmtcode); +STATICFNDCL uchar_ptr_t op_fnzpeek_uint64fmt(uchar_ptr_t p, gtm_uint64_t n); +STATICFNDCL uchar_ptr_t op_fnzpeek_hexfmt(uchar_ptr_t p, gtm_uint64_t n, int fmtlen); +STATICFNDEF boolean_t op_fnzpeek_attach_jnlpool(void); +STATICFNDEF boolean_t op_fnzpeek_attach_recvpool(void); + +typedef struct +{ + int peekop; /* Peek operation mnemonic id */ + boolean_t allowargs; /* Number of arguments allowed */ +} zpeek_data_typ; + +/* Lookup tables for first argument - Note names are limited to NAME_ENTRY_SZ bytes each */ +LITDEF nametabent zpeek_names[] = +{ /* Array offsets */ + {3, "CSA"}, {6, "CSAREG"} /* 0, 1 */ + ,{2, "FH"}, {5, "FHREG"} /* 2, 3 */ + ,{3, "GDR"}, {6, "GDRREG"} /* 4, 5 */ + ,{3, "GLF"}, {7, "GLFREPL"} /* 6, 7 */ + ,{3, "GRL"}, {7, "GRLREPL"} /* 8, 9 */ + ,{3, "GSL"}, {7, "GSLREPL"} /* 10, 11 */ + ,{3, "JPC"}, {7, "JPCREPL"} /* 12, 13 */ + ,{2, "NL"}, {5, "NLREG"} /* 14, 15 */ + ,{6, "NLREPL"} /* 16 */ + ,{4, "PEEK"} /* 17 */ + ,{3, "RIH"}, {7, "RIHREPL"} /* 18, 19 */ + ,{3, "RPC"}, {7, "RPCREPL"} /* 20, 21 */ + ,{3, "UHC"}, {7, "UHCREPL"} /* 22, 23 */ + ,{3, "UPL"}, {7, "UPLREPL"} /* 24, 25 */ + /* Total length 26 */ +}; +LITDEF unsigned char zpeek_index[] = +{ + 0, 0, 0, 2, 2, 2, 4, 12, 12, /* a b c d e f g h i */ + 12, 14, 14, 14, 14, 17, 17, 18, 18, /* j k l m n o p q r */ + 22, 22, 22, 26, 26, 26, 26, 26, 26 /* s t u v w x y z ~ */ +}; +LITDEF zpeek_data_typ zpeek_data[] = +{ + {PO_CSAREG, 1}, {PO_CSAREG, 1} + ,{PO_FHREG, 1}, {PO_FHREG, 1} + ,{PO_GDRREG, 1}, {PO_GDRREG, 1} + ,{PO_GLFREPL, 1}, {PO_GLFREPL, 1} + ,{PO_GRLREPL, 0}, {PO_GRLREPL, 0} + ,{PO_GSLREPL, 1}, {PO_GSLREPL, 1} + ,{PO_JPCREPL, 0}, {PO_JPCREPL, 0} + ,{PO_NLREG, 1}, {PO_NLREG, 1} + ,{PO_NLREPL, 0} + ,{PO_PEEK, 1} + ,{PO_RIHREPL, 0}, {PO_RIHREPL, 0} + ,{PO_RPCREPL, 0}, {PO_RPCREPL, 0} + ,{PO_UHCREPL, 0}, {PO_UHCREPL, 0} + ,{PO_UPLREPL, 0}, {PO_UPLREPL, 0} +}; + +/* Condition handler for use during copy of memory range to the stringpool for return. Note this condition handler is itself + * never tripped but serves as an unwind target for the signal handler defined below (see its comments). + */ +CONDITION_HANDLER(op_fnzpeek_ch) +{ + START_CH; + NEXTCH; /* In the unlikely event it gets driven, just be a pass-thru */ +} + +/* $ZPEEK() is processing a process memory range specified by an M routine so is definitely capable of getting + * user inspired address type exceptions. We protect against this by setting up our signal handler to catch any + * such exceptions for the duration of this routine and just unwind them so we can throw a non-fatal error + * message instead. + */ +void op_fnzpeek_signal_handler(int sig, siginfo_t *info, void *context) +{ + /* We basically want to do UNWIND(NULL, NULL) logic but the UNWIND macro can only be used in a condition + * handler so next is a block that pretends it is our condition handler and does the needful. Note in order + * for this to work, we need to be wrapped in a condition handler even if that condition handler is never + * actually invoked to serve as the target for the UNWIND(). + */ + { /* Needs new block since START_CH declares a new var used in UNWIND() */ + int arg = 0; /* Needed for START_CH macro if debugging enabled */ + START_CH; + DEBUG_ONLY(ok_to_UNWIND_in_exit_handling = TRUE); + UNWIND(NULL, NULL); + } +} + +/* Routine to convert gtm_uint64_t to ascii value not losing any precision. Routine is based on i2asc() but + * uses gtm_uint64_t as the type. + */ +STATICFNDCL uchar_ptr_t op_fnzpeek_uint64fmt(uchar_ptr_t p, gtm_uint64_t n) +{ + unsigned char ar[MAX_DIGITS_IN_INT8], *q; + gtm_uint64_t m; + int len; + + q = ar + SIZEOF(ar); + if (!n) + *--q = '0'; + else + { + while (n) + { + m = n / 10; + *--q = n - (m * 10) + '0'; + n = m; + } + } + assert((uintszofptr_t)q >= (uintszofptr_t)ar); + len = (unsigned int)(ar + SIZEOF(ar) - q); + memcpy(p, q, len); + return p + len; +} + +/* Routine to format hex output to given length with format 0xhh>>. Similar to i2asclx(). + * + * p - Output buffer (generally stringpool.free) + * n - Hex value to format + * fmtlen - Length in bytes of output value + */ +STATICFNDCL uchar_ptr_t op_fnzpeek_hexfmt(uchar_ptr_t p, gtm_uint64_t n, int fmtlen) +{ + unsigned char ar[MAX_HEX_DIGITS_IN_INT8], *q; + int m, digits; + + q = ar + SIZEOF(ar); + for (digits = fmtlen; (0 < digits); --digits) + { + m = n & 0xF; + if (m <= 9) + *--q = m + '0'; + else + *--q = m - 0xa + 'A'; + n = n >> 4; + } + assert(0 == n); /* Verify complete number has been output (no truncated digits) */ + memcpy(p, q, fmtlen); + return p + fmtlen; +} + +/* Routine to extract and optionally format the requested data leaving it in the stringpool. This routine is protected + * by a signal handler for data access against SIGSEGV or SIGBUS signals. Note the fields that are sub-integer (1 or + * 2 bytes) are pulled into integer forms before processing. + */ +STATICFNDEF int op_fnzpeek_stpcopy(char *zpeekadr, int len, mval *ret, char fmtcode) +{ + unsigned int uint; + boolean_t negative; + gtm_uint64_t uint64; + unsigned char *numstrstart, *numstrend; + unsigned char *hexchr, *hexchrend, hexc, hexdgt, *spfree; + + ESTABLISH_RET(op_fnzpeek_ch, ERR_BADZPEEKRANGE); /* If get an exception, likely due to bad range */ + ret->mvtype = 0; /* Prevent GC of incomplete field */ + switch(fmtcode) + { + case 'S': /* Null terminated string processing */ + STRNLEN(zpeekadr, len, len); /* Reset len to actual len, fall into "C" processing */ + /* warning - fall through */ + case 'C': /* Character area (no processing - just copy */ + if (len > MAX_STRLEN) + { /* Requested string return is too large */ + REVERT; + return ERR_MAXSTRLEN; + } + ENSURE_STP_FREE_SPACE(len); + memcpy(stringpool.free, zpeekadr, len); + ret->str.addr = (char *)stringpool.free; + ret->str.len = len; + stringpool.free += len; + break; + case 'I': /* Initially, treat signed/unsigned the same */ + case 'U': + negative = FALSE; + switch(len) + { + case SIZEOF(gtm_uint64_t): + /* Dealing with 8 byte integer style values is not GT.M's forte since its internal + * number scheme is limited to 20 digits. So use our own routine to do the conversion. + * Note: we could use this routine for all the below cases but on 32 bit platforms + * with no native 8 byte values, they would run far slower so only use this for the + * 8 byte values we deal with. + */ + uint64 = *(gtm_uint64_t *)zpeekadr; + if ('I' == fmtcode) + { /* If signed, check if need to add minus sign to value and change value to + * positive. + */ + negative = (0 > (gtm_int64_t)uint64); + if (negative) + uint64 = (gtm_uint64_t)(-(gtm_int64_t)uint64); + } + fmtcode = 'u'; /* Change fmtcode to skip negative value check below */ + break; + case SIZEOF(unsigned int): + uint = *(unsigned int *)zpeekadr; + break; + case SIZEOF(short): + uint = (unsigned int)*(unsigned short *)zpeekadr; + break; + case SIZEOF(char): + uint = (unsigned int)*(unsigned char *)zpeekadr; + break; + default: + REVERT; + return ERR_BADZPEEKFMT; + } + if ('I' == fmtcode) + { /* If signed, check if need to add minus sign to value and change value to positive. Note this test + * is bypassed for uint64 types because the check is already made (in a differet/longer value). + */ + negative = (0 > (signed int)uint); + if (negative) + uint = (unsigned int)(-(signed int)uint); + } + ENSURE_STP_FREE_SPACE(MAX_DIGITS_IN_INT + negative); /* Space to hold # */ + numstrstart = stringpool.free; + if (negative) + *stringpool.free++ = '-'; /* Value is negative, record in output */ + /* Use the correct formmating routine based on size */ + numstrend = (SIZEOF(gtm_uint64_t) != len) ? i2asc(stringpool.free, uint) + : op_fnzpeek_uint64fmt(stringpool.free, uint64); + ret->str.addr = (char *)numstrstart; + ret->str.len = INTCAST(numstrend - numstrstart); + stringpool.free = numstrend; + break; + case 'X': /* Hex format for numeric values */ + switch(len) + { + case SIZEOF(gtm_uint64_t): + uint64 = *(gtm_uint64_t *)zpeekadr; + break; + case SIZEOF(unsigned int): + uint64 = (gtm_uint64_t)*(unsigned int *)zpeekadr; + break; + case SIZEOF(unsigned short): + uint64 = (gtm_uint64_t)*(unsigned short *)zpeekadr; + break; + case SIZEOF(unsigned char): + uint64 = (gtm_uint64_t)*(unsigned char *)zpeekadr; + break; + default: + REVERT; + return ERR_BADZPEEKFMT; + } + ENSURE_STP_FREE_SPACE((len * 2) + 2); + numstrstart = stringpool.free; + *stringpool.free++ = '0'; + *stringpool.free++ = 'x'; + numstrend = op_fnzpeek_hexfmt(stringpool.free, uint64, (len * 2)); + ret->str.addr = (char *)numstrstart; + ret->str.len = INTCAST(numstrend - numstrstart); + stringpool.free = numstrend; + break; + case 'Z': /* Hex format (no 0x prefix) of storage as it exists */ + if ((len * 2) > MAX_STRLEN) + { /* Requested string return is too large */ + REVERT; + return ERR_MAXSTRLEN; + } + ENSURE_STP_FREE_SPACE(len * 2); /* Need enough space for hex string */ + spfree = stringpool.free; + ret->str.addr = (char *)spfree; + hexchr = (unsigned char *)zpeekadr; + hexchrend = hexchr + len; + if (hexchr > hexchrend) /* Wrapped address - range error */ + { + REVERT; + return ERR_BADZPEEKRANGE; + } + for (; hexchr < hexchrend; ++hexchr) + { /* Format 2 digits in each character encountered */ + hexc = *hexchr; + hexdgt = (hexc & 0xF0) >> 4; + FMTHEXDGT(spfree, hexdgt); + hexdgt = (hexc & 0x0F); + FMTHEXDGT(spfree, hexdgt); + } + stringpool.free = spfree; /* "commit" string to stringpool */ + ret->str.len = len * 2; + break; + default: + REVERT; + return ERR_BADZPEEKARG; + } + REVERT; + ret->mvtype = MV_STR; + return 0; +} + +/* A condition handler for when we are attaching to either the jnlpool or the gtmrecv pool. We don't + * care why we can't get to them. On the fact that we can't is material for $ZPEEK(). + */ +CONDITION_HANDLER(op_fnzpeek_getpool_ch) +{ + START_CH; + if (DUMPABLE) + NEXTCH; /* Let next (more robust) handler deal with it */ + UNWIND(NULL, NULL); +} + +/* Attach to the journal pool. Separate routine so can be wrapped in a condition handler */ +STATICFNDEF boolean_t op_fnzpeek_attach_jnlpool(void) +{ + ESTABLISH_RET(op_fnzpeek_getpool_ch, FALSE); + jnlpool_init(GTMRELAXED, FALSE, NULL); /* Attach to journal pool */ + REVERT; + return pool_init; +} + +/* Attach to the receive pool. Separate routine so can be wrapped in a condition handler */ +STATICFNDEF boolean_t op_fnzpeek_attach_recvpool(void) +{ + ESTABLISH_RET(op_fnzpeek_getpool_ch, FALSE); + recvpool_init(GTMZPEEK, FALSE); /* Attach to receive pool */ + REVERT; + return ((NULL != recvpool.recvpool_ctl) && recvpool.recvpool_ctl->initialized); +} + +/* Generalized peek facility: + * + * structid - String that describes the structure + * offset - Offset of item within that structure. + * len - Length of the fetch. + * format - Option format character - codes described below + * ret - Return mval + */ +void op_fnzpeek(mval *structid, int offset, int len, mval *format, mval *ret) +{ + void *zpeekadr; + UINTPTR_T prmpeekadr; + struct sigaction new_action, prev_action_bus, prev_action_segv; + sigset_t savemask; + int errtoraise, rslt; + char fmtcode; + boolean_t arg_supplied, attach_success; + unsigned char mnemonic[NAME_ENTRY_SZ], *nptr, *cptr, *cptrend, *argptr; + int mnemonic_len, mnemonic_index, mnemonic_opcode, arglen, arryidx; + gd_region *r_top, *r_ptr; + replpool_identifier replpool_id; + unsigned int full_len; + unsigned char argument_uc_buf[ARGUMENT_MAX_LEN]; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + /* Make sure lookup table is setup correctly */ + assert(zpeek_index[26] == (SIZEOF(zpeek_names) / SIZEOF(nametabent))); + assert((SIZEOF(zpeek_names) / SIZEOF(nametabent)) == (SIZEOF(zpeek_data) / SIZEOF(zpeek_data_typ))); + /* Initialize */ + fmtcode = 'C'; /* If arg is NULL string (noundef default), provide default */ + MV_FORCE_STR(structid); + if (MV_DEFINED(format)) + { + MV_FORCE_STR(format); + } else format = (mval *)&literal_zpeekdeffmt; /* Cast to avoid compiler warning about dropping readonly type attributes */ + /* Parse and lookup the first arg's mnemonic and arg (if supplied) */ + for (nptr = mnemonic, cptr = (unsigned char *)structid->str.addr, cptrend = cptr + structid->str.len; + cptr < cptrend; ++cptr) + { + if (':' == *cptr) + break; /* End of mnemonic, start of arg */ + *nptr++ = *cptr; + } + arg_supplied = (cptr < cptrend); + mnemonic_len = INTCAST(nptr - mnemonic); + mnemonic_index = namelook(zpeek_index, zpeek_names, (char *)mnemonic, mnemonic_len); + if (0 > mnemonic_index) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic type")); + mnemonic_opcode = zpeek_data[mnemonic_index].peekop; + if ((arg_supplied && !zpeek_data[mnemonic_index].allowargs) || (!arg_supplied && zpeek_data[mnemonic_index].allowargs)) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument")); + if (arg_supplied) + { /* Parse supplied argument */ + argptr = ++cptr; /* Bump past ":" - if now have end-of-arg then arg is missing */ + if (argptr == cptrend) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument")); + arglen = INTCAST(cptrend - cptr); + if (ARGUMENT_MAX_LEN < arglen) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("mnemonic argument")); + switch(mnemonic_opcode) + { + case PO_CSAREG: /* These types have a region name argument */ + case PO_FHREG: + case PO_GDRREG: + case PO_NLREG: + /* Uppercase the region name since that is what GDE does when creating them */ + lower_to_upper(argument_uc_buf, argptr, arglen); + argptr = argument_uc_buf; /* Reset now to point to upper case version */ + /* See if region recently used so can avoid lookup */ + if ((arglen == TREF(zpeek_regname_len)) && (0 == memcmp(argptr, TADR(zpeek_regname), arglen))) + { /* Fast path - no lookup necessary */ + r_ptr = TREF(zpeek_reg_ptr); + assert(r_ptr->open && !r_ptr->was_open); /* Make sure truly open */ + break; + } + /* Region now defined - make sure it is open */ + if (!gd_header) /* If gd_header is NULL, open gbldir */ + gvinit(); + r_ptr = gd_header->regions; + for (r_top = r_ptr + gd_header->n_regions; ; r_ptr++) + { + if (r_ptr >= r_top) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, + RTS_ERROR_LITERAL("mnemonic argument (region name)")); + if ((r_ptr->rname_len == arglen) && (0 == memcmp(r_ptr->rname, argptr, arglen))) + break; + } + if (!r_ptr->open) + gv_init_reg(r_ptr); + /* Cache new region access for followup references */ + memcpy(TADR(zpeek_regname), argptr, arglen); + TREF(zpeek_regname_len) = arglen; + TREF(zpeek_reg_ptr) = r_ptr; + /* r_ptr now points to (open) region */ + assert(r_ptr->open && !r_ptr->was_open); /* Make sure truly open */ + break; + case PO_GLFREPL: /* These types have an array index argument */ + case PO_GSLREPL: + arryidx = asc2i(argptr, arglen); + if ((0 > arryidx) || (NUM_GTMSRC_LCL < arryidx)) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, + RTS_ERROR_LITERAL("mnemonic argument (array index)")); + break; + case PO_PEEK: /* Argument is address of form 0Xhhhhhhhh[hhhhhhhh] */ + if (('0' != *cptr++) || ('x' != *cptr) && ('X' != *cptr)) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, + RTS_ERROR_LITERAL("mnemonic argument (peek base address)")); + cptr++; /* Bump past 'x' or 'X' - rest of arg should be hex value */ + prmpeekadr = (UINTPTR_T)GTM64_ONLY(asc_hex2l)NON_GTM64_ONLY(asc_hex2i)(cptr, arglen - 2); + if (-1 == (INTPTR_T)prmpeekadr) + /* Either an error occurred or the user specified the maximum address. So it's + * either an error from the conversion routine or an otherwise useless value. + */ + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, + RTS_ERROR_LITERAL("mnemonic argument (peek base address)")); + break; + default: + assert(FALSE); /* Only the above types should ever have an argument */ + } + } + /* Figure out the address of each block to return */ + switch(mnemonic_opcode) + { + case PO_CSAREG: /* r_ptr set from option processing */ + zpeekadr = &FILE_INFO(r_ptr)->s_addrs; + break; + case PO_FHREG: /* r_ptr set from option processing */ + zpeekadr = (&FILE_INFO(r_ptr)->s_addrs)->hdr; + break; + case PO_GDRREG: /* r_ptr set from option processing */ + zpeekadr = r_ptr; + break; + case PO_NLREG: /* r_ptr set from option processing */ + zpeekadr = (&FILE_INFO(r_ptr)->s_addrs)->nl; + break; + case PO_GLFREPL: /* This set of opcodes all require the journal pool to be initialized. Verify it */ + case PO_GSLREPL: + case PO_JPCREPL: + case PO_NLREPL: + case PO_RIHREPL: + /* Make sure jnlpool_addrs are availble */ + if (!REPL_INST_AVAILABLE) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO); + if (!pool_init) + { + attach_success = op_fnzpeek_attach_jnlpool(); + if (!attach_success) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO); + } + switch(mnemonic_opcode) + { + case PO_GLFREPL: /* arryidx set by option processing */ + zpeekadr = (jnlpool.gtmsrc_lcl_array + arryidx); + break; + case PO_GSLREPL: /* arryidx set by option processing */ + zpeekadr = (jnlpool.gtmsource_local_array + arryidx); + break; + case PO_NLREPL: + zpeekadr = (&FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs)->nl; + break; + case PO_JPCREPL: + zpeekadr = jnlpool.jnlpool_ctl; + break; + case PO_RIHREPL: + zpeekadr = jnlpool.repl_inst_filehdr; + break; + default: + assert(FALSE); + } + break; + case PO_RPCREPL: /* This set of opcodes all require the receive pool to be initialized. Verify it */ + case PO_GRLREPL: + case PO_UPLREPL: + case PO_UHCREPL: + /* Make sure recvpool_addrs are available */ + if (!REPL_INST_AVAILABLE) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO); + if (NULL == recvpool.recvpool_ctl) + { + attach_success = op_fnzpeek_attach_recvpool(); + if (!attach_success) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_ZPEEKNORPLINFO); + } + switch(mnemonic_opcode) + { + case PO_RPCREPL: + zpeekadr = recvpool.recvpool_ctl; + break; + case PO_GRLREPL: + zpeekadr = recvpool.gtmrecv_local; + break; + case PO_UPLREPL: + zpeekadr = recvpool.upd_proc_local; + break; + case PO_UHCREPL: + zpeekadr = recvpool.upd_helper_ctl; + break; + default: + assert(FALSE); + } + break; + case PO_PEEK: /* prmpeekadr set up in argument processing */ + zpeekadr = (void *)prmpeekadr; + break; + default: + assert(FALSE); + } + assert(NULL != zpeekadr); + /* Check the rest of the args */ + if (0 > offset) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("offset")); + zpeekadr = (void *)((char *)zpeekadr + offset); + if ((0 > len) || (MAX_STRLEN < len)) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("length")); + if (1 < format->str.len) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("format")); + else if (1 == format->str.len) + { /* Validate format option */ + fmtcode = *format->str.addr; + fmtcode = lower_to_upper_table[fmtcode]; + switch(fmtcode) + { + case 'C': /* Character data - returned as is */ + case 'I': /* Signed integer format - up to 31 bits */ + case 'S': /* String data - Same as 'C' except string is NULL terminated */ + case 'U': /* Unsigned integer format - up to 64 bits */ + case 'X': /* Humeric hex format: e.g. 0x12AB. Total length is (2 * bytes) + 2 */ + case 'Z': /* Hex format - not treated as numeric. Shown as occurs in memory (subject to endian) + * and is returned with no 0x prefix. + */ + break; + default: + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_BADZPEEKARG, 2, RTS_ERROR_LITERAL("format")); + } + } + /* Block out timer calls that might trigger processing that could fail. We especially want to prevent + * nesting of signal handlers since the longjump() function used by the UNWIND macro is undefined on + * Tru64 when signal handlers are nested. + */ + sigprocmask(SIG_BLOCK, &blockalrm, &savemask); + /* Setup new signal handler to just drive condition handler which will do the right thing */ + memset(&new_action, 0, SIZEOF(new_action)); + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = SA_SIGINFO; +# ifdef __sparc + new_action.sa_handler = op_fnzpeek_signal_handler; +# else + new_action.sa_sigaction = op_fnzpeek_signal_handler; +# endif + sigaction(SIGBUS, &new_action, &prev_action_bus); + sigaction(SIGSEGV, &new_action, &prev_action_segv); + /* Attempt to copy return string to stringpool which protected by our handlers. If the copy completes, the return + * mval is updated to point to the return string. Even errors return here so these sigactions can be reversed. + */ + errtoraise = op_fnzpeek_stpcopy(zpeekadr, len, ret, fmtcode); + /* Can restore handlers now that access verified */ + sigaction(SIGBUS, &prev_action_bus, NULL); + sigaction(SIGSEGV, &prev_action_segv, NULL); + /* Let the timers pop again.. */ + sigprocmask(SIG_SETMASK, &savemask, NULL); + /* If we didn't complete correctly, raise error */ + if (0 != errtoraise) + { /* The only time ERR_BADZPEEKARG is driven is when the format code is not recognized so give that error + * specifically with the additional args. Else just raise the error. + */ + if (ERR_BADZPEEKARG == errtoraise) + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(4) errtoraise, 2, RTS_ERROR_LITERAL("format")); + rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) errtoraise); + } + return; +} diff --git a/sr_unix/repl_logfileinfo_get.c b/sr_unix/repl_logfileinfo_get.c new file mode 100644 index 0000000..0e7777d --- /dev/null +++ b/sr_unix/repl_logfileinfo_get.c @@ -0,0 +1,80 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ +#include +#include + +#include "mdef.h" +#include "gtm_limits.h" +#include "gtm_string.h" +#include "gtm_stdio.h" +#include "gtm_unistd.h" +#include "repl_msg.h" +#include "repl_log.h" +#include "gdsroot.h" +#include "have_crit.h" +#include "min_max.h" + +error_def(ERR_FILENAMETOOLONG); + +GBLREF uint4 process_id; + +uint4 repl_logfileinfo_get(char *logfile, repl_logfile_info_msg_t *msgp, boolean_t cross_endian, FILE *logfp) +{ + uint4 status, fullpath_len, msglen; + int save_errno; + char fullpath[GTM_PATH_MAX], *cwdptr; + + assert(NULL != msgp); + msgp->type = cross_endian ? GTM_BYTESWAP_32(REPL_LOGFILE_INFO) : REPL_LOGFILE_INFO; + assert(GTM_PATH_MAX >= REPL_LOGFILE_PATH_MAX); + assert(GTM_PATH_MAX >= PATH_MAX); + if (NULL == logfile) + { + GETCWD(fullpath, GTM_PATH_MAX, cwdptr); + assert(NULL != cwdptr); + if (NULL == cwdptr) + { + save_errno = errno; + assert(FALSE); + repl_log(logfp, TRUE, TRUE, "Could not obtain current working directory: %s\n", STRERROR(save_errno)); + SNPRINTF(fullpath, GTM_PATH_MAX, "Could not obtain current working directory"); + } + fullpath_len = STRLEN(fullpath); + } else if (!get_full_path(STR_AND_LEN(logfile), fullpath, &fullpath_len, GTM_PATH_MAX + 1, &status)) + { /* Either GETCWD failed or buffer not large enough to hold the expanded logfile path. In either case, we don't want + * to error out as this is just a supplementary message. Copy whatever possible. + */ + assert(ERR_FILENAMETOOLONG != status); + SNPRINTF(fullpath, GTM_PATH_MAX, logfile); + fullpath_len = STRLEN(fullpath); + /* Print a warning message for diagnostic purposes */ + if (ERR_FILENAMETOOLONG != status) + repl_log(logfp, TRUE, TRUE, "Could not obtain current working directory: %s\n", STRERROR(status)); + else + repl_log(logfp, TRUE, TRUE, "Could not obtain full path of log file: Path name exceeds %d characters\n", + GTM_PATH_MAX); + } + assert('\0' == fullpath[fullpath_len]); + fullpath_len = MIN(fullpath_len, REPL_LOGFILE_PATH_MAX); + fullpath[fullpath_len] = '\0'; /* truncate if needed */ + fullpath_len++; /* So that, we copy and send null-terminator as well */ + memcpy(msgp->fullpath, fullpath, fullpath_len); + msgp->fullpath_len = cross_endian ? GTM_BYTESWAP_32(fullpath_len) : fullpath_len; + assert(fullpath_len <= REPL_LOGFILE_PATH_MAX); + /* Receiver expects 8 byte alignment on data portion of the message. */ + fullpath_len = ROUND_UP2(fullpath_len, REPL_MSG_ALIGN); + assert(fullpath_len <= REPL_LOGFILE_PATH_MAX + 1); + msglen = REPL_LOGFILE_INFO_MSGHDR_SZ + fullpath_len; + msgp->len = cross_endian ? GTM_BYTESWAP_32(msglen) : msglen; + msgp->proto_ver = REPL_PROTO_VER_THIS; + msgp->pid = cross_endian ? GTM_BYTESWAP_32(process_id) : process_id; + return msglen; +} diff --git a/sr_unix/show_install_config.sh b/sr_unix/show_install_config.sh new file mode 100644 index 0000000..25f807b --- /dev/null +++ b/sr_unix/show_install_config.sh @@ -0,0 +1,54 @@ +#!/bin/sh +################################################################# +# # +# Copyright 2012 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +if [ "x" = x"$gtm_dist" ]; then + echo "Environment variable - gtm_dist not defined." + exit 1 +fi + +if [ ! -d $gtm_dist/plugin ]; then + echo "Unable to locate $gtm_dist/plugin. Exiting..." + exit 1 +fi + +platform_name=`uname -s` +ext=".so" +if [ "OS/390" = $platform_name ]; then ext=".dll" ; fi + +base_libname="libgtmcrypt" +generic_libname=$base_libname$ext +if [ "x" = x"$gtm_crypt_plugin" ]; then + shared_object="$gtm_dist/plugin/$generic_libname" + txt="symbolic link pointed by $gtm_dist/plugin/$generic_libname" +else + shared_object="$gtm_dist/plugin/$gtm_crypt_plugin" + txt='$gtm_crypt_plugin' +fi +if [ ! -f $shared_object ] ; then + echo "Cannot find $shared_object. Exiting..." + exit 1 +fi +# Obtain the symbolic link (if any) +link=`ls -l $shared_object | awk '{print $NF}'` +# Get rid of the prefix (any path associated with the link) and the extension +basepart=`echo $link | awk -F/ '{print $NF}' | sed 's/'"$ext"'$//'` +# Resulting $basepart should be of form -- A_B_C +encryption_lib=`echo $basepart | cut -f2 -d'_'` +algorithm=`echo $basepart | cut -f3 -d'_'` +if [ "$encryption_lib" = "$algorithm" -o "" = "$algorithm" ] ; then + echo "Unable to determine encryption library name or algorithm. Please ensure that $txt has the correct format. Exiting..." + exit 1 +fi + +echo "ENCRYPTION_LIB = $encryption_lib" +echo "ALGORITHM = $algorithm" +exit 0 diff --git a/sr_unix/util_help.c b/sr_unix/util_help.c new file mode 100644 index 0000000..6a7cf15 --- /dev/null +++ b/sr_unix/util_help.c @@ -0,0 +1,63 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" +#include "util_help.h" +#include "gtm_stdio.h" /* for snprintf() */ +#include "gtm_string.h" /* for strlen() */ +#include "gtm_stdlib.h" /* for SYSTEM() */ +#include "gtmimagename.h" /* for struct gtmImageName */ + + +error_def(ERR_TEXT); + +#define HELP_CMD_STRING_SIZE 512 +#define EXEC_GTMHELP "$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'", + +#define UTIL_HELP_IMAGES 5 +/* We need the first two entries for compatibility */ +char *utilImageGLDs[UTIL_HELP_IMAGES] = +{ +#define IMAGE_TABLE_ENTRY(A,B) B, +IMAGE_TABLE_ENTRY (INVALID_IMAGE, "") +IMAGE_TABLE_ENTRY (GTM_IMAGE, "gtm") +IMAGE_TABLE_ENTRY (MUPIP_IMAGE, "mupip") +IMAGE_TABLE_ENTRY (DSE_IMAGE, "dse") +IMAGE_TABLE_ENTRY (LKE_IMAGE, "lke") +#undef IMAGE_TABLE_ENTRY +}; + +void util_help(void) +{ + int rc; + char *help_option; + char help_cmd_string[HELP_CMD_STRING_SIZE]; + DCL_THREADGBL_ACCESS; + + SETUP_THREADGBL_ACCESS; + assert(1 >= TREF(parms_cnt)); + assert(GTM_IMAGE < image_type && UTIL_HELP_IMAGES > image_type); + if (0 == TREF(parms_cnt)) + help_option = utilImageGLDs[INVALID_IMAGE]; + else + { + assert(TAREF1(parm_ary, TREF(parms_cnt) - 1)); + assert((char *)-1L != (TAREF1(parm_ary, TREF(parms_cnt) - 1))); + help_option = (TAREF1(parm_ary, TREF(parms_cnt) - 1)); + } + SNPRINTF(help_cmd_string, SIZEOF(help_cmd_string), + "$gtm_dist/mumps -run %%XCMD 'do ^GTMHELP(\"%s\",\"$gtm_dist/%shelp.gld\")'", + help_option, utilImageGLDs[image_type]); + rc = SYSTEM(help_cmd_string); + if (0 != rc) + rts_error_csa(NULL, VARLSTCNT(5) ERR_TEXT, 2, RTS_ERROR_TEXT("HELP command error"), rc); +} + diff --git a/sr_unix/util_help.h b/sr_unix/util_help.h new file mode 100644 index 0000000..ebc004c --- /dev/null +++ b/sr_unix/util_help.h @@ -0,0 +1,16 @@ +/**************************************************************** + * * + * Copyright 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef UTIL_HELP_INCLUDED +#define UTIL_HELP_INCLUDED + +void util_help(void); +#endif diff --git a/sr_unix/wait_for_disk_space.c b/sr_unix/wait_for_disk_space.c new file mode 100644 index 0000000..5a3b5de --- /dev/null +++ b/sr_unix/wait_for_disk_space.c @@ -0,0 +1,155 @@ +/**************************************************************** + * * + * Copyright 2012, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include /* for ENOSPC */ + +#include "anticipatory_freeze.h" +#include "wait_for_disk_space.h" +#include "gtmio.h" +#include "have_crit.h" +#include "filestruct.h" +#include "jnl.h" +#include "error.h" +#include "gtmmsg.h" + +#ifdef DEBUG +GBLDEF uint4 lseekwrite_target; +#endif + +GBLREF jnlpool_addrs jnlpool; +GBLREF volatile int4 exit_state; +GBLREF int4 exi_condition; +GBLREF int4 forced_exit_err; + +error_def(ERR_DSKNOSPCAVAIL); +error_def(ERR_DSKNOSPCBLOCKED); +error_def(ERR_DSKSPCAVAILABLE); +error_def(ERR_ENOSPCQIODEFER); + +/* In case of ENOSPC, if anticipatory freeze scheme is in effect and this process has attached to the + * journal pool, trigger an instance freeze in this case and wait for the disk space to be available + * at which point unfreeze the instance. + */ +void wait_for_disk_space(sgmnt_addrs *csa, char *fn, int fd, off_t offset, char *buf, size_t count, int *save_errno) +{ + boolean_t was_crit; + gd_region *reg; + int fn_len, tmp_errno; + boolean_t freeze_cleared; + char wait_comment[MAX_FREEZE_COMMENT_LEN]; + sgmnt_addrs *repl_csa; +# ifdef DEBUG + uint4 lcl_lseekwrite_target; +# endif + DCL_THREADGBL_ACCESS; /* needed by ANTICIPATORY_FREEZE_AVAILABLE macro */ + + SETUP_THREADGBL_ACCESS; /* needed by ANTICIPATORY_FREEZE_AVAILABLE macro */ +# ifdef DEBUG + /* Reset global to safe state after noting it down in a local (just in case there are errors in this function) */ + lcl_lseekwrite_target = lseekwrite_target; lseekwrite_target = LSEEKWRITE_IS_TO_NONE; +# endif + /* If anticipatory freeze scheme is not in effect, or if this database does not care about it, + * or DSKNOSPCAVAIL is not configured as a custom error, return right away. + */ + if (!ANTICIPATORY_FREEZE_ENABLED(csa) || (NULL == is_anticipatory_freeze_needed_fnptr) + || !(*is_anticipatory_freeze_needed_fnptr)(csa, ERR_DSKNOSPCAVAIL)) + return; + fn_len = STRLEN(fn); + repl_csa = &FILE_INFO(jnlpool.jnlpool_dummy_reg)->s_addrs; + was_crit = repl_csa->now_crit; + reg = csa->region; + if (!was_crit) + { /* Setting the instance freeze requires the journal pool lock (grab_lock). However, we need to be careful + * to avoid a deadlock. A deadlock is possible if we hold the io_in_prog_latch, and meanwhile another + * process has grabbed crit in t_end/tp_tend, grabbed the journal pool lock, and is now waiting on the + * io_in_prog_latch (e.g., via jnl_write). By doing a blocking wait in grab_lock here, we would + * deadlock. Therefore, we must pass is_blocking_wait = FALSE to grab_lock. If grab_lock does not succeed, + * we return right away and do not complete the jnl or db write operation for which we are waiting for disk + * space. Since we do not hold crit, we can safely proceed without its completion. + * On the other hand, this scenario is not possible if we hold crit on the region of interest. In this + * case, a normal grab_lock is fine (is_blocking_wait = TRUE). + */ + if (csa->now_crit) + grab_lock(jnlpool.jnlpool_dummy_reg, TRUE, GRAB_LOCK_ONLY); + else if (FALSE == grab_lock(jnlpool.jnlpool_dummy_reg, FALSE, GRAB_LOCK_ONLY)) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_ENOSPCQIODEFER, 2, fn_len, fn); + *save_errno = ERR_ENOSPCQIODEFER; + return; + } + } + /* We either came into this function holding journal pool lock or grab_lock() succeeded */ + assert(NULL != jnlpool.jnlpool_ctl); + assert(NULL != fn); /* if "csa" is non-NULL, fn better be non-NULL as well */ + /* The "send_msg" of DSKNOSPCAVAIL done below will set instance freeze (the configuration file includes it). After that, we + * will keep retrying the IO waiting for disk space to become available. If yes, we will clear the freeze. Until that is + * done, we should not allow ourselves to be interrupted as otherwise interrupt code can try to write to the db/jnl (as + * part of DB_LSEEKWRITE) and the first step there would be to wait for the freeze to be lifted off. Since we were the ones + * who set the freeze in the first place, the auto-clearing of freeze (on disk space freeup) will no longer work in that + * case. Hence the reason not to allow interrupts. + */ + DEFER_INTERRUPTS(INTRPT_IN_WAIT_FOR_DISK_SPACE); + send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DSKNOSPCAVAIL, 2, fn_len, fn); /* this should set the instance freeze */ + /* Make a copy of the freeze comment which would be set by the previous message. */ + GENERATE_INST_FROZEN_COMMENT(wait_comment, MAX_FREEZE_COMMENT_LEN, ERR_DSKNOSPCAVAIL); + tmp_errno = *save_errno; + assert(ENOSPC == tmp_errno); + /* Hang/retry waiting for the disk space situation to be cleared. */ + for ( ; ENOSPC == tmp_errno; ) + { + if (!IS_REPL_INST_FROZEN) + { /* Some other process cleared the instance freeze. But we still dont have our disk + * space issue resolved so set the freeze flag again until space is available for us. + */ + send_msg_csa(CSA_ARG(csa) VARLSTCNT(4) ERR_DSKNOSPCAVAIL, 2, fn_len, fn); + } else if (exit_state != 0) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); + gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(1) forced_exit_err); + exit(-exi_condition); + } + /* Sleep for a while before retrying the write. Do not use "hiber_start" as that + * uses timers and if we are already in a timer handler now, nested timers wont work. + */ + SHORT_SLEEP(SLEEP_IORETRYWAIT); + DEBUG_ONLY(CLEAR_FAKE_ENOSPC_IF_MASTER_DEAD); + /* If some other process froze the instance and changed the comment, a retry of the + * LSEEKWRITE may not be appropriate, so just loop waiting for the freeze to be lifted. + */ + if (IS_REPL_INST_FROZEN && (STRCMP(wait_comment, jnlpool.jnlpool_ctl->freeze_comment) != 0)) + { + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSKNOSPCBLOCKED, 2, fn_len, fn); + WAIT_FOR_REPL_INST_UNFREEZE(csa) + } + LSEEKWRITE(fd, offset, buf, count, tmp_errno); +# ifdef DEBUG + if (LSEEKWRITE_IS_TO_DB == lcl_lseekwrite_target) + FAKE_ENOSPC(csa, fake_db_enospc, lcl_lseekwrite_target, tmp_errno) + else if (LSEEKWRITE_IS_TO_JNL == lcl_lseekwrite_target) + FAKE_ENOSPC(csa, fake_jnl_enospc, lcl_lseekwrite_target, tmp_errno) +# endif + } + /* Report that we were able to continue whether we are still frozen or not. */ + send_msg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_DSKSPCAVAILABLE, 2, fn_len, fn); + /* Only report if we were the process to set the current freeze comment; otherwise someone else reported it. */ + if (STRCMP(wait_comment, jnlpool.jnlpool_ctl->freeze_comment) == 0) + { + CLEAR_ANTICIPATORY_FREEZE(freeze_cleared); /* sets freeze_cleared */ + REPORT_INSTANCE_UNFROZEN(freeze_cleared); + } + *save_errno = tmp_errno; + ENABLE_INTERRUPTS(INTRPT_IN_WAIT_FOR_DISK_SPACE); + if (!was_crit) + rel_lock(jnlpool.jnlpool_dummy_reg); + return; +} diff --git a/sr_unix/wait_for_disk_space.h b/sr_unix/wait_for_disk_space.h new file mode 100644 index 0000000..809a35e --- /dev/null +++ b/sr_unix/wait_for_disk_space.h @@ -0,0 +1,17 @@ +/**************************************************************** + * * + * Copyright 2012 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#ifndef __WAIT_FOR_DISK_SPACE_H__ +#define __WAIT_FOR_DISK_SPACE_H__ + +void wait_for_disk_space(sgmnt_addrs *csa, char *fn, int fd, off_t offset, char *buf, size_t count, int *save_errno); + +#endif diff --git a/sr_vvms/grab_crit_immediate.c b/sr_vvms/grab_crit_immediate.c new file mode 100644 index 0000000..4157532 --- /dev/null +++ b/sr_vvms/grab_crit_immediate.c @@ -0,0 +1,109 @@ +/**************************************************************** + * * + * Copyright 2001, 2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + +#include "mdef.h" + +#include /* for VSIG_ATOMIC_T type */ + +#include "gdsroot.h" +#include "gtm_facility.h" +#include "fileinfo.h" +#include "gdsbt.h" +#include "gdsfhead.h" +#include "ccp.h" +#include "ccpact.h" +#include "error.h" +#include "filestruct.h" +#include "wcs_recover.h" + +error_def(ERR_CRITRESET); +error_def(ERR_DBCCERR); + +GBLREF short crash_count; +GBLREF volatile int4 crit_count; +GBLREF int4 exi_condition; +GBLREF VSIG_ATOMIC_T forced_exit; +GBLREF uint4 process_id; +GBLREF sgmnt_addrs *vms_mutex_check_csa; + +/* One try to grab crit; no waiting because of possible deadlock. Used by TP */ + +boolean_t grab_crit_immediate(gd_region *reg) +{ + unsigned short cycle_count, cycle; + ccp_action_aux_value msg; + sgmnt_addrs *csa; + enum cdb_sc status; + node_local_ptr_t cnl; + + csa = &FILE_INFO(reg)->s_addrs; + vms_mutex_check_csa = csa; + cnl = csa->nl; + if (!csa->now_crit) + { + assert(0 == crit_count); + crit_count++; + if (csa->hdr->clustered) + { + /* For an explanation of the code dealing with clusters, see CCP_EXITWM_ATTEMPT.C. + Please do not change this code without updating the comments in that file. */ + cycle = cnl->ccp_cycle; + if (!CCP_SEGMENT_STATE(cnl, CCST_MASK_WRITE_MODE)) + return FALSE; + } + if ((status = mutex_lockwim(csa->critical, crash_count, &csa->now_crit)) != cdb_sc_normal) + { + crit_count = 0; + switch (status) + { + case cdb_sc_nolock: + return FALSE; + case cdb_sc_critreset: + rts_error_csa(CSA_ARG(NULL) ERR_CRITRESET, 2, REG_LEN_STR(reg)); + case cdb_sc_dbccerr: + rts_error_csa(CSA_ARG(NULL) ERR_DBCCERR, 2, REG_LEN_STR(reg)); + default: + if (forced_exit) + EXIT(exi_condition); + GTMASSERT; + } + return FALSE; + } + assert(cnl->in_crit == 0); + cnl->in_crit = process_id; + if (csa->hdr->clustered) + { + cycle = cnl->ccp_cycle; + if (cnl->ccp_crit_blocked) + { + msg.exreq.fid = FILE_INFO(reg)->file_id; + msg.exreq.cycle = cycle; + (void)ccp_sendmsg(CCTR_EXITWM, &msg); + (void)ccp_userwait(reg, ~(CCST_MASK_WRITE_MODE), 0, cycle); + if (cnl->ccp_crit_blocked && (cnl->ccp_cycle == cycle) || + !CCP_SEGMENT_STATE(cnl, CCST_MASK_WRITE_MODE)) + { + crit_count = 0; + rel_crit(reg); + return FALSE; + } + } + } + crit_count = 0; + } + /* We can be in an AST if we are called wcs_wipchk_ast(). In that case don't do wcs_recover since it can + * cause deadlocks. Let the next guy obtaining crit do it. Note also the order of the statements in the + * if. wc_blocked is very rarely TRUE and hence is placed ahead of the lib$ast_in_prog check. + */ + if (cnl->wc_blocked && !lib$ast_in_prog()) + wcs_recover(reg); + return TRUE; +} diff --git a/sr_vvms/kitprepare.com b/sr_vvms/kitprepare.com new file mode 100644 index 0000000..932e67b --- /dev/null +++ b/sr_vvms/kitprepare.com @@ -0,0 +1,73 @@ +$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +$! ! +$! Copyright 2013 Fidelity Information Services, Inc ! +$! ! +$! This source code contains the intellectual property ! +$! of its copyright holder(s), and is made available ! +$! under a license. If you do not know the terms of ! +$! the license, please stop and do not read further. ! +$! ! +$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +$! The purpose of this script is to generate save the full directory +$! information to dir_full.txt and record the checksum for each file. +$ +$! p1 - version to get kits for (e.g. V50000D) +$ +$ if (p1 .eqs. "") +$ then +$ write sys$output "" +$ write sys$output "With yeti or bgfoot as the build system of record" +$ write sys$output "Syntax : @gtm$tools:kitprepare " +$ write sys$output " e.g. @gtm$tools:kitprepare V60002" +$ write sys$output "" +$ exit +$ endif +$ +$! Check if the kits we expect to see are present in GTM$VRT:[DIST] +$ gtmverno = p1 +$ distdir = "gtm$root:[" + gtmverno + ".dist]" +$ +$ set def gtm$root:['gtmverno] +$ set def [.dist] +$ purge/log *.* +$ if (f$search("dir_full.txt") .nes. "") +$ then +$ delete/log dir_full.txt; +$ endif +$ dir/full /out=dir_full.txt +$ +$ open/append dirlist dir_full.txt +$ +$! the following list has to be maintained in sync with "distrib_kits_vms" defined in $cms_tools/server_list +$ kitlist = "GTCDxxxxx.A,GTCMxxxxx.A,GTDCxxxxx.A,GTMxxxxx.A,GTMxxxxx.B,GTMxxxxx.C" +$! +$ numkits = f$length(kitlist) +$ partial_list = "''kitlist'" +$ verlength = f$length(gtmverno) +$ kitver = f$extract(1, 5, gtmverno) +$kitcheckloop: +$ index = f$locate(",",partial_list) +$ curkit = f$extract(0, index, partial_list) +$ partial_list = f$extract(index + 1, numkits, partial_list) +$ if (curkit .eqs. "") then goto endkitcheckloop +$ length = f$length(curkit) +$ xxindex = f$locate("xxxxx",curkit) +$ kitprefix = f$extract(0, xxindex, curkit) +$ kitsuffix = f$extract(xxindex+5, length, curkit) +$ kitfile = distdir + kitprefix + kitver + kitsuffix +$ if (f$search(kitfile) .eqs. "") +$ then +$ msg = "''kitfile' does not exist. First run @gtm$com:kitstart all ''gtmverno' user:[library.''gtmverno'.dist]" +$ write sys$output "KITPREP-E-NOKITS : ''msg'" +$ write dirlist "KITPREP-E-NOKITS : ''msg'" +$ exit 0 ! to signal error +$ endif +$ checksum 'kitfile +$ filename = f$parse(kitfile,,,"NAME") + f$parse(kitfile,,,"TYPE") +$ write sys$output "KITPREP-I-CHECKSUM : ''filename' : checksum = [''checksum$checksum'] " +$ write dirlist "KITPREP-I-CHECKSUM : ''filename' : checksum = [''checksum$checksum'] " +$ goto kitcheckloop +$endkitcheckloop: +$ +$ write sys$output "KITPREP-S-SUCCESS : KITPREP completed successfully" +$ write dirlist "KITPREP-S-SUCCESS : KITPREP completed successfully" diff --git a/sr_vvms/spkitupdate.com b/sr_vvms/spkitupdate.com new file mode 100644 index 0000000..e64a338 --- /dev/null +++ b/sr_vvms/spkitupdate.com @@ -0,0 +1,28 @@ +$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +$! ! +$! Copyright 2001, 2013 Fidelity Information Services Inc ! +$! ! +$! This source code contains the intellectual property ! +$! of its copyright holder(s), and is made available ! +$! under a license. If you do not know the terms of ! +$! the license, please stop and do not read further. ! +$! ! +$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +$! +$! spkitupdate.com p1=version +$! +$ vno = p1 +$ p1 = "" +$ say = "write sys$output" +$ gawk:=$gtm_bin:gawk.exe +$ say "Fixing the version in packaging config files to "'vno' +$ ver 'vno' p +$ curr_priv = f$setprv("sysprv") +$ gtma := $ gtm$exe:gtm$dmod.exe +$ gtma "user:[library.''vno']" +d ^spkitbld +$ curr_priv=f$setprv(curr_priv) +$ delete/nolog/since spkitbld.obj.,_ucase.obj. +$ say "Should show the correct version" +$ pipe gawk /commands ="/KITNAME/{printf(""%-32s\t%s\n"", FILENAME, $2);}" /field_sep=":=" gtm$vrt:[t%%]*_spkitbld.dat +$ exit diff --git a/sr_x86_64/merrors_ansi.h b/sr_x86_64/merrors_ansi.h new file mode 100644 index 0000000..38cc6a1 --- /dev/null +++ b/sr_x86_64/merrors_ansi.h @@ -0,0 +1,1364 @@ +/**************************************************************** + * * + * Copyright 2001,2013 Fidelity Information Services, Inc * + * * + * This source code contains the intellectual property * + * of its copyright holder(s), and is made available * + * under a license. If you do not know the terms of * + * the license, please stop and do not read further. * + * * + ****************************************************************/ + + +const static readonly int error_ansi[] = { + 0, /* ACK */ + 0, /* BREAKZST */ + 0, /* BADACCMTHD */ + 0, /* BADJPIPARAM */ + 0, /* BADSYIPARAM */ + 0, /* BITMAPSBAD */ + 0, /* BREAK */ + 0, /* BREAKDEA */ + 0, /* BREAKZBA */ + 0, /* STATCNT */ + 0, /* BTFAIL */ + 0, /* MUPRECFLLCK */ + 0, /* CMD */ + 0, /* COLON */ + 0, /* COMMA */ + 0, /* COMMAORRPAREXP */ + 0, /* COMMENT */ + 0, /* CTRAP */ + 0, /* CTRLC */ + 0, /* CTRLY */ + 0, /* DBCCERR */ + 0, /* DUPTOKEN */ + 0, /* DBJNLNOTMATCH */ + 0, /* DBFILERR */ + 0, /* DBNOTGDS */ + 0, /* DBOPNERR */ + 0, /* DBRDERR */ + 0, /* CCEDUMPNOW */ + 0, /* DEVPARINAP */ + 0, /* RECORDSTAT */ + 0, /* NOTGBL */ + 0, /* DEVPARPROT */ + 0, /* PREMATEOF */ + 0, /* GVINVALID */ + 0, /* DEVPARTOOBIG */ + 0, /* DEVPARUNK */ + 0, /* DEVPARVALREQ */ + 0, /* DEVPARMNEG */ + 0, /* DSEBLKRDFAIL */ + 0, /* DSEFAIL */ + 0, /* NOTALLREPLON */ + 0, /* BADLKIPARAM */ + 0, /* JNLREADBOF */ + 0, /* DVIKEYBAD */ + 0, /* ENQ */ + 0, /* EQUAL */ + 0, /* ERRORSUMMARY */ + 0, /* ERRWEXC */ + 0, /* ERRWIOEXC */ + 0, /* ERRWZBRK */ + 0, /* ERRWZTRAP */ + 0, /* NUMUNXEOR */ + 0, /* EXPR */ + 0, /* STRUNXEOR */ + 0, /* JNLEXTEND */ + 0, /* FCHARMAXARGS */ + 0, /* FCNSVNEXPECTED */ + 2, /* FNARGINC */ + 0, /* JNLACCESS */ + 44, /* TRANSNOSTART */ + 0, /* FNUMARG */ + 0, /* FOROFLOW */ + 0, /* YDIRTSZ */ + 0, /* JNLSUCCESS */ + 29, /* GBLNAME */ + 0, /* GBLOFLOW */ + 0, /* CORRUPT */ + 0, /* GTMCHECK */ + 0, /* GVDATAFAIL */ + 0, /* EORNOTFND */ + 0, /* GVGETFAIL */ + 0, /* GVIS */ + 0, /* GVKILLFAIL */ + 1, /* GVNAKED */ + 0, /* GVNEXTARG */ + 0, /* GVORDERFAIL */ + 0, /* GVPUTFAIL */ + 0, /* PATTABSYNTAX */ + 0, /* GVSUBOFLOW */ + 7, /* GVUNDEF */ + 0, /* TRANSNEST */ + 0, /* INDEXTRACHARS */ + 0, /* UNUSEDMSG260 */ + 0, /* INDRMAXLEN */ + 0, /* INSFFBCNT */ + 0, /* INTEGERRS */ + 0, /* INVCMD */ + 0, /* INVFCN */ + 0, /* INVOBJ */ + 8, /* INVSVN */ + 0, /* IOEOF */ + 0, /* IONOTOPEN */ + 0, /* MUPIPINFO */ + 0, /* IVTIME */ + 0, /* JOBFAIL */ + 13, /* JOBLABOFF */ + 0, /* JOBPARNOVAL */ + 0, /* JOBPARNUM */ + 0, /* JOBPARSTR */ + 0, /* JOBPARUNK */ + 0, /* JOBPARVALREQ */ + 0, /* JUSTFRACT */ + 0, /* KEY2BIG */ + 0, /* LABELEXPECTED */ + 13, /* LABELMISSING */ + 13, /* LABELUNKNOWN */ + 9, /* DIVZERO */ + 0, /* LKNAMEXPECTED */ + 0, /* JNLRDERR */ + 25, /* LOADRUNNING */ + 0, /* LPARENMISSING */ + 0, /* LSEXPECTED */ + 0, /* LVORDERARG */ + 0, /* MAXFORARGS */ + 0, /* TRANSMINUS */ + 0, /* MAXNRSUBSCRIPTS */ + 75, /* MAXSTRLEN */ + 0, /* JNLDBERR */ + 0, /* JNLFILOPN */ + 0, /* MBXRDONLY */ + 0, /* JNLINVALID */ + 0, /* MBXWRTONLY */ + 0, /* MEMORY */ + 70, /* MTBLKTOOBIG */ + 70, /* MTBLKTOOSM */ + 70, /* MTFIXRECSZ */ + 0, /* MTIS */ + 0, /* MTRDBADBLK */ + 62, /* MTRDONLY */ + 0, /* MTRDTHENWRT */ + 71, /* MTRECGTRBLK */ + 72, /* MTRECTOOBIG */ + 72, /* MTRECTOOSM */ + 0, /* JNLTMQUAL3 */ + 57, /* MULTLAB */ + 0, /* BLKCNT */ + 0, /* CCEDUMPOFF */ + 0, /* NOPLACE */ + 0, /* JNLCLOSE */ + 0, /* NOTPRINCIO */ + 0, /* NOTTOEOFONPUT */ + 0, /* NOZBRK */ + 0, /* NULSUBSC */ + 92, /* NUMOFLOW */ + 0, /* PARFILSPC */ + 0, /* PATCLASS */ + 10, /* PATCODE */ + 0, /* PATLIT */ + 0, /* PATMAXLEN */ + 0, /* LPARENREQD */ + 10, /* PATUPPERLIM */ + 0, /* PCONDEXPECTED */ + 0, /* PRCNAMLEN */ + 3, /* RANDARGNEG */ + 0, /* DBPRIVERR */ + 75, /* REC2BIG */ + 0, /* RHMISSING */ + 62, /* DEVICEREADONLY */ + 0, /* COLLDATAEXISTS */ + 88, /* ROUTINEUNKNOWN */ + 0, /* RPARENMISSING */ + 0, /* RTNNAME */ + 0, /* VIEWGVN */ + 0, /* RTSLOC */ + 0, /* RWARG */ + 0, /* RWFORMAT */ + 0, /* JNLWRTDEFER */ + 4, /* SELECTFALSE */ + 0, /* SPOREOL */ + 0, /* SRCLIN */ + 0, /* SRCLOC */ + 0, /* SRCLOCUNKNOWN */ + 0, /* STACKCRIT */ + 0, /* STACKOFLOW */ + 0, /* STACKUNDERFLO */ + 0, /* STRINGOFLOW */ + 0, /* SVNOSET */ + 0, /* VIEWFN */ + 0, /* TERMASTQUOTA */ + 5, /* TEXTARG */ + 0, /* TMPSTOREMAX */ + 0, /* VIEWCMD */ + 0, /* JNI */ + 0, /* TXTSRCFMT */ + 0, /* UIDMSG */ + 0, /* UIDSND */ + 6, /* UNDEF */ + 0, /* UNIMPLOP */ + 39, /* VAREXPECTED */ + 0, /* VARRECBLKSZ */ + 0, /* MAXARGCNT */ + 0, /* GTMSECSHRSEMGET */ + 0, /* VIEWARGCNT */ + 0, /* GTMSECSHRDMNSTARTED */ + 0, /* ZATTACHERR */ + 0, /* ZDATEFMT */ + 0, /* ZEDFILSPEC */ + 75, /* ZFILENMTOOLONG */ + 0, /* ZFILKEYBAD */ + 0, /* ZFILNMBAD */ + 0, /* ZGOTOLTZERO */ + 0, /* ZGOTOTOOBIG */ + 0, /* ZLINKFILE */ + 0, /* ZPARSETYPE */ + 0, /* ZPARSFLDBAD */ + 0, /* ZPIDBADARG */ + 0, /* ZPRIVARGBAD */ + 0, /* ZPRIVSYNTAXERR */ + 13, /* ZPRTLABNOTFND */ + 0, /* VIEWAMBIG */ + 0, /* VIEWNOTFOUND */ + 0, /* ZSETPRVARGBAD */ + 0, /* INVSPECREC */ + 0, /* ZSETPRVSYNTAX */ + 0, /* ZSRCHSTRMCT */ + 0, /* VERSION */ + 0, /* MUNOTALLSEC */ + 0, /* MUSECDEL */ + 0, /* MUSECNOTDEL */ + 0, /* RPARENREQD */ + 26, /* ZGBLDIRACC */ + 0, /* GVNAKEDEXTNM */ + 0, /* EXTGBLDEL */ + 0, /* DSEWCINITCON */ + 0, /* LASTFILCMPLD */ + 0, /* NOEXCNOZTRAP */ + 0, /* UNSDCLASS */ + 0, /* UNSDDTYPE */ + 0, /* ZCUNKTYPE */ + 0, /* ZCUNKMECH */ + 0, /* ZCUNKQUAL */ + 0, /* JNLDBTNNOMATCH */ + 0, /* ZCALLTABLE */ + 58, /* ZCARGMSMTCH */ + 58, /* ZCCONMSMTCH */ + 0, /* ZCOPT0 */ + 0, /* ZCSTATUS */ + 0, /* ZCUSRRTN */ + 0, /* ZCPOSOVR */ + 0, /* ZCINPUTREQ */ + 0, /* JNLTNOUTOFSEQ */ + 0, /* ACTRANGE */ + 0, /* ZCCONVERT */ + 0, /* ZCRTENOTF */ + 0, /* GVRUNDOWN */ + 0, /* LKRUNDOWN */ + 0, /* IORUNDOWN */ + 0, /* FILENOTFND */ + 0, /* MUFILRNDWNFL */ + 0, /* JNLTMQUAL1 */ + 0, /* FORCEDHALT */ + 0, /* LOADEOF */ + 0, /* WILLEXPIRE */ + 0, /* LOADEDBG */ + 0, /* LABELONLY */ + 0, /* MUREORGFAIL */ + 0, /* GVZPREVFAIL */ + 21, /* MULTFORMPARM */ + 16, /* QUITARGUSE */ + 0, /* NAMEEXPECTED */ + 11, /* FALLINTOFLST */ + 16, /* NOTEXTRINSIC */ + 0, /* GTMSECSHRREMSEMFAIL */ + 20, /* FMLLSTMISSING */ + 58, /* ACTLSTTOOLONG */ + 0, /* ACTOFFSET */ + 0, /* MAXACTARG */ + 0, /* GTMSECSHRREMSEM */ + 0, /* JNLTMQUAL2 */ + 0, /* GDINVALID */ + 0, /* ASSERT */ + 0, /* MUFILRNDWNSUC */ + 0, /* LOADEDSZ */ + 16, /* QUITARGLST */ + 17, /* QUITARGREQD */ + 0, /* CRITRESET */ + 0, /* UNKNOWNFOREX */ + 0, /* FSEXP */ + 0, /* WILDCARD */ + 0, /* DIRONLY */ + 0, /* FILEPARSE */ + 0, /* QUALEXP */ + 0, /* BADQUAL */ + 0, /* QUALVAL */ + 0, /* ZROSYNTAX */ + 0, /* COMPILEQUALS */ + 0, /* ZLNOOBJECT */ + 0, /* ZLMODULE */ + 0, /* DBBLEVMX */ + 0, /* DBBLEVMN */ + 0, /* DBBSIZMN */ + 0, /* DBBSIZMX */ + 0, /* DBRSIZMN */ + 0, /* DBRSIZMX */ + 0, /* DBCMPNZRO */ + 0, /* DBSTARSIZ */ + 0, /* DBSTARCMP */ + 0, /* DBCMPMX */ + 0, /* DBKEYMX */ + 0, /* DBKEYMN */ + 0, /* DBCMPBAD */ + 0, /* DBKEYORD */ + 0, /* DBPTRNOTPOS */ + 0, /* DBPTRMX */ + 0, /* DBPTRMAP */ + 0, /* IFBADPARM */ + 0, /* IFNOTINIT */ + 0, /* GTMSECSHRSOCKET */ + 0, /* LOADBGSZ */ + 0, /* LOADFMT */ + 0, /* LOADFILERR */ + 0, /* NOREGION */ + 0, /* PATLOAD */ + 0, /* EXTRACTFILERR */ + 0, /* FREEZE */ + 0, /* NOSELECT */ + 0, /* EXTRFAIL */ + 0, /* LDBINFMT */ + 0, /* NOPREVLINK */ + 0, /* CCEDUMPON */ + 0, /* CCEDMPQUALREQ */ + 0, /* CCEDBDUMP */ + 0, /* CCEDBNODUMP */ + 0, /* CCPMBX */ + 0, /* REQRUNDOWN */ + 0, /* CCPINTQUE */ + 0, /* CCPBADMSG */ + 0, /* CNOTONSYS */ + 0, /* CCPNAME */ + 0, /* CCPNOTFND */ + 0, /* OPRCCPSTOP */ + 0, /* SELECTSYNTAX */ + 0, /* LOADABORT */ + 0, /* FNOTONSYS */ + 0, /* AMBISYIPARAM */ + 0, /* PREVJNLNOEOF */ + 0, /* LKSECINIT */ + 0, /* MTDOSLAB */ + 0, /* MTDOSFOR */ + 0, /* MTINVLAB */ + 0, /* TXTSRCMAT */ + 0, /* CCENOGROUP */ + 0, /* BADDBVER */ + 0, /* LINKVERSION */ + 0, /* TOTALBLKMAX */ + 0, /* LOADCTRLY */ + 0, /* CLSTCONFLICT */ + 0, /* SRCNAM */ + 0, /* LCKGONE */ + 0, /* SUB2LONG */ + 0, /* EXTRACTCTRLY */ + 0, /* CCENOWORLD */ + 0, /* GVQUERYFAIL */ + 0, /* LCKSCANCELLED */ + 0, /* INVNETFILNM */ + 0, /* NETDBOPNERR */ + 0, /* BADSRVRNETMSG */ + 0, /* BADGTMNETMSG */ + 0, /* SERVERERR */ + 0, /* NETFAIL */ + 0, /* NETLCKFAIL */ + 0, /* TTINVFILTER */ + 0, /* MTANSILAB */ + 0, /* MTANSIFOR */ + 0, /* BADTRNPARAM */ + 0, /* DSEONLYBGMM */ + 0, /* DSEINVLCLUSFN */ + 18, /* RDFLTOOSHORT */ + 0, /* TIMRBADVAL */ + 0, /* CCENOSYSLCK */ + 0, /* CCPGRP */ + 0, /* UNSOLCNTERR */ + 0, /* BACKUPCTRL */ + 0, /* NOCCPPID */ + 0, /* CCPJNLOPNERR */ + 0, /* LCKSGONE */ + 0, /* ZLKIDBADARG */ + 0, /* DBFILOPERR */ + 0, /* CCERDERR */ + 0, /* CCEDBCL */ + 0, /* CCEDBNTCL */ + 0, /* CCEWRTERR */ + 0, /* CCEBADFN */ + 0, /* CCERDTIMOUT */ + 0, /* CCPSIGCONT */ + 0, /* CCEBGONLY */ + 0, /* CCENOCCP */ + 0, /* CCECCPPID */ + 0, /* CCECLSTPRCS */ + 0, /* ZSHOWBADFUNC */ + 0, /* NOTALLJNLEN */ + 0, /* ZSHOWGLOSMALL */ + 0, /* NOLBRSRC */ + 0, /* INVZSTEP */ + 0, /* ZSTEPARG */ + 0, /* INVSTRLEN */ + 0, /* RECCNT */ + 0, /* TEXT */ + 0, /* ZWRSPONE */ + 0, /* FILEDEL */ + 0, /* JNLBADLABEL */ + 0, /* JNLREADEOF */ + 0, /* JNLRECFMT */ + 0, /* BLKTOODEEP */ + 0, /* NESTFORMP */ + 0, /* BINHDR */ + 0, /* GOQPREC */ + 0, /* LDGOQFMT */ + 0, /* BEGINST */ + 0, /* INVMVXSZ */ + 0, /* JNLWRTNOWWRTR */ + 0, /* GTMSECSHRSHMCONCPROC */ + 0, /* JNLINVALLOC */ + 0, /* JNLINVEXT */ + 0, /* MUPCLIERR */ + 0, /* JNLTMQUAL4 */ + 0, /* GTMSECSHRREMSHM */ + 0, /* GTMSECSHRREMFILE */ + 0, /* MUNODBNAME */ + 0, /* FILECREATE */ + 0, /* FILENOTCREATE */ + 0, /* JNLPROCSTUCK */ + 0, /* INVGLOBALQUAL */ + 0, /* COLLARGLONG */ + 0, /* NOPINI */ + 0, /* DBNOCRE */ + 0, /* JNLSPACELOW */ + 0, /* DBCOMMITCLNUP */ + 0, /* BFRQUALREQ */ + 0, /* REQDVIEWPARM */ + 0, /* COLLFNMISSING */ + 0, /* JNLACTINCMPLT */ + 0, /* NCTCOLLDIFF */ + 0, /* DLRCUNXEOR */ + 0, /* DLRCTOOBIG */ + 0, /* WCERRNOTCHG */ + 0, /* WCWRNNOTCHG */ + 0, /* ZCWRONGDESC */ + 0, /* MUTNWARN */ + 0, /* GTMSECSHRUPDDBHDR */ + 0, /* LCKSTIMOUT */ + 0, /* CTLMNEMAXLEN */ + 0, /* CTLMNEXPECTED */ + 0, /* USRIOINIT */ + 0, /* CRITSEMFAIL */ + 0, /* TERMWRITE */ + 0, /* COLLTYPVERSION */ + 0, /* LVNULLSUBS */ + 0, /* GVREPLERR */ + 0, /* MTIOERR */ + 72, /* RMWIDTHPOS */ + 13, /* OFFSETINV */ + 0, /* JOBPARTOOLONG */ + 0, /* JOBARGMISSING */ + 0, /* RUNPARAMERR */ + 0, /* FNNAMENEG */ + 0, /* ORDER2 */ + 0, /* MUNOUPGRD */ + 0, /* REORGCTRLY */ + 0, /* TSTRTPARM */ + 0, /* TRIGNAMENF */ + 0, /* TRIGZBREAKREM */ + 44, /* TLVLZERO */ + 27, /* TRESTNOT */ + 41, /* TPLOCK */ + 42, /* TPQUIT */ + 0, /* TPFAIL */ + 0, /* TPRETRY */ + 0, /* TPTOODEEP */ + 0, /* ZDEFACTIVE */ + 0, /* ZDEFOFLOW */ + 0, /* MUPRESTERR */ + 0, /* MUBCKNODIR */ + 0, /* TRANS2BIG */ + 0, /* INVBITLEN */ + 0, /* INVBITSTR */ + 0, /* INVBITPOS */ + 0, /* PARNORMAL */ + 0, /* PARBUFSM */ + 72, /* RMWIDTHTOOBIG */ + 0, /* PATTABNOTFND */ + 0, /* OBJFILERR */ + 0, /* SRCFILERR */ + 95, /* NEGFRACPWR */ + 0, /* MTNOSKIP */ + 0, /* CETOOMANY */ + 0, /* CEUSRERROR */ + 0, /* CEBIGSKIP */ + 0, /* CETOOLONG */ + 0, /* CENOINDIR */ + 0, /* COLLATIONUNDEF */ + 0, /* RBWRNNOTCHG */ + 0, /* GTMSECSHRSRVF */ + 0, /* FREEZECTRL */ + 0, /* JNLFLUSH */ + 0, /* CCPSIGDMP */ + 0, /* NOPRINCIO */ + 0, /* INVPORTSPEC */ + 0, /* INVADDRSPEC */ + 78, /* SOCKPARMREQ */ + 0, /* IPADDRREQ */ + 80, /* SOCKWAIT */ + 81, /* SOCKACPT */ + 80, /* SOCKINIT */ + 81, /* OPENCONN */ + 0, /* DEVNOTIMP */ + 0, /* JNLEXTR */ + 0, /* DBREMOTE */ + 0, /* JNLREQUIRED */ + 0, /* TPMIXUP */ + 0, /* HTOFLOW */ + 72, /* RMNOBIGRECORD */ + 0, /* DBBMSIZE */ + 0, /* DBBMBARE */ + 0, /* DBBMINV */ + 0, /* DBBMMSTR */ + 0, /* DBROOTBURN */ + 0, /* REPLSTATEERR */ + 0, /* VMSMEMORY */ + 0, /* DBDIRTSUBSC */ + 0, /* TIMEROVFL */ + 0, /* GTMASSERT */ + 0, /* DBFHEADERR4 */ + 0, /* DBADDRANGE */ + 0, /* DBQUELINK */ + 0, /* DBCRERR */ + 0, /* MUSTANDALONE */ + 0, /* MUNOACTION */ + 0, /* RMBIGSHARE */ + 0, /* TPRESTART */ + 0, /* SOCKWRITE */ + 0, /* DBCNTRLERR */ + 0, /* NOTERMENV */ + 0, /* NOTERMENTRY */ + 0, /* NOTERMINFODB */ + 0, /* INVACCMETHOD */ + 0, /* JNLOPNERR */ + 0, /* JNLRECTYPE */ + 0, /* JNLTRANSGTR */ + 0, /* JNLTRANSLSS */ + 0, /* JNLWRERR */ + 0, /* FILEIDMATCH */ + 0, /* EXTSRCLIN */ + 0, /* EXTSRCLOC */ + 0, /* BIGNOACL */ + 0, /* ERRCALL */ + 0, /* ZCCTENV */ + 0, /* ZCCTOPN */ + 0, /* ZCCTNULLF */ + 0, /* ZCUNAVAIL */ + 0, /* ZCENTNAME */ + 0, /* ZCCOLON */ + 0, /* ZCRTNTYP */ + 0, /* ZCRCALLNAME */ + 0, /* ZCRPARMNAME */ + 0, /* ZCUNTYPE */ + 0, /* ZCMLTSTATUS */ + 0, /* ZCSTATUSRET */ + 0, /* ZCMAXPARAM */ + 0, /* ZCCSQRBR */ + 0, /* ZCPREALLNUMEX */ + 0, /* ZCPREALLVALPAR */ + 0, /* VERMISMATCH */ + 0, /* JNLCNTRL */ + 0, /* TRIGNAMBAD */ + 0, /* BUFRDTIMEOUT */ + 0, /* INVALIDRIP */ + 0, /* BLKSIZ512 */ + 0, /* MUTEXERR */ + 0, /* JNLVSIZE */ + 0, /* MUTEXLCKALERT */ + 0, /* MUTEXFRCDTERM */ + 0, /* GTMSECSHR */ + 0, /* GTMSECSHRSRVFID */ + 0, /* GTMSECSHRSRVFIL */ + 0, /* FREEBLKSLOW */ + 0, /* PROTNOTSUP */ + 0, /* DELIMSIZNA */ + 0, /* INVCTLMNE */ + 0, /* SOCKLISTEN */ + 0, /* LQLENGTHNA */ + 0, /* ADDRTOOLONG */ + 0, /* GTMSECSHRGETSEMFAIL */ + 0, /* CPBEYALLOC */ + 0, /* DBRDONLY */ + 0, /* DUPTN */ + 0, /* TRESTLOC */ + 0, /* REPLPOOLINST */ + 0, /* ZCVECTORINDX */ + 0, /* REPLNOTON */ + 0, /* JNLMOVED */ + 0, /* EXTRFMT */ + 0, /* CALLERID */ + 0, /* KRNLKILL */ + 0, /* MEMORYRECURSIVE */ + 0, /* FREEZEID */ + 0, /* BLKWRITERR */ + 0, /* STOPTIMEOUT */ + 0, /* TRIGMODINTP */ + 0, /* BCKUPBUFLUSH */ + 0, /* NOFORKCORE */ + 0, /* JNLREAD */ + 0, /* JNLMINALIGN */ + 0, /* UNUSEDMSG781 */ + 0, /* JNLPOOLSETUP */ + 0, /* JNLSTATEOFF */ + 0, /* RECVPOOLSETUP */ + 0, /* REPLCOMM */ + 0, /* NOREPLCTDREG */ + 0, /* REPLINFO */ + 0, /* REPLWARN */ + 0, /* REPLERR */ + 0, /* JNLNMBKNOTPRCD */ + 0, /* REPLFILIOERR */ + 0, /* REPLBRKNTRANS */ + 0, /* TTWIDTHTOOBIG */ + 0, /* REPLLOGOPN */ + 0, /* REPLFILTER */ + 0, /* GBLMODFAIL */ + 0, /* TTLENGTHTOOBIG */ + 0, /* TPTIMEOUT */ + 0, /* DEFEREVENT */ + 0, /* JNLFILNOTCHG */ + 0, /* EVENTLOGERR */ + 0, /* UPDATEFILEOPEN */ + 0, /* JNLBADRECFMT */ + 0, /* NULLCOLLDIFF */ + 0, /* MUKILLIP */ + 0, /* JNLRDONLY */ + 0, /* ANCOMPTINC */ + 0, /* ABNCOMPTINC */ + 0, /* UNUSEDMSG809 */ + 0, /* SOCKNOTFND */ + 0, /* CURRSOCKOFR */ + 79, /* SOCKETEXIST */ + 76, /* LISTENPASSBND */ + 0, /* DBCLNUPINFO */ + 0, /* MUNODWNGRD */ + 0, /* REPLTRANS2BIG */ + 0, /* RDFLTOOLONG */ + 0, /* MUNOFINISH */ + 0, /* DBFILEXT */ + 0, /* JNLFSYNCERR */ + 0, /* FSYNCTIMOUT */ + 0, /* ZCPREALLVALINV */ + 0, /* NEWJNLFILECREAT */ + 0, /* DSKSPACEFLOW */ + 0, /* GVINCRFAIL */ + 0, /* ISOLATIONSTSCHN */ + 0, /* REPLGBL2LONG */ + 0, /* TRACEON */ + 0, /* TOOMANYCLIENTS */ + 0, /* NOEXCLUDE */ + 0, /* GVINCRISOLATION */ + 0, /* EXCLUDEREORG */ + 0, /* REORGINC */ + 0, /* ASC2EBCDICCONV */ + 0, /* GTMSECSHRSTART */ + 0, /* DBVERPERFWARN1 */ + 0, /* FILEIDGBLSEC */ + 0, /* GBLSECNOTGDS */ + 0, /* BADGBLSECVER */ + 0, /* RECSIZENOTEVEN */ + 0, /* BUFFLUFAILED */ + 0, /* MUQUALINCOMP */ + 0, /* DISTPATHMAX */ + 0, /* UNUSEDMSG844 */ + 0, /* IMAGENAME */ + 0, /* GTMSECSHRPERM */ + 0, /* GTMDISTUNDEF */ + 0, /* SYSCALL */ + 0, /* MAXGTMPATH */ + 0, /* TROLLBK2DEEP */ + 0, /* INVROLLBKLVL */ + 0, /* OLDBINEXTRACT */ + 0, /* ACOMPTBINC */ + 0, /* NOTREPLICATED */ + 0, /* DBPREMATEOF */ + 0, /* KILLBYSIG */ + 0, /* KILLBYSIGUINFO */ + 0, /* KILLBYSIGSINFO1 */ + 0, /* KILLBYSIGSINFO2 */ + 0, /* SIGILLOPC */ + 0, /* SIGILLOPN */ + 0, /* SIGILLADR */ + 0, /* SIGILLTRP */ + 0, /* SIGPRVOPC */ + 0, /* SIGPRVREG */ + 0, /* SIGCOPROC */ + 0, /* SIGBADSTK */ + 0, /* SIGADRALN */ + 0, /* SIGADRERR */ + 0, /* SIGOBJERR */ + 0, /* SIGINTDIV */ + 0, /* SIGINTOVF */ + 0, /* SIGFLTDIV */ + 0, /* SIGFLTOVF */ + 0, /* SIGFLTUND */ + 0, /* SIGFLTRES */ + 0, /* SIGFLTINV */ + 0, /* SIGMAPERR */ + 0, /* SIGACCERR */ + 0, /* TRNLOGFAIL */ + 0, /* INVDBGLVL */ + 0, /* DBMAXNRSUBS */ + 0, /* GTMSECSHRSCKSEL */ + 0, /* GTMSECSHRTMOUT */ + 0, /* GTMSECSHRRECVF */ + 0, /* GTMSECSHRSENDF */ + 0, /* SIZENOTVALID8 */ + 0, /* GTMSECSHROPCMP */ + 0, /* GTMSECSHRSUIDF */ + 0, /* GTMSECSHRSGIDF */ + 0, /* GTMSECSHRSSIDF */ + 0, /* GTMSECSHRFORKF */ + 0, /* DBFSYNCERR */ + 0, /* SECONDAHEAD */ + 0, /* SCNDDBNOUPD */ + 0, /* MUINFOUINT4 */ + 0, /* NLMISMATCHCALC */ + 0, /* UNUSEDMSG898 */ + 0, /* UNUSEDMSG899 */ + 0, /* DBBADNSUB */ + 0, /* DBBADKYNM */ + 0, /* DBBADPNTR */ + 0, /* DBBNPNTR */ + 0, /* DBINCLVL */ + 0, /* DBBFSTAT */ + 0, /* DBBDBALLOC */ + 0, /* DBMRKFREE */ + 0, /* DBMRKBUSY */ + 0, /* DBBSIZZRO */ + 0, /* DBSZGT64K */ + 0, /* DBNOTMLTP */ + 0, /* DBTNTOOLG */ + 0, /* DBBPLMLT512 */ + 0, /* DBBPLMGT2K */ + 0, /* MUINFOUINT8 */ + 0, /* DBBPLNOT512 */ + 0, /* MUINFOSTR */ + 0, /* DBUNDACCMT */ + 0, /* DBTNNEQ */ + 0, /* MUPGRDSUCC */ + 0, /* DBDSRDFMTCHNG */ + 0, /* DBFGTBC */ + 0, /* DBFSTBC */ + 0, /* DBFSTHEAD */ + 0, /* DBCREINCOMP */ + 0, /* DBFLCORRP */ + 0, /* DBHEADINV */ + 0, /* DBINCRVER */ + 0, /* DBINVGBL */ + 0, /* DBKEYGTIND */ + 0, /* DBGTDBMAX */ + 0, /* DBKGTALLW */ + 0, /* DBLTSIBL */ + 0, /* DBLRCINVSZ */ + 0, /* MUREUPDWNGRDEND */ + 0, /* DBLOCMBINC */ + 0, /* DBLVLINC */ + 0, /* DBMBSIZMX */ + 0, /* DBMBSIZMN */ + 0, /* DBMBTNSIZMX */ + 0, /* DBMBMINCFRE */ + 0, /* DBMBPINCFL */ + 0, /* DBMBPFLDLBM */ + 0, /* DBMBPFLINT */ + 0, /* DBMBPFLDIS */ + 0, /* DBMBPFRDLBM */ + 0, /* DBMBPFRINT */ + 0, /* DBMAXKEYEXC */ + 0, /* DBMXRSEXCMIN */ + 0, /* UNUSEDMSG950 */ + 0, /* DBREADBM */ + 0, /* DBCOMPTOOLRG */ + 0, /* DBVERPERFWARN2 */ + 0, /* DBRBNTOOLRG */ + 0, /* DBRBNLBMN */ + 0, /* DBRBNNEG */ + 0, /* DBRLEVTOOHI */ + 0, /* DBRLEVLTONE */ + 0, /* DBSVBNMIN */ + 0, /* DBTTLBLK0 */ + 0, /* DBNOTDB */ + 0, /* DBTOTBLK */ + 0, /* DBTN */ + 0, /* DBNOREGION */ + 0, /* DBTNRESETINC */ + 0, /* DBTNLTCTN */ + 0, /* DBTNRESET */ + 0, /* MUTEXRSRCCLNUP */ + 0, /* SEMWT2LONG */ + 0, /* REPLINSTOPEN */ + 0, /* REPLINSTCLOSE */ + 0, /* UNUSEDMSG972 */ + 0, /* DBCRERR8 */ + 0, /* NUMPROCESSORS */ + 0, /* DBADDRANGE8 */ + 0, /* RNDWNSEMFAIL */ + 0, /* GTMSECSHRSHUTDN */ + 0, /* NOSPACECRE */ + 0, /* LOWSPACECRE */ + 0, /* WAITDSKSPACE */ + 0, /* OUTOFSPACE */ + 0, /* JNLPVTINFO */ + 0, /* NOSPACEEXT */ + 0, /* WCBLOCKED */ + 0, /* REPLJNLCLOSED */ + 0, /* RENAMEFAIL */ + 0, /* FILERENAME */ + 0, /* JNLBUFINFO */ + 0, /* UNUSEDMSG989 */ + 0, /* UNUSEDMSG990 */ + 0, /* TPNOTACID */ + 0, /* JNLSETDATA2LONG */ + 0, /* JNLNEWREC */ + 0, /* REPLFTOKSEM */ + 0, /* UNUSEDMSG995 */ + 0, /* EXTRIOERR */ + 0, /* EXTRCLOSEERR */ + 0, /* UNUSEDMSG998 */ + 0, /* REPLEXITERR */ + 0, /* MUDESTROYSUC */ + 0, /* DBRNDWN */ + 0, /* MUDESTROYFAIL */ + 0, /* NOTALLDBOPN */ + 0, /* MUSELFBKUP */ + 0, /* DBDANGER */ + 0, /* TRUNCATEFAIL */ + 0, /* TCGETATTR */ + 0, /* TCSETATTR */ + 0, /* IOWRITERR */ + 0, /* REPLINSTWRITE */ + 0, /* DBBADFREEBLKCTR */ + 0, /* REQ2RESUME */ + 0, /* TIMERHANDLER */ + 0, /* FREEMEMORY */ + 0, /* MUREPLSECDEL */ + 0, /* MUREPLSECNOTDEL */ + 0, /* MUJPOOLRNDWNSUC */ + 0, /* MURPOOLRNDWNSUC */ + 0, /* MUJPOOLRNDWNFL */ + 0, /* MURPOOLRNDWNFL */ + 0, /* MUREPLPOOL */ + 0, /* REPLACCSEM */ + 0, /* JNLFLUSHNOPROG */ + 0, /* REPLINSTCREATE */ + 0, /* SUSPENDING */ + 0, /* SOCKBFNOTEMPTY */ + 0, /* ILLESOCKBFSIZE */ + 0, /* NOSOCKETINDEV */ + 0, /* SETSOCKOPTERR */ + 0, /* GETSOCKOPTERR */ + 0, /* NOSUCHPROC */ + 0, /* DSENOFINISH */ + 0, /* LKENOFINISH */ + 0, /* NOCHLEFT */ + 0, /* MULOGNAMEDEF */ + 0, /* BUFOWNERSTUCK */ + 0, /* ACTIVATEFAIL */ + 0, /* DBRNDWNWRN */ + 0, /* DLLNOOPEN */ + 0, /* DLLNORTN */ + 0, /* DLLNOCLOSE */ + 0, /* FILTERNOTALIVE */ + 0, /* FILTERCOMM */ + 0, /* FILTERBADCONV */ + 0, /* PRIMARYISROOT */ + 0, /* GVQUERYGETFAIL */ + 0, /* DBCREC2BIGINBLK */ + 19, /* MERGEDESC */ + 0, /* MERGEINCOMPL */ + 0, /* DBNAMEMISMATCH */ + 0, /* DBIDMISMATCH */ + 0, /* DEVOPENFAIL */ + 0, /* IPCNOTDEL */ + 0, /* XCVOIDRET */ + 0, /* MURAIMGFAIL */ + 0, /* REPLINSTUNDEF */ + 0, /* REPLINSTACC */ + 0, /* NOJNLPOOL */ + 0, /* NORECVPOOL */ + 0, /* FTOKERR */ + 0, /* REPLREQRUNDOWN */ + 0, /* BLKCNTEDITFAIL */ + 0, /* SEMREMOVED */ + 0, /* REPLINSTFMT */ + 0, /* SEMKEYINUSE */ + 0, /* XTRNTRANSERR */ + 0, /* XTRNTRANSDLL */ + 0, /* XTRNRETVAL */ + 0, /* XTRNRETSTR */ + 101, /* INVECODEVAL */ + 0, /* SETECODE */ + 0, /* INVSTACODE */ + 0, /* REPEATERROR */ + 90, /* NOCANONICNAME */ + 0, /* NOSUBSCRIPT */ + 0, /* SYSTEMVALUE */ + 0, /* SIZENOTVALID4 */ + 0, /* STRNOTVALID */ + 0, /* UNUSEDMSG1079 */ + 0, /* ERRWETRAP */ + 0, /* TRACINGON */ + 0, /* CITABENV */ + 0, /* CITABOPN */ + 0, /* CIENTNAME */ + 0, /* CIRTNTYP */ + 0, /* CIRCALLNAME */ + 0, /* CIRPARMNAME */ + 0, /* CIDIRECTIVE */ + 0, /* CIPARTYPE */ + 0, /* CIUNTYPE */ + 0, /* CINOENTRY */ + 0, /* JNLINVSWITCHLMT */ + 0, /* SETZDIR */ + 40, /* JOBACTREF */ + 0, /* ECLOSTMID */ + 0, /* ZFF2MANY */ + 0, /* JNLFSYNCLSTCK */ + 0, /* DELIMWIDTH */ + 0, /* DBBMLCORRUPT */ + 0, /* DLCKAVOIDANCE */ + 0, /* WRITERSTUCK */ + 0, /* PATNOTFOUND */ + 0, /* INVZDIRFORM */ + 0, /* ZDIROUTOFSYNC */ + 0, /* GBLNOEXIST */ + 0, /* MAXBTLEVEL */ + 0, /* UNUSEDMSG1107 */ + 0, /* JNLALIGNSZCHG */ + 0, /* UNUSEDMSG1109 */ + 0, /* GVFAILCORE */ + 0, /* DBCDBNOCERTIFY */ + 0, /* DBFRZRESETSUC */ + 0, /* JNLFILEXTERR */ + 0, /* JOBEXAMDONE */ + 0, /* JOBEXAMFAIL */ + 0, /* JOBINTRRQST */ + 0, /* ERRWZINTR */ + 0, /* CLIERR */ + 0, /* REPLNOBEFORE */ + 0, /* REPLJNLCNFLCT */ + 0, /* JNLDISABLE */ + 0, /* FILEEXISTS */ + 0, /* JNLSTATE */ + 0, /* REPLSTATE */ + 0, /* JNLCREATE */ + 0, /* JNLNOCREATE */ + 0, /* JNLFNF */ + 0, /* PREVJNLLINKCUT */ + 0, /* PREVJNLLINKSET */ + 0, /* FILENAMETOOLONG */ + 0, /* REQRECOV */ + 0, /* JNLTRANS2BIG */ + 0, /* JNLSWITCHTOOSM */ + 0, /* JNLSWITCHSZCHG */ + 0, /* NOTRNDMACC */ + 0, /* TMPFILENOCRE */ + 0, /* SHRMEMEXHAUSTED */ + 0, /* JNLSENDOPER */ + 0, /* DDPSUBSNUL */ + 0, /* DDPNOCONNECT */ + 0, /* DDPCONGEST */ + 0, /* DDPSHUTDOWN */ + 0, /* DDPTOOMANYPROCS */ + 0, /* DDPBADRESPONSE */ + 0, /* DDPINVCKT */ + 0, /* DDPVOLSETCONFIG */ + 0, /* DDPCONFGOOD */ + 0, /* DDPCONFIGNORE */ + 0, /* DDPCONFINCOMPL */ + 0, /* DDPCONFBADVOL */ + 0, /* DDPCONFBADUCI */ + 0, /* DDPCONFBADGLD */ + 0, /* DDPRECSIZNOTNUM */ + 0, /* DDPOUTMSG2BIG */ + 0, /* DDPNOSERVER */ + 0, /* MUTEXRELEASED */ + 0, /* JNLCRESTATUS */ + 0, /* ZBREAKFAIL */ + 0, /* DLLVERSION */ + 0, /* INVZROENT */ + 0, /* DDPLOGERR */ + 0, /* GETSOCKNAMERR */ + 0, /* INVGTMEXIT */ + 0, /* CIMAXPARAM */ + 0, /* CITPNESTED */ + 0, /* CIMAXLEVELS */ + 0, /* JOBINTRRETHROW */ + 0, /* STARFILE */ + 0, /* NOSTARFILE */ + 0, /* MUJNLSTAT */ + 0, /* JNLTPNEST */ + 0, /* REPLOFFJNLON */ + 0, /* FILEDELFAIL */ + 0, /* INVQUALTIME */ + 0, /* NOTPOSITIVE */ + 0, /* INVREDIRQUAL */ + 0, /* INVERRORLIM */ + 0, /* INVIDQUAL */ + 0, /* INVTRNSQUAL */ + 0, /* JNLNOBIJBACK */ + 0, /* SETREG2RESYNC */ + 0, /* JNLALIGNTOOSM */ + 0, /* JNLFILEOPNERR */ + 0, /* JNLFILECLOSERR */ + 0, /* REPLSTATEOFF */ + 0, /* MUJNLPREVGEN */ + 0, /* MUPJNLINTERRUPT */ + 0, /* ROLLBKINTERRUPT */ + 0, /* RLBKJNSEQ */ + 0, /* REPLRECFMT */ + 0, /* PRIMARYNOTROOT */ + 0, /* DBFRZRESETFL */ + 0, /* JNLCYCLE */ + 0, /* JNLPREVRECOV */ + 0, /* RESOLVESEQNO */ + 0, /* BOVTNGTEOVTN */ + 0, /* BOVTMGTEOVTM */ + 0, /* BEGSEQGTENDSEQ */ + 0, /* DBADDRALIGN */ + 0, /* DBWCVERIFYSTART */ + 0, /* DBWCVERIFYEND */ + 0, /* MUPIPSIG */ + 0, /* HTSHRINKFAIL */ + 0, /* STPEXPFAIL */ + 0, /* DBBTUWRNG */ + 0, /* DBBTUFIXED */ + 0, /* DBMAXREC2BIG */ + 0, /* DBCSCNNOTCMPLT */ + 0, /* DBCBADFILE */ + 0, /* DBCNOEXTND */ + 0, /* DBCINTEGERR */ + 0, /* DBMINRESBYTES */ + 0, /* DBCNOTSAMEDB */ + 0, /* DBCDBCERTIFIED */ + 0, /* DBCMODBLK2BIG */ + 0, /* DBCREC2BIG */ + 0, /* DBCCMDFAIL */ + 0, /* DBCKILLIP */ + 0, /* DBCNOFINISH */ + 0, /* DYNUPGRDFAIL */ + 0, /* MMNODYNDWNGRD */ + 0, /* MMNODYNUPGRD */ + 0, /* MUDWNGRDNRDY */ + 0, /* MUDWNGRDTN */ + 0, /* MUDWNGRDNOTPOS */ + 0, /* MUUPGRDNRDY */ + 0, /* TNWARN */ + 0, /* TNTOOLARGE */ + 0, /* SHMPLRECOV */ + 0, /* MUNOSTRMBKUP */ + 0, /* EPOCHTNHI */ + 0, /* CHNGTPRSLVTM */ + 0, /* JNLUNXPCTERR */ + 0, /* OMISERVHANG */ + 0, /* RSVDBYTE2HIGH */ + 0, /* BKUPTMPFILOPEN */ + 0, /* BKUPTMPFILWRITE */ + 0, /* VMSMEMORY2 */ + 0, /* LOADBGSZ2 */ + 0, /* LOADEDSZ2 */ + 0, /* REPLINSTMISMTCH */ + 0, /* REPLINSTREAD */ + 0, /* REPLINSTDBMATCH */ + 0, /* REPLINSTNMSAME */ + 0, /* REPLINSTNMUNDEF */ + 0, /* REPLINSTNMLEN */ + 0, /* REPLINSTNOHIST */ + 0, /* REPLINSTSECLEN */ + 0, /* REPLINSTSECMTCH */ + 0, /* REPLINSTSECNONE */ + 0, /* REPLINSTSECUNDF */ + 0, /* REPLINSTSEQORD */ + 0, /* REPLINSTSTNDALN */ + 0, /* REPLREQROLLBACK */ + 0, /* REQROLLBACK */ + 0, /* UNUSEDMSG1256 */ + 0, /* SRCSRVEXISTS */ + 0, /* SRCSRVNOTEXIST */ + 0, /* SRCSRVTOOMANY */ + 0, /* JNLPOOLBADSLOT */ + 0, /* NOENDIANCVT */ + 0, /* ENDIANCVT */ + 0, /* DBENDIAN */ + 0, /* BADCHSET */ + 0, /* BADCASECODE */ + 0, /* BADCHAR */ + 0, /* DLRCILLEGAL */ + 0, /* NONUTF8LOCALE */ + 0, /* INVDLRCVAL */ + 0, /* DBMISALIGN */ + 0, /* LOADINVCHSET */ + 0, /* DLLCHSETM */ + 0, /* DLLCHSETUTF8 */ + 0, /* BOMMISMATCH */ + 0, /* WIDTHTOOSMALL */ + 80, /* SOCKMAX */ + 0, /* PADCHARINVALID */ + 0, /* ZCNOPREALLOUTPAR */ + 0, /* SVNEXPECTED */ + 0, /* SVNONEW */ + 0, /* ZINTDIRECT */ + 0, /* ZINTRECURSEIO */ + 0, /* MRTMAXEXCEEDED */ + 0, /* JNLCLOSED */ + 0, /* RLBKNOBIMG */ + 0, /* RLBKJNLNOBIMG */ + 0, /* RLBKLOSTTNONLY */ + 0, /* KILLBYSIGSINFO3 */ + 0, /* GTMSECSHRTMPPATH */ + 0, /* GTMERREXIT */ + 0, /* INVMEMRESRV */ + 0, /* OPCOMMISSED */ + 0, /* COMMITWAITSTUCK */ + 0, /* COMMITWAITPID */ + 0, /* UPDREPLSTATEOFF */ + 0, /* LITNONGRAPH */ + 0, /* DBFHEADERR8 */ + 0, /* MMBEFOREJNL */ + 0, /* MMNOBFORRPL */ + 0, /* KILLABANDONED */ + 0, /* BACKUPKILLIP */ + 0, /* LOGTOOLONG */ + 0, /* NOALIASLIST */ + 0, /* ALIASEXPECTED */ + 0, /* VIEWLVN */ + 0, /* DZWRNOPAREN */ + 0, /* DZWRNOALIAS */ + 0, /* FREEZEERR */ + 0, /* CLOSEFAIL */ + 0, /* CRYPTINIT */ + 0, /* CRYPTOPFAILED */ + 0, /* CRYPTDLNOOPEN */ + 0, /* CRYPTNOV4 */ + 0, /* CRYPTNOMM */ + 0, /* CRYPTJNLWRONGHASH */ + 0, /* CRYPTKEYFETCHFAILED */ + 0, /* CRYPTKEYFETCHFAILEDNF */ + 0, /* CRYPTHASHGENFAILED */ + 0, /* CRYPTNOPSWDINTP */ + 0, /* BADTAG */ + 0, /* ICUVERLT36 */ + 0, /* ICUSYMNOTFOUND */ + 0, /* STUCKACT */ + 0, /* CALLINAFTERXIT */ + 0, /* LOCKSPACEFULL */ + 0, /* IOERROR */ + 0, /* MAXSSREACHED */ + 0, /* SNAPSHOTNOV4 */ + 0, /* SSV4NOALLOW */ + 0, /* SSTMPDIRSTAT */ + 0, /* SSTMPCREATE */ + 0, /* JNLFILEDUP */ + 0, /* SSPREMATEOF */ + 0, /* SSFILOPERR */ + 0, /* REGSSFAIL */ + 0, /* SSSHMCLNUPFAIL */ + 0, /* SSFILCLNUPFAIL */ + 0, /* SETINTRIGONLY */ + 0, /* MAXTRIGNEST */ + 0, /* TRIGCOMPFAIL */ + 0, /* NOZTRAPINTRIG */ + 0, /* ZTWORMHOLE2BIG */ + 0, /* JNLENDIANLITTLE */ + 0, /* JNLENDIANBIG */ + 0, /* TRIGINVCHSET */ + 0, /* TRIGREPLSTATE */ + 0, /* GVDATAGETFAIL */ + 0, /* TRIG2NOTRIG */ + 0, /* ZGOTOINVLVL */ + 0, /* TRIGTCOMMIT */ + 0, /* TRIGTLVLCHNG */ + 0, /* TRIGNAMEUNIQ */ + 0, /* ZTRIGINVACT */ + 0, /* INDRCOMPFAIL */ + 0, /* QUITALSINV */ + 0, /* PROCTERM */ + 0, /* SRCLNNTDSP */ + 0, /* ARROWNTDSP */ + 0, /* TRIGDEFBAD */ + 0, /* TRIGSUBSCRANGE */ + 0, /* TRIGDATAIGNORE */ + 0, /* TRIGIS */ + 0, /* TCOMMITDISALLOW */ + 0, /* SSATTACHSHM */ + 0, /* TRIGDEFNOSYNC */ + 0, /* TRESTMAX */ + 0, /* UNUSEDMSG1367 */ + 0, /* GBLEXPECTED */ + 0, /* GVZTRIGFAIL */ + 0, /* MUUSERLBK */ + 0, /* SETINSETTRIGONLY */ + 0, /* DZTRIGINTRIG */ + 0, /* SECNODZTRIGINTP */ + 0, /* BOOLSIDEFFECT */ + 0, /* DBBADUPGRDSTATE */ + 0, /* WRITEWAITPID */ + 0, /* ZGOCALLOUTIN */ + 0, /* REPLNOXENDIAN */ + 0, /* REPLXENDIANFAIL */ + 0, /* ZGOTOINVLVL2 */ + 0, /* GTMSECSHRCHDIRF */ + 0, /* JNLORDBFLU */ + 0, /* ZCCLNUPRTNMISNG */ + 0, /* ZCINVALIDKEYWORD */ + 0, /* REPLNOMULTILINETRG */ + 0, /* DBSHMNAMEDIFF */ + 0, /* SHMREMOVED */ + 0, /* DEVICEWRITEONLY */ + 0, /* ICUERROR */ + 0, /* ZDATEBADDATE */ + 0, /* ZDATEBADTIME */ + 0, /* COREINPROGRESS */ + 0, /* MAXSEMGETRETRY */ + 0, /* JNLNOREPL */ + 0, /* JNLRECINCMPL */ + 0, /* JNLALLOCGROW */ + 0, /* INVTRCGRP */ + 0, /* MUINFOUINT6 */ + 0, /* NOLOCKMATCH */ + 0, /* BADREGION */ + 0, /* LOCKSPACEUSE */ + 0, /* JIUNHNDINT */ + 0, /* GTMASSERT2 */ + 0, /* ZTRIGNOTRW */ + 0, /* TRIGMODREGNOTRW */ + 0, /* INSNOTJOINED */ + 0, /* INSROLECHANGE */ + 0, /* INSUNKNOWN */ + 0, /* NORESYNCSUPPLONLY */ + 0, /* NORESYNCUPDATERONLY */ + 0, /* NOSUPPLSUPPL */ + 0, /* REPL2OLD */ + 0, /* EXTRFILEXISTS */ + 0, /* MUUSERECOV */ + 0, /* SECNOTSUPPLEMENTARY */ + 0, /* SUPRCVRNEEDSSUPSRC */ + 0, /* UNUSEDMSG1417 */ + 0, /* UNUSEDMSG1418 */ + 0, /* UPDSYNC2MTINS */ + 0, /* UPDSYNCINSTFILE */ + 0, /* REUSEINSTNAME */ + 0, /* RCVRMANYSTRMS */ + 0, /* RSYNCSTRMVAL */ + 0, /* RLBKSTRMSEQ */ + 0, /* RESOLVESEQSTRM */ + 0, /* REPLINSTDBSTRM */ + 0, /* RESUMESTRMNUM */ + 0, /* ORLBKSTART */ + 0, /* ORLBKTERMNTD */ + 0, /* ORLBKCMPLT */ + 0, /* ORLBKNOSTP */ + 0, /* ORLBKFRZPROG */ + 0, /* ORLBKFRZOVER */ + 0, /* ORLBKNOV4BLK */ + 0, /* DBROLLEDBACK */ + 0, /* DSEWCREINIT */ + 0, /* MURNDWNOVRD */ + 0, /* REPLONLNRLBK */ + 0, /* SRVLCKWT2LNG */ + 0, /* IGNBMPMRKFREE */ + 0, /* PERMGENFAIL */ + 0, /* PERMGENDIAG */ + 0, /* MUTRUNC1ATIME */ + 0, /* MUTRUNCBACKINPROG */ + 0, /* MUTRUNCERROR */ + 0, /* MUTRUNCFAIL */ + 0, /* MUTRUNCNOSPACE */ + 0, /* MUTRUNCNOTBG */ + 0, /* MUTRUNCNOV4 */ + 0, /* MUTRUNCPERCENT */ + 0, /* MUTRUNCSSINPROG */ + 0, /* MUTRUNCSUCCESS */ + 0, /* RSYNCSTRMSUPPLONLY */ + 0, /* STRMNUMIS */ + 0, /* STRMNUMMISMTCH1 */ + 0, /* STRMNUMMISMTCH2 */ + 0, /* STRMSEQMISMTCH */ + 0, /* LOCKSPACEINFO */ + 0, /* JRTNULLFAIL */ + 0, /* LOCKSUB2LONG */ + 0, /* RESRCWAIT */ + 0, /* RESRCINTRLCKBYPAS */ + 0, /* DBFHEADERRANY */ + 0, /* REPLINSTFROZEN */ + 0, /* REPLINSTFREEZECOMMENT */ + 0, /* REPLINSTUNFROZEN */ + 0, /* DSKNOSPCAVAIL */ + 0, /* DSKNOSPCBLOCKED */ + 0, /* DSKSPCAVAILABLE */ + 0, /* ENOSPCQIODEFER */ + 0, /* CUSTOMFILOPERR */ + 0, /* CUSTERRNOTFND */ + 0, /* CUSTERRSYNTAX */ + 0, /* ORLBKINPROG */ + 0, /* DBSPANGLOINCMP */ + 0, /* DBSPANCHUNKORD */ + 0, /* DBDATAMX */ + 0, /* DBIOERR */ + 0, /* INITORRESUME */ + 0, /* GTMSECSHRNOARG0 */ + 0, /* GTMSECSHRISNOT */ + 0, /* GTMSECSHRBADDIR */ + 0, /* JNLBUFFREGUPD */ + 0, /* JNLBUFFDBUPD */ + 0, /* LOCKINCR2HIGH */ + 0, /* LOCKIS */ + 0, /* LDSPANGLOINCMP */ + 0, /* MUFILRNDWNFL2 */ + 0, /* MUINSTFROZEN */ + 0, /* MUINSTUNFROZEN */ + 0, /* GTMEISDIR */ + 0, /* SPCLZMSG */ + 0, /* MUNOTALLINTEG */ + 0, /* BKUPRUNNING */ + 0, /* MUSIZEINVARG */ + 0, /* MUSIZEFAIL */ + 0, /* SIDEEFFECTEVAL */ + 0, /* CRYPTINIT2 */ + 0, /* CRYPTDLNOOPEN2 */ + 0, /* CRYPTBADCONFIG */ + 0, /* DBCOLLREQ */ + 0, /* SETEXTRENV */ + 0, /* NOTALLDBRNDWN */ + 0, /* TPRESTNESTERR */ + 0, /* JNLFILRDOPN */ + 0, /* SEQNUMSEARCHTIMEOUT */ + 0, /* FTOKKEY */ + 0, /* SEMID */ + 0, /* JNLQIOSALVAGE */ + 0, /* FAKENOSPCLEARED */ + 0, /* MMFILETOOLARGE */ + 0, /* BADZPEEKARG */ + 0, /* BADZPEEKRANGE */ + 0, /* BADZPEEKFMT */ + 0, /* DBMBMINCFREFIXED */ + 0, /* NULLENTRYREF */ + 0, /* ZPEEKNORPLINFO */ + 0, /* MMREGNOACCESS */ + 0, /* MALLOCMAXUNIX */ + 0, /* MALLOCMAXVMS */ + 0, /* HOSTCONFLICT */ + 0, /* GETADDRINFO */ + 0, /* GETNAMEINFO */ + 0, /* SOCKBIND */ + 0, /* INSTFRZDEFER */ + 0, /* REGOPENRETRY */ + 0, /* REGOPENFAIL */ + }; diff --git a/sr_x86_64/opp_indsavglvn.s b/sr_x86_64/opp_indsavglvn.s new file mode 100644 index 0000000..48fc0cf --- /dev/null +++ b/sr_x86_64/opp_indsavglvn.s @@ -0,0 +1,38 @@ +################################################################# +# # +# Copyright 2012 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +# PAGE ,132 + .title opp_indsavglvn.s + +# .386 +# .MODEL FLAT, C + +.include "linkage.si" + .INCLUDE "g_msf.si" + + .sbttl opp_indsavglvn +# PAGE + + .DATA +.extern frame_pointer # /* :DWORD */ + + .text +.extern op_indsavglvn + +# PUBLIC opp_indsavglvn +ENTRY opp_indsavglvn # /* PROC */ + putframe + addq $8,REG_SP # burn return PC + call op_indsavglvn + getframe + ret +# opp_indsavglvn ENDP + +# END diff --git a/sr_x86_64/opp_indsavlvn.s b/sr_x86_64/opp_indsavlvn.s new file mode 100644 index 0000000..2259eb2 --- /dev/null +++ b/sr_x86_64/opp_indsavlvn.s @@ -0,0 +1,38 @@ +################################################################# +# # +# Copyright 2012 Fidelity Information Services, Inc # +# # +# This source code contains the intellectual property # +# of its copyright holder(s), and is made available # +# under a license. If you do not know the terms of # +# the license, please stop and do not read further. # +# # +################################################################# + +# PAGE ,132 + .title opp_indsavlvn.s + +# .386 +# .MODEL FLAT, C + +.include "linkage.si" + .INCLUDE "g_msf.si" + + .sbttl opp_indsavlvn +# PAGE + + .DATA +.extern frame_pointer # /* :DWORD */ + + .text +.extern op_indsavlvn + +# PUBLIC opp_indsavlvn +ENTRY opp_indsavlvn # /* PROC */ + putframe + addq $8,REG_SP # burn return PC + call op_indsavlvn + getframe + ret +# opp_indsavlvn ENDP + +# END