Changeset 479
- Timestamp:
- 08/16/06 01:46:08 (2 years ago)
- Files:
-
- 1.7.7/CHANGES.177 (modified) (1 diff)
- 1.7.7/Configure (modified) (1 diff)
- 1.7.7/MANIFEST (modified) (1 diff)
- 1.7.7/Makefile.SH (modified) (2 diffs)
- 1.7.7/Patchlevel (modified) (1 diff)
- 1.7.7/config_h.SH (modified) (1 diff)
- 1.7.7/confmagic.h (modified) (1 diff)
- 1.7.7/game/alias.cnf (deleted)
- 1.7.7/game/data/minimal.db (deleted)
- 1.7.7/game/mushcnf.dst (modified) (1 diff)
- 1.7.7/game/names.cnf (deleted)
- 1.7.7/game/restrict.cnf (deleted)
- 1.7.7/game/txt/hlp/penncmd.hlp (modified) (2 diffs)
- 1.7.7/game/txt/hlp/pennfunc.hlp (modified) (2 diffs)
- 1.7.7/game/txt/hlp/penntop.hlp (modified) (1 diff)
- 1.7.7/game/txt/hlp/pennv177.hlp (modified) (2 diffs)
- 1.7.7/game/txt/hlp/pennvOLD.hlp (modified) (1 diff)
- 1.7.7/hdrs/command.h (modified) (1 diff)
- 1.7.7/hdrs/memcheck.h (deleted)
- 1.7.7/hdrs/oldattrb.h (deleted)
- 1.7.7/hdrs/version.h (modified) (1 diff)
- 1.7.7/hdrs/warnings.h (deleted)
- 1.7.7/hints/linux_2.sh (modified) (1 diff)
- 1.7.7/src/Makefile (deleted)
- 1.7.7/src/announce.c (deleted)
- 1.7.7/src/attrib.c (modified) (4 diffs)
- 1.7.7/src/bsd.c (modified) (1 diff)
- 1.7.7/src/chunk.c (modified) (35 diffs)
- 1.7.7/src/command.c (modified) (4 diffs)
- 1.7.7/src/conf.c (modified) (1 diff)
- 1.7.7/src/convdb.c (deleted)
- 1.7.7/src/csrimalloc.c (modified) (3 diffs)
- 1.7.7/src/extmail.c (modified) (1 diff)
- 1.7.7/src/flags.c (modified) (2 diffs)
- 1.7.7/src/function.c (modified) (1 diff)
- 1.7.7/src/funstr.c (modified) (1 diff)
- 1.7.7/src/game.c (modified) (4 diffs)
- 1.7.7/src/lock.c (modified) (1 diff)
- 1.7.7/src/switchinc.c (modified) (1 diff)
- 1.7.7/utils/mkcmds.sh (deleted)
- 1.7.7/utils/penn-install (deleted)
- 1.7.7/win32/cmds.h (modified) (1 diff)
- 1.7.7/win32/config.h (modified) (1 diff)
- 1.7.7/win32/funs.h (modified) (2 diffs)
- 1.7.7/win32/msvc.net (added)
- 1.7.7/win32/msvc.net/pennmush.sln (moved) (moved from 1.7.7/win32/pennmush.sln)
- 1.7.7/win32/msvc.net/pennmush.vcproj (moved) (moved from 1.7.7/win32/pennmush.vcproj)
- 1.7.7/win32/msvc6 (added)
- 1.7.7/win32/msvc6/pennmush.dsp (moved) (moved from 1.7.7/win32/pennmush.dsp)
- 1.7.7/win32/msvc6/pennmush.dsw (moved) (moved from 1.7.7/win32/pennmush.dsw)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
1.7.7/CHANGES.177
r477 r479 18 18 19 19 ========================================================================== 20 21 Version 1.7.7 patchlevel 40 December 1, 2004 22 23 Major Changes: 24 * Another pass at the chunk allocator! Simpler but effective. 25 Folks should, however, greatly reduce their chunk_migrate 26 value in mush.cnf -- we suggest '50'. [TAP] 27 Commands: 28 * @command/alias can alias commands. Patch by Walker@M*U*S*H. 29 Functions: 30 * zwho() and zmwho(). [EEH] 31 Minor Changes: 32 * utils/penn-install is no longer part of the PennMUSH distribution 33 (it's part of the Debian maintainer's stuff). [EEH] 34 * Inheritable @locks are inherited off of ancestor objects. 35 Suggested by Zith@Lovarii. [SW] 36 Fixes: 37 * Infinite recursion in @lock/examine fixed. Report by 38 Amy Kou'ai (Amy@ShoujoAi) and Sparta Kerleon (Sparta@ShoujoAi). [TAP] 39 * @flag/letter now allows setting a flag's letter to one used by 40 another flag that works on different object types. Report by Lenon. 41 * Translation corrections by Cheetah@M*U*S*H and [EEH]. 42 * Added __USE_POSIX to the cflags for linux, and removed 43 checking for -lbind, to help SuSE 9. Report by Ambrosia@M*U*S*H. 44 * Fixes to panic db loading logic. [SW] 45 * escape() shouldn't double-escape the first character of the 46 string when it's a special character. Report by Walker@M*U*S*H. 47 20 48 21 49 Version 1.7.7 patchlevel 39 October 25, 2004 1.7.7/Configure
r467 r479 19 19 # 20 20 21 # $Id: Head.U 1.1 Thu, 20 Jul 2000 17:42:54-0500 dunemush $21 # $Id: Configure 1.21.1.4.1.1.1.1.1.1.1.7.1.14 Mon, 28 Jun 2004 09:33:37 -0500 dunemush $ 22 22 # 23 # Generated on Mon May 24 11:39:50CDT 2004 [metaconfig 3.0 PL70]23 # Generated on Mon Jun 28 09:20:55 CDT 2004 [metaconfig 3.0 PL70] 24 24 25 25 cat >/tmp/c1$$ <<EOF 1.7.7/MANIFEST
r477 r479 164 164 utils/mkcmds.sh.SH 165 165 utils/mkvershlp.pl 166 utils/penn-install167 166 utils/update-cnf.pl 168 167 utils/update.pl 1.7.7/Makefile.SH
r467 r479 67 67 GLOBAL_INSTALL=/usr/libexec/pennmush 68 68 69 # Where to install with 'make debianinstall'70 DEB_INSTALL=$(DESTDIR)/usr/lib/pennmush/game71 DEB_BIN=$(DESTDIR)/usr/games72 73 69 all: config.h options.h autogen game/mush.cnf 74 70 @echo "Making all in src." … … 299 295 @echo "** or symlink that to somewhere easier to run. You may wish to strip them." 300 296 301 debianinstall: install302 (cd game/txt; make clean compose.sh)303 $(INSTALLDIR) $(DEB_INSTALL)304 $(INSTALLDIR) $(DEB_BIN)305 $(CP) -R game/* $(DEB_INSTALL)306 -rm -f $(DEB_INSTALL)/netmush $(DEB_INSTALL)/info_slave307 $(INSTALL) config.sh $(DEB_INSTALL)/config.sh308 $(INSTALL) src/netmud $(DEB_INSTALL)/netmush309 $(INSTALL) src/info_slave $(DEB_INSTALL)/info_slave310 $(INSTALL) utils/penn-install $(DEB_BIN)/penn-install311 $(CHMOD) a+rX -R $(DEB_INSTALL)312 $(CHMOD) a+rX $(DEB_BIN)/penn-install313 @echo "** Files installed in $(DEB_INSTALL)."314 @echo "** You can run penn-install to create a user directory."315 316 297 !NO!SUBS! 317 298 chmod 644 Makefile 1.7.7/Patchlevel
r477 r479 1 1 Do not edit this file. It is maintained by the official PennMUSH patches. 2 This is PennMUSH 1.7.7p 392 This is PennMUSH 1.7.7p40 1.7.7/config_h.SH
r463 r479 26 26 * For a more permanent change edit config.sh and rerun config_h.SH. 27 27 * 28 * \$Id: Config_h.U,v 3.0.1.5 1997/02/28 14:57:43 ram Exp$28 * \$Id: config_h.SH 1.17.1.2.1.1.1.11 Mon, 24 May 2004 14:14:15 -0500 dunemush $ 29 29 */ 30 30 1.7.7/confmagic.h
r337 r479 7 7 * without the -M option. 8 8 * 9 * $Id: Magic_h.U,v 3.0.1.2 1993/11/10 17:32:58 ram Exp$9 * $Id: confmagic.h 1.9 Fri, 15 Feb 2002 16:56:28 -0600 dunemush $ 10 10 */ 11 11 1.7.7/game/mushcnf.dst
r477 r479 153 153 # second. The higher the value, the faster memory gets defragmented, 154 154 # but at a greater CPU cost. 155 chunk_migrate 50 0155 chunk_migrate 50 156 156 157 157 ### 1.7.7/game/txt/hlp/penncmd.hlp
r477 r479 571 571 @command <command> 572 572 @command/<switch> <command> 573 @command/alias <command>=<new command name> 573 574 574 575 @command provides information about and controls the availability … … 583 584 /enable : Enable the <command> 584 585 /on : Synonym for /enable 586 /alias : Creates an alias for a command. 585 587 /quiet : Don't make noisy output when doing one of the above 586 588 /add : Creates a useless command. @hook/override it. 587 /delete : Deletes a command added by @command/add 589 /delete : Deletes a command added by @command/add, or aliases. 588 590 589 591 See HELP RESTRICT for more. 1.7.7/game/txt/hlp/pennfunc.hlp
r477 r479 114 114 cmds() conn() doing() height() hostname() 115 115 hidden() idle() ipaddr() lports() lwho() 116 mwho() ports() pueblo() recv() sent() 117 ssl() terminfo() width() 116 mwho() nmwho() nwho() ports() pueblo() 117 recv() sent() ssl() terminfo() width() 118 xmwho() xwho() zmwho() zwho() 118 119 & Dbref functions 119 120 Dbref functions return a dbref or list of dbrefs related to some value … … 4532 4533 4533 4534 See also: lwho(), mwho(), nwho() 4535 4536 & ZMWHO() 4537 zmwho(<object>) 4538 4539 This returns a list of the dbref numbers for all current-connected, 4540 non-hidden players within a location belonging to the specified zone. 4541 It's exactly the same as zwho() used by a mortal, and is suitable for 4542 use on privileged global objects who need an unprivileged zwho-list. 4543 4544 See also: zwho() 4545 4546 & ZWHO() 4547 zwho(<object>[,<viewer>]) 4548 4549 This returns a list of the dbref numbers for all currently-connected 4550 players within a location belonging to the specified zone. When mortals 4551 use this function, the dbref numbers of DARK wizards or hidden royalty 4552 do NOT appear on the dbref list. 4553 4554 If <viewer> is given by a privileged user, zwho() returns a dbref list 4555 using <viewer>'s privileges. 4556 4557 See also: zmwho() 4534 4558 & ZEMIT() 4535 4559 & NSZEMIT() 1.7.7/game/txt/hlp/penntop.hlp
r477 r479 392 392 UNIX Tinyfugue tf.tcp.com 393 393 /pub/tinyfugue 394 WINDOWS 32-bit MUSHClient ftp.pennmush.org 395 /pub/PennMUSH/Win32Binaries 394 WINDOWS 32-bit MUSHClient http://www.mushclient.com 396 395 SimpleMU http://simplemu.onlineroleplay.com 396 MuckClient http://www.xcalibur.co.uk/MuckClient/ 397 397 MACINTOSH MUDDweller http://www.shareware.com (search for Muddweller) 398 398 1.7.7/game/txt/hlp/pennv177.hlp
r477 r479 1 & 1.7.7p 391 & 1.7.7p40 2 2 & changes 3 3 This is a list of changes in this patchlevel which are probably of … … 12 12 be read in 'help patchlevels'. 13 13 14 Version 1.7.7 patchlevel 40 December 1, 2004 15 16 Major Changes: 17 * Another pass at the chunk allocator! Simpler but effective. 18 Folks should, however, greatly reduce their chunk_migrate 19 value in mush.cnf -- we suggest '50'. [TAP] 20 Commands: 21 * @command/alias can alias commands. Patch by Walker@M*U*S*H. 22 Functions: 23 * zwho() and zmwho(). [EEH] 24 Minor Changes: 25 * utils/penn-install is no longer part of the PennMUSH distribution 26 (it's part of the Debian maintainer's stuff). [EEH] 27 * Inheritable @locks are inherited off of ancestor objects. 28 Suggested by Zith@Lovarii. [SW] 29 Fixes: 30 * Infinite recursion in @lock/examine fixed. Report by 31 Amy Kou'ai (Amy@ShoujoAi) and Sparta Kerleon (Sparta@ShoujoAi). [TAP] 32 * @flag/letter now allows setting a flag's letter to one used by 33 another flag that works on different object types. Report by Lenon. 34 * Translation corrections by Cheetah@M*U*S*H and [EEH]. 35 * Added __USE_POSIX to the cflags for linux, and removed 36 checking for -lbind, to help SuSE 9. Report by Ambrosia@M*U*S*H. 37 * Fixes to panic db loading logic. [SW] 38 * escape() shouldn't double-escape the first character of the 39 string when it's a special character. Report by Walker@M*U*S*H. 40 41 42 & 1.7.7p39 14 43 Version 1.7.7 patchlevel 39 October 25, 2004 15 44 1.7.7/game/txt/hlp/pennvOLD.hlp
r477 r479 4420 4420 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 4421 4421 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 4422 36, 37, 38, 39 4422 36, 37, 38, 39, 40 4423 4423 1.7.6: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 4424 4424 1.7.5: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 1.7.7/hdrs/command.h
r477 r479 106 106 char *arg_left, char *args_left[MAX_ARG], \ 107 107 char *arg_right, char *args_right[MAX_ARG]) 108 109 /* For things that DON'T get auto-aliased by mkalias, like 'i' for 'inv' and 'l' for 'look' */110 111 typedef struct command_alias COMALIAS;112 /** An alias to a command.113 * This structure represents a command alias, which consists of the command's114 * real (canonical) name and an alias for that name.115 */116 struct command_alias {117 const char *name; /**< Canonical command name */118 const char *alias; /**< Command alias */119 };120 108 121 109 typedef struct command_info COMMAND_INFO; 1.7.7/hdrs/version.h
r477 r479 1 1 #define VERSION "1.7.7" 2 #define PATCHLEVEL " 39"3 #define PATCHDATE "[1 0/25/2004]"4 #define NUMVERSION 0010070070 392 #define PATCHLEVEL "40" 3 #define PATCHDATE "[12/01/2004]" 4 #define NUMVERSION 001007007040 1.7.7/hints/linux_2.sh
r267 r479 1 1 nm_opt='-B' 2 ccflags='-D__USE_POSIX' 3 libswanted='nsl m c crypt intl resolv' 2 4 echo "I suggest using sysmalloc when you edit options.h." 1.7.7/src/attrib.c
r477 r479 245 245 static char name[ATTRIBUTE_NAME_LIMIT + 1]; 246 246 char *p; 247 int control; 248 int exam; 247 int cansee; 249 248 int canlook; 250 249 dbref target; … … 254 253 visible = (player == NOTHING); 255 254 if (visible) { 256 control = 0; 257 exam = (Visual(obj) && 258 eval_lock(PLAYER_START, obj, Examine_Lock) && 259 eval_lock(MASTER_ROOM, obj, Examine_Lock)); 255 cansee = (Visual(obj) && 256 eval_lock(PLAYER_START, obj, Examine_Lock) && 257 eval_lock(MASTER_ROOM, obj, Examine_Lock)); 260 258 canlook = 0; 261 259 } else { 262 c ontrol = controls(player, obj);263 exam =(Visual(obj) && eval_lock(player, obj, Examine_Lock));260 cansee = controls(player, obj) || 261 (Visual(obj) && eval_lock(player, obj, Examine_Lock)); 264 262 canlook = can_look_at(player, obj); 265 263 } … … 268 266 /* If we can't see the attribute itself, then that's easy. */ 269 267 if (AF_Internal(atr) || AF_Mdark(atr) || 270 !(c ontrol || exam||268 !(cansee || 271 269 (AF_Visual(atr) && (!AF_Nearby(atr) || canlook)) || 272 270 (!visible && !Mistrust(player) && … … 297 295 } 298 296 if (AF_Internal(atr) || AF_Mdark(atr) || 299 !(c ontrol || exam||297 !(cansee || 300 298 (AF_Visual(atr) && (!AF_Nearby(atr) || canlook)) || 301 299 (!visible && !Mistrust(player) && 1.7.7/src/bsd.c
r477 r479 4277 4277 } 4278 4278 4279 /* ZWHO() function - really belongs in eval.c but needs stuff declared here */ 4280 /* ARGSUSED */ 4281 FUNCTION(fun_zwho) 4282 { 4283 DESC *d; 4284 dbref zone, victim; 4285 int first; 4286 int powered = (strcmp(called_as, "ZMWHO") && Priv_Who(executor)); 4287 first = 1; 4288 4289 zone = match_thing(executor, args[0]); 4290 4291 if (nargs == 1) { 4292 victim = executor; 4293 } else if ((nargs == 2) && powered) { 4294 if ((victim = match_thing(executor, args[1])) == 0) { 4295 safe_str(T(e_match), buff, bp); 4296 return; 4297 } 4298 } else { 4299 safe_str(T(e_perm), buff, bp); 4300 return; 4301 } 4302 4303 if (!GoodObject(zone) || !eval_lock(victim, zone, Zone_Lock)) { 4304 safe_str(T(e_perm), buff, bp); 4305 return; 4306 } 4307 if ((getlock(zone, Zone_Lock) == TRUE_BOOLEXP) || 4308 (IsPlayer(zone) && !(has_flag_by_name(zone, "SHARED", TYPE_PLAYER)))) { 4309 safe_str(T("#-1 INVALID ZONE."), buff, bp); 4310 return; 4311 } 4312 4313 /* Use lowest privilege for victim */ 4314 if (!Priv_Who(victim)) 4315 powered = 0; 4316 4317 DESC_ITER_CONN(d) { 4318 if (!Hidden(d) || powered) { 4319 if (Zone(Location(d->player)) == zone) { 4320 if (first) { 4321 first = 0; 4322 } else { 4323 safe_chr(' ', buff, bp); 4324 } 4325 safe_dbref(d->player, buff, bp); 4326 } 4327 } 4328 } 4329 } 4330 4279 4331 /* ARGSUSED */ 4280 4332 FUNCTION(fun_doing) 1.7.7/src/chunk.c
r467 r479 15 15 * 16 16 * <h3>Basic operation:</h3> 17 * The managed memory pool is divided into approximately 64K regions.18 * Each of these regions contain variable-size chunks representing19 * a llocated and available (free) memory. No individual allocation20 * may be larger than will fit in a single region, and no allocation21 * may be smaller than two bytes. Each chunk has between two and four22 * bytes of overhead (indicating the used/free status, the size of the23 * chunk, and the number of dereferences for the chunk), and each24 * region has additional overhead of about 32 bytes.17 * The managed memory pool is divided into regions of approximately 64KB. 18 * These regions contain variable-size chunks representing allocated and 19 * available (free) memory. No individual allocation may be larger than 20 * will fit in a single region, and no allocation may be smaller than one 21 * byte. Each chunk has between two and four bytes of overhead (indicating 22 * the used/free status, the size of the chunk, and the number of 23 * dereferences for the chunk), and each region has additional overhead 24 * of about 42 bytes. 25 25 * 26 26 * Allocations are made with the chunk_create() call, which is given … … 77 77 * whole. 78 78 * 79 * There are severalthings that factor into a chunk's happiness.79 * There are two things that factor into a chunk's happiness. 80 80 * The things that make a chunk unhappy are: 81 81 * <ul> 82 * <li> Having free space both before and after the chunk in its region.83 * <li> Having only one allocated neighbor (or worse, none). The edges84 * of a region count as allocated neighbors.85 82 * <li> Having a dereference count different from the region average. 86 83 * The greater the difference, the more unhappy the chunk is. 87 * <li> Being in a sparsely populated region. The more free spacein a84 * <li> Being in a sparsely populated region. The fewer chunks in a 88 85 * region, the more unhappy the chunks in it. 89 * <li> Being away from the other chunks migrated at the same time.90 * If some of the other chunks allowed to migrate are in the same91 * region as a chunk, then it is happier. (This is specifically92 * to improve locality during dumps.)93 86 * </ul> 94 * N one of these factors are absolute; all of them have different weights95 * that add into a general unhappiness for the chunk. The lower the96 * unhappiness, the better.87 * Neither of these factors are absolute; both of them have different 88 * weights that add into a general unhappiness for the chunk. The lower 89 * the unhappiness, the better. 97 90 * 98 91 * Over time and usage, the dereference counts for chunks will increase … … 105 98 * and all chunk dereference counts are halved. The critical number of 106 99 * regions is determined based on the cache size and the total number of 107 * regions. I n general, period change should be controlled primarily by108 * the frequency of database dumps (which end up incrementing the dereference109 * count on all chunks, and thus all regions). Given a dump frequency110 * of once per hour (the default), there should be a period change about111 * every 2.6 days.100 * regions. If you're not using forking dumps, then period change should 101 * be controlled primarily by the frequency of database dumps (which end 102 * up incrementing the dereference count on all chunks, and thus all 103 * regions). Given a dump frequency of once per hour (the default), there 104 * should be a period change about every 2.6 days. 112 105 * 113 106 * … … 219 212 #include "conf.h" 220 213 214 #include <limits.h> 221 215 #include <string.h> 216 #include <stdarg.h> 222 217 #include <stdlib.h> 223 218 … … 253 248 /** Log all moves and slides during migration. */ 254 249 #undef DEBUG_CHUNK_MIGRATE 255 /** Log start, phases, and finish of migration. */256 #undef DEBUG_CHUNK_MIGRATE_LOUD257 /** Log info about trying to fill holes. */258 #undef DEBUG_CHUNK_MIGRATE_FILL259 250 /** Log creation of regions. */ 260 251 #undef DEBUG_CHUNK_REGION_CREATE … … 263 254 /** Log all mallocs. */ 264 255 #undef DEBUG_CHUNK_MALLOC 256 257 /** For debugging, we keep a rolling log of debug messages. 258 * These get dumped to disk if we're about to panic. 259 */ 260 #define ROLLING_LOG_SIZE 200 261 #define ROLLING_LOG_ENTRY_LEN 1024 265 262 266 263 /* debug... */ … … 291 288 #define MAX_CHUNK_LEN (16384-1) 292 289 290 /** Number of oddballs tracked in regions. 291 * This is used to figure out when we should pull regions in because 292 * we have an opportunity to migrate chunks that don't match. 293 * Relatively arbitrary; too low means you don't move things out 294 * enough, but boosting it too high wastes memory. 295 */ 296 #define NUM_ODDBALLS 10 297 298 /** Minimum disagreement to be an oddball. 299 * This is used to figure out when we should pull regions in because 300 * we have an opportunity to migrate chunks that don't match. 301 * Relatively arbitrary; too low means you don't move things out 302 * enough, but boosting it too high wastes migration time. 303 */ 304 #define ODDBALL_THRESHOLD 8 305 293 306 /* 294 307 * FIXME: pulling config variables out of my left ear. Fix later. … … 299 312 #define FIXME_REGION_ARRAY_INCREMENT 10 300 313 301 /* 302 * FIXME: unhappiness constants pulled out of right ear. 303 * Needs testing and tweaking. 304 */ 305 /** Constants affecting the way things are migrated around. 306 * Details in the migration discussion. */ 307 #define UNHAPPINESS_HARD 0 308 #define UNHAPPINESS_SOFT 4 309 #define UNHAPPINESS_MAYBE 32 310 #define UNHAPPINESS_TWO 0 311 #define UNHAPPINESS_ONE 2 312 #define UNHAPPINESS_ZERO 24 313 #define UNHAPPINESS_SPACE_DIVISOR 1024 314 #define UNHAPPINESS_DEREFS_DIVISOR 1 315 #define UNHAPPINESS_NEVER 0xffff 316 #define UNHAPPINESS_AWAY_THRESHOLD 96 314 /** Limit for when being a nearly-empty region counts against being 315 * a good region. This is exponential: an empty region gets a penalty 316 * of 1 << LONLINESS_LIMIT. A near-empty region gets a penalty of 317 * 1 << (LONLINESS_LIMIT - used_count). 318 * 319 * Rationale: we don't want to reuse empty regions (or make new regions) 320 * for trivialities. 321 */ 322 #define LONLINESS_LIMIT 5 323 324 /** Free space limit for when we consider making new regions. 325 * The total free space must be less than this percent of capacity. 326 * 327 * Rationale: we don't want to waste memory with lots of extra regions. 328 */ 329 #define FREE_PERCENT_LIMIT 2 330 331 /** Bias for allocating chunks in a region that's already in memory. 332 * Actually, this is a bias against allocating in swapped-out regions, 333 * but that's a nit... 334 * 335 * Rationale: reduce the amount of paging during migration. 336 */ 337 #define IN_MEMORY_BIAS 4 317 338 318 339 /* … … 446 467 ChunkPointer(ChunkReferenceToRegion((ref)), ChunkReferenceToOffset((ref))) 447 468 448 449 469 /* 450 470 * Macros for probing and manipulating chunk headers … … 501 521 ((ChunkDataPtr(region, offset)[0] << 8) + ChunkDerefs(region, offset)) 502 522 523 /* 0 for no, 1 for yes with room, 2 for exact */ 524 #define FitsInSpace(size, capacity) \ 525 (((size) == (capacity)) ? 2 : ((size) <= (capacity) - MIN_REMNANT_LEN)) 526 503 527 /** Region info that gets paged out with its region. 504 528 * This is at the start of the region; … … 525 549 counts on period change! */ 526 550 RegionHeader *in_memory; /**< cache entry; NULL if paged out */ 551 u_int_16 oddballs[NUM_ODDBALLS]; /**< chunk offsets with odd derefs */ 527 552 } Region; 528 553 … … 533 558 regions[(region)].used_count \ 534 559 : 0) 560 #define RegionDerefsWithChunk(region, derefs) \ 561 (((regions[(region)].total_derefs >> \ 562 (curr_period - regions[(region)].period_last_touched)) + derefs) / \ 563 (regions[(region)].used_count + 1)) 535 564 536 565 /* … … 585 614 static int stat_page_in; /**< Number of page-ins */ 586 615 static int stat_migrate_slide; /**< Number of slide migrations */ 587 static int stat_migrate_fill_exact; /**< Number of exact hole fillings */ 588 static int stat_migrate_fill_inexact; /**< Number of inexact hole fillings */ 589 static int stat_migrate_away; /**< Number of chunk expulsions */ 616 static int stat_migrate_move; /**< Number of move migrations */ 617 static int stat_migrate_away; /**< Number of chunk evictions */ 590 618 static int stat_create; /**< Number of chunk creations */ 591 619 static int stat_delete; /**< Number of chunk deletions */ … … 596 624 * migration globals that are used for holding relevant data... 597 625 */ 598 static int m_alloc; /**< The allocated length for the arrays. */599 626 static int m_count; /**< The used length for the arrays. */ 600 627 static chunk_reference_t **m_references; /**< The passed-in references array. */ 601 static u_int_16 *m_length; /**< The lengths of the chunks to be moved. */ 602 static u_int_16 *m_unhappiness; /**< The unhappiness of the chunks. */ 603 static unsigned char *m_derefs; /**< The dereferences for the chunks. */ 604 static int m_limit; /**< The number of migrates allowed. */ 605 628 629 #ifdef CHUNK_PARANOID 630 /** Log of recent actions for debug purposes */ 631 static char rolling_log[ROLLING_LOG_SIZE][ROLLING_LOG_ENTRY_LEN]; 632 static int rolling_pos; 633 static int noisy_log = 0; 634 #endif 635 636 /* 637 * Forward decls 638 */ 639 static void find_oddballs(u_int_16 region); 606 640 607 641 /* 608 642 * Debug routines 609 643 */ 644 /** Add a message to the rolling log. */ 645 static void 646 debug_log(char const *format, ...) 647 { 610 648 #ifdef CHUNK_PARANOID 649 va_list args; 650 651 va_start(args, format); 652 vsprintf(rolling_log[rolling_pos], format, args); 653 va_end(args); 654 655 rolling_log[rolling_pos][ROLLING_LOG_ENTRY_LEN - 1] = '\0'; 656 if (noisy_log) { 657 fprintf(tracelog_fp, "%s\n", rolling_log[rolling_pos]); 658 fflush(tracelog_fp); 659 } 660 rolling_pos = (rolling_pos + 1) % ROLLING_LOG_SIZE; 661 #else 662 if (format) 663 return; /* shut up the compiler warning */ 664 #endif 665 } 666 667 #ifdef CHUNK_PARANOID 668 /** Dump the rolling log. */ 669 static void 670 dump_debug_log(FILE * fp) 671 { 672 int j; 673 fputs("Recent chunk activity:\n", fp); 674 j = rolling_pos; 675 do { 676 if (rolling_log[j][0]) { 677 fputs(rolling_log[j], fp); 678 fputc('\n', fp); 679 rolling_log[j][0] = '\0'; 680 } 681 j = (j + 1) % ROLLING_LOG_SIZE; 682 } while (j != rolling_pos); 683 fputs("End of recent chunk activity.\n", fp); 684 fflush(fp); 685 } 686 687 /** Test if a chunk is migratable. */ 688 static int 689 migratable(u_int_16 region, u_int_16 offset) 690 { 691 chunk_reference_t ref = ChunkReference(region, offset); 692 int j; 693 694 for (j = 0; j < m_count; j++) 695 if (m_references[j][0] == ref) 696 return 1; 697 return 0; 698 } 699 611 700 /** Give a detailed map of a region. 612 701 * Lists pertinent region information, and all the chunks in the region. … … 641 730 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 642 731 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 643 fprintf(fp, "chunk: %4s %-6s off:%04x full:%04x ", 732 fprintf(fp, "chunk:%c%4s %-6s off:%04x full:%04x ", 733 migratable(region, offset) ? '*' : ' ', 644 734 ChunkIsFree(region, offset) ? "FREE" : "", 645 735 ChunkIsShort(region, offset) ? "SHORT" : … … 678 768 pos < REGION_SIZE; pos += ChunkFullLen(region, pos)) { 679 769 if (pos == offset) { 680 if ( (ChunkPointer(region, pos)[0] & CHUNK_FREE_MASK) == CHUNK_FREE)681 mush_panic("Invalid reference to used chunk");770 if (ChunkIsFree(region, pos)) 771 mush_panic("Invalid reference to free chunk as used"); 682 772 return; 683 773 } 684 774 } 775 mush_panic("Invalid reference to non-chunk as used"); 685 776 } 686 777 … … 1055 1146 * \param offset the offset of the hole to use. 1056 1147 * \param full_len the length (including headers) of the space to allocate. 1148 * \param align the alignment to use: 0 = easiest, 1 = left, 2 = right. 1057 1149 * \return the offset of the allocated space. 1058 1150 */ 1059 1151 static u_int_16 1060 split_hole(u_int_16 region, u_int_16 offset, u_int_16 full_len )1152 split_hole(u_int_16 region, u_int_16 offset, u_int_16 full_len, int align) 1061 1153 { 1062 1154 Region *rp = regions + region; … … 1098 1190 1099 1191 ASSERT(hole_len >= full_len + MIN_REMNANT_LEN); 1100 if (rp->in_memory->first_free == offset) { 1192 if (!align) { 1193 if (rp->in_memory->first_free == offset) 1194 align = 1; 1195 else 1196 align = 2; 1197 } 1198 if (align == 1) { 1101 1199 rp->free_bytes -= full_len; 1102 rp->in_memory->first_free += full_len;1103 1200 write_free_chunk(region, offset + full_len, 1104 1201 hole_len - full_len, ChunkNextFree(region, offset)); 1202 if (rp->in_memory->first_free == offset) 1203 rp->in_memory->first_free += full_len; 1204 else { 1205 u_int_16 hole; 1206 for (hole = rp->in_memory->first_free; 1207 hole; hole = ChunkNextFree(region, hole)) 1208 if (ChunkNextFree(region, hole) == offset) 1209 break; 1210 ASSERT(hole); 1211 write_next_free(region, hole, offset + full_len); 1212 } 1105 1213 if (rp->largest_free_chunk == hole_len) 1106 1214 rp->largest_free_chunk = largest_hole(region); … … 1134 1242 int done; 1135 1243 1244 debug_log("read_cache_region %04x", region); 1245 1136 1246 /* Try to seek up to 3 times... */ 1137 1247 for (j = 0; j < 3; j++) … … 1181 1291 } 1182 1292 1183 /** Write a region froma file.1293 /** Write a region to a file. 1184 1294 * \param fd file to write to 1185 1295 * \param rhp region buffer to use … … 1194 1304 size_t remaining; 1195 1305 int done; 1306 1307 debug_log("write_cache_region %04x", region); 1196 1308 1197 1309 /* Try to seek up to 3 times... */ … … 1244 1356 } 1245 1357 1358 /** Update cache position to stave off recycling. 1359 * \param rhp the cached region to keep around. 1360 */ 1361 static void 1362 touch_cache_region(RegionHeader * rhp) 1363 { 1364 debug_log("touch_cache_region %04x", rhp->region_id); 1365 1366 if (cache_head == rhp) 1367 return; 1368 if (cache_tail == rhp) 1369 cache_tail = rhp->prev; 1370 if (rhp->prev) 1371 rhp->prev->next = rhp->next; 1372 if (rhp->next) 1373 rhp->next->prev = rhp->prev; 1374 1375 if (cache_head) 1376 cache_head->prev = rhp; 1377 rhp->next = cache_head; 1378 rhp->prev = NULL; 1379 cache_head = rhp; 1380 if (!cache_tail) 1381 cache_tail = rhp; 1382 } 1383 1246 1384 /** Find space in the cache. 1247 1385 * This is likely to require paging out something. … … 1252 1390 { 1253 1391 RegionHeader *rhp; 1392 1393 debug_log("find_available_cache_region"); 1254 1394 1255 1395 if (!cache_tail || … … 1272 1412 return cache_tail; 1273 1413 1414 rhp = cache_tail; 1274 1415 /* page the current occupant out */ 1416 find_oddballs(rhp->region_id); 1275 1417 #ifdef DEBUG_CHUNK_PAGING 1276 1418 do_rawlog(LT_TRACE, "CHUNK: Paging out region %04x (offset %08x)", 1277 cache_tail->region_id, (unsigned) file_offset);1278 #endif 1279 write_cache_region(swap_fd, cache_tail, cache_tail->region_id);1419 rhp->region_id, (unsigned) file_offset); 1420 #endif 1421 write_cache_region(swap_fd, rhp, rhp->region_id); 1280 1422 /* keep statistics */ 1281 stat_paging_histogram[RegionDerefs( cache_tail->region_id)]++;1423 stat_paging_histogram[RegionDerefs(rhp->region_id)]++; 1282 1424 stat_page_out++; 1283 1425 1284 1426 /* mark the paged out region as not in memory */ 1285 regions[ cache_tail->region_id].in_memory = NULL;1427 regions[rhp->region_id].in_memory = NULL; 1286 1428 /* mark it not in use for sanity check reasons */ 1287 cache_tail->region_id = INVALID_REGION_ID; 1288 1289 return cache_tail; 1290 } 1291 1292 /** Update cache position to stave off recycling. 1293 * \param rhp the cached region to keep around. 1294 */ 1295 static void 1296 touch_cache_region(RegionHeader * rhp) 1297 { 1298 if (cache_head == rhp) 1299 return; 1300 if (cache_tail == rhp) 1301 cache_tail = rhp->prev; 1302 if (rhp->prev) 1303 rhp->prev->next = rhp->next; 1304 if (rhp->next) 1305 rhp->next->prev = rhp->prev; 1306 1307 if (cache_head) 1308 cache_head->prev = rhp; 1309 rhp->next = cache_head; 1310 rhp->prev = NULL; 1311 cache_head = rhp; 1312 if (!cache_tail) 1313 cache_tail = rhp; 1429 rhp->region_id = INVALID_REGION_ID; 1430 1431 return rhp; 1314 1432 } 1315 1433 … … 1326 1444 unsigned int shift; 1327 1445 1446 debug_log("bring_in_region %04x", region); 1447 1448 ASSERT(region < region_count); 1328 1449 if (rp->in_memory) 1329 1450 return; … … 1424 1545 } 1425 1546 1426 /** Compute the expected unhappiness for a chunk in a region. 1427 * This is used to figure out which region is the best region to hold 1428 * a chunk, either when it is new, or when it's really unhappy where it is. 1429 * If the region is in memory, then the free list is searched for a good 1430 * place to put the chunk; otherwise an educated guess is made based on 1431 * the free count, free bytes, and largest free chunk. 1432 * \param region the prospective region to hold the chunk. 1433 * \param full_len the length (including headers) of the chunk. 1434 * \param derefs the number of dereferences on the chunk. 1435 * \return the unhappiness rating if the chunk was placed here. 1436 */ 1437 static u_int_16 1438 predict_score(u_int_16 region, u_int_16 full_len, unsigned char derefs) 1547 /** Find the oddball chunks in a region. 1548 * \param region the region to search in. 1549 */ 1550 static void 1551 find_oddballs(u_int_16 region) 1439 1552 { 1440 1553 Region *rp = regions + region; 1441 u_int_16 score; 1442 1443 if (rp->free_bytes < full_len) 1444 return UNHAPPINESS_NEVER; 1445 1446 score = 0; 1447 if (rp->in_memory) { 1448 u_int_16 offset, best_offset; 1449 score = UNHAPPINESS_NEVER; 1450 best_offset = 0; 1451 for (offset = rp->in_memory->first_free; 1452 offset; offset = ChunkNextFree(region, offset)) { 1453 if (ChunkFullLen(region, offset) == full_len) { 1454 score = UNHAPPINESS_TWO; 1455 best_offset = offset; 1456 if (best_offset == rp->in_memory->first_free) 1457 break; 1458 } else if (ChunkFullLen(region, offset) >= full_len + MIN_REMNANT_LEN && 1459 score >= UNHAPPINESS_ONE) { 1460 if (score == UNHAPPINESS_ONE && 1461 best_offset == rp->in_memory->first_free) 1462 continue; 1463 score = UNHAPPINESS_ONE; 1464 best_offset = offset; 1465 } 1554 int j, d1, d2; 1555 u_int_16 offset, len; 1556 int mean; 1557 1558 for (j = 0; j < NUM_ODDBALLS; j++) 1559 rp->oddballs[j] = 0; 1560 1561 mean = RegionDerefs(region); 1562 1563 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 1564 offset < REGION_SIZE; offset += len) { 1565 len = ChunkFullLen(region, offset); 1566 if (ChunkIsFree(region, offset)) 1567 continue; 1568 d1 = abs(mean - ChunkDerefs(region, offset)); 1569 if (d1 < ODDBALL_THRESHOLD) 1570 continue; 1571 j = NUM_ODDBALLS; 1572 while (j--) { 1573 if (!rp->oddballs[j]) 1574 continue; 1575 d2 = abs(mean - ChunkDerefs(region, rp->oddballs[j])); 1576 if (d1 < d2) 1577 break; 1578 if (j < NUM_ODDBALLS - 1)
