1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/src/cmd/ksh93/include/variables.h
Johnothan King 396b388e1f Fix a few issues with $RANDOM seeding in subshells (#339)
This commit fixes an issue I found in the subshell $RANDOM
reseeding code.

The main issue is a performance regression in the shbench fibonacci
benchmark, introduced in commit af6a32d1. Performance dropped in
this benchmark because $RANDOM is always reseeded and restored,
even when it's never used in a subshell. Performance results from
before and after this performance fix (results are on Linux with
CC=gcc and CCFLAGS='-O2 -D_std_malloc'):

  $ ./shbench -b bench/fibonacci.ksh -l 100 ./ksh-0f06a2e ./ksh-af6a32d ./ksh-f31e368 ./ksh-randfix

  benchmarking ./ksh-0f06a2e, ./ksh-af6a32d, ./ksh-f31e368, ./ksh-randfix ...
  *** fibonacci.ksh ***
  # ./ksh-0f06a2e  # Recent version of ksh93u+m
  # ./ksh-af6a32d  # Commit that introduced the regression
  # ./ksh-f31e368  # Commit without the regression
  # ./ksh-randfix  # Ksh93u+m with this patch applied

  -------------------------------------------------------------------------------------------------
  name           ./ksh-0f06a2e        ./ksh-af6a32d        ./ksh-f31e368        ./ksh-randfix
  -------------------------------------------------------------------------------------------------
  fibonacci.ksh  0.481 [0.459-0.515]  0.472 [0.455-0.504]  0.396 [0.380-0.442]  0.407 [0.385-0.439]
  -------------------------------------------------------------------------------------------------

src/cmd/ksh93/include/variables.h,
src/cmd/ksh93/sh/{init,subshell}.c:
- Rather than reseed $RANDOM every time a subshell is created, add
  a sh_save_rand_seed() function that does this only when the
  $RANDOM variable is used in a subshell. This function is called
  by the $RANDOM discipline functions nget_rand() and put_rand().
  As a minor optimization, sh_save_rand_seed doesn't reseed if it's
  called from put_rand().
- Because $RANDOM may have a seed of zero (i.e., RANDOM=0),
  sp->rand_seed isn't enough to tell if $RANDOM has been reseeded.
  Add sp->rand_state for this purpose.
- sh_subshell(): Only restore the former $RANDOM seed and state if
  it is necessary to prevent a subshell leak.

src/cmd/ksh93/tests/variables.sh:
- Add two regression tests for bugs I ran into while making this
  patch.
2021-11-19 08:18:44 +01:00

110 lines
4.6 KiB
C

/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1982-2011 AT&T Intellectual Property *
* Copyright (c) 2020-2021 Contributors to ksh 93u+m *
* and is licensed under the *
* Eclipse Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* http://www.eclipse.org/org/documents/epl-v10.html *
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* David Korn <dgk@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
#ifndef SH_VALNOD
#include <option.h>
#include "FEATURE/options"
#include "FEATURE/dynamic"
#include <nval.h>
/* used for RANDNOD ($RANDOM) */
struct rand
{
Namfun_t hdr;
unsigned int rand_seed;
int32_t rand_last;
};
extern void sh_reseed_rand(struct rand *);
extern void sh_save_rand_seed(struct rand *, int);
/* The following defines must be kept synchronous with shtab_variables[] in data/variables.c */
#define PATHNOD (shgd->bltin_nodes)
#define PS1NOD (shgd->bltin_nodes+1)
#define PS2NOD (shgd->bltin_nodes+2)
#define IFSNOD (shgd->bltin_nodes+3)
#define PWDNOD (shgd->bltin_nodes+4)
#define HOME (shgd->bltin_nodes+5)
#define MAILNOD (shgd->bltin_nodes+6)
#define REPLYNOD (shgd->bltin_nodes+7)
#define SHELLNOD (shgd->bltin_nodes+8)
#define EDITNOD (shgd->bltin_nodes+9)
#define MCHKNOD (shgd->bltin_nodes+10)
#define RANDNOD (shgd->bltin_nodes+11)
#define ENVNOD (shgd->bltin_nodes+12)
#define HISTFILE (shgd->bltin_nodes+13)
#define HISTSIZE (shgd->bltin_nodes+14)
#define HISTEDIT (shgd->bltin_nodes+15)
#define HISTCUR (shgd->bltin_nodes+16)
#define FCEDNOD (shgd->bltin_nodes+17)
#define CDPNOD (shgd->bltin_nodes+18)
#define MAILPNOD (shgd->bltin_nodes+19)
#define PS3NOD (shgd->bltin_nodes+20)
#define OLDPWDNOD (shgd->bltin_nodes+21)
#define VISINOD (shgd->bltin_nodes+22)
#define COLUMNS (shgd->bltin_nodes+23)
#define LINES (shgd->bltin_nodes+24)
#define PPIDNOD (shgd->bltin_nodes+25)
#define L_ARGNOD (shgd->bltin_nodes+26)
#define TMOUTNOD (shgd->bltin_nodes+27)
#define SECONDS (shgd->bltin_nodes+28)
#define LINENO (shgd->bltin_nodes+29)
#define OPTARGNOD (shgd->bltin_nodes+30)
#define OPTINDNOD (shgd->bltin_nodes+31)
#define PS4NOD (shgd->bltin_nodes+32)
#define FPATHNOD (shgd->bltin_nodes+33)
#define LANGNOD (shgd->bltin_nodes+34)
#define LCALLNOD (shgd->bltin_nodes+35)
#define LCCOLLNOD (shgd->bltin_nodes+36)
#define LCTYPENOD (shgd->bltin_nodes+37)
#define LCMSGNOD (shgd->bltin_nodes+38)
#define LCNUMNOD (shgd->bltin_nodes+39)
#define LCTIMENOD (shgd->bltin_nodes+40)
#define FIGNORENOD (shgd->bltin_nodes+41)
#define VERSIONNOD (shgd->bltin_nodes+42)
#define JOBMAXNOD (shgd->bltin_nodes+43)
#define DOTSHNOD (shgd->bltin_nodes+44)
#define ED_CHRNOD (shgd->bltin_nodes+45)
#define ED_COLNOD (shgd->bltin_nodes+46)
#define ED_TXTNOD (shgd->bltin_nodes+47)
#define ED_MODENOD (shgd->bltin_nodes+48)
#define SH_NAMENOD (shgd->bltin_nodes+49)
#define SH_SUBSCRNOD (shgd->bltin_nodes+50)
#define SH_VALNOD (shgd->bltin_nodes+51)
#define SH_VERSIONNOD (shgd->bltin_nodes+52)
#define SH_DOLLARNOD (shgd->bltin_nodes+53)
#define SH_MATCHNOD (shgd->bltin_nodes+54)
#define SH_COMMANDNOD (shgd->bltin_nodes+55)
#define SH_PATHNAMENOD (shgd->bltin_nodes+56)
#define SH_FUNNAMENOD (shgd->bltin_nodes+57)
#define SH_SUBSHELLNOD (shgd->bltin_nodes+58)
#define SH_LEVELNOD (shgd->bltin_nodes+59)
#define SH_LINENO (shgd->bltin_nodes+60)
#define SH_STATS (shgd->bltin_nodes+61)
#define SH_MATHNOD (shgd->bltin_nodes+62)
#define SH_JOBPOOL (shgd->bltin_nodes+63)
#define SH_PIDNOD (shgd->bltin_nodes+64)
#define SH_TILDENOD (shgd->bltin_nodes+65)
#define SHLVL (shgd->bltin_nodes+66)
#endif /* SH_VALNOD */