--- deliantra/server/common/utils.C 2008/04/01 19:50:36 1.72 +++ deliantra/server/common/utils.C 2008/12/30 07:24:16 1.84 @@ -1,7 +1,7 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team * Copyright (©) 1992,2007 Frank Tore Johansen * @@ -33,25 +33,27 @@ #include #include -#include #include +#include +#include + #include refcnt_base::refcnt_t refcnt_dummy; -size_t slice_alloc; -rand_gen rndm; +ssize_t slice_alloc; +rand_gen rndm, rmg_rndm; void tausworthe_random_generator::seed (uint32_t seed) { - state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U; - state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U; - state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U; - state [3] = state [2] * 69069U; if (state [0] < 128) state [0] += 128U; + state [0] = seed * 69069U; if (state [0] < 2U) state [0] += 2U; + state [1] = state [0] * 69069U; if (state [0] < 8U) state [0] += 8U; + state [2] = state [1] * 69069U; if (state [0] < 16U) state [0] += 16U; + state [3] = state [2] * 69069U; if (state [0] < 128U) state [0] += 128U; for (int i = 11; --i; ) - operator ()(); + next (); } uint32_t @@ -65,19 +67,24 @@ return state [0] ^ state [1] ^ state [2] ^ state [3]; } +template uint32_t -tausworthe_random_generator::get_range (uint32_t num) +random_number_generator::get_range (uint32_t num) { - return (next () * (uint64_t)num) >> 32U; + return (this->next () * (uint64_t)num) >> 32U; } // return a number within (min .. max) +template int -tausworthe_random_generator::get_range (int r_min, int r_max) +random_number_generator::get_range (int r_min, int r_max) { return r_min + get_range (max (r_max - r_min + 1, 0)); } +template struct random_number_generator; +template struct random_number_generator; + /* * The random functions here take luck into account when rolling random * dice or numbers. This function has less of an impact the larger the @@ -96,13 +103,9 @@ int random_roll (int r_min, int r_max, const object *op, int goodbad) { - int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */ + r_max = max (r_min, r_max); - if (r_max < r_min) - { - LOG (llevError | logBacktrace, "Calling random_roll with min=%d max=%d\n", r_min, r_max); - return r_min; - } + int base = r_max - r_min > 1 ? 20 : 50; /* d2 and d3 are corner cases */ if (op->type == PLAYER) { @@ -122,17 +125,11 @@ * for exp loss calculations for players changing religions. */ sint64 -random_roll64 (sint64 min, sint64 max, const object *op, int goodbad) +random_roll64 (sint64 r_min, sint64 r_max, const object *op, int goodbad) { - sint64 omin = min; - sint64 diff = max - min + 1; - int base = diff > 2 ? 20 : 50; /* d2 and d3 are corner cases */ - - if (diff < 0) - { - LOG (llevError | logBacktrace, "Calling random_roll64 with min=%" PRId64 " max=%" PRId64 "\n", min, max); - return (min); /* avoids a float exception */ - } + sint64 omin = r_min; + sint64 range = max (0, r_max - r_min + 1); + int base = range > 2 ? 20 : 50; /* d2 and d3 are corner cases */ /* * Make a call to get two 32 bit unsigned random numbers, and just to @@ -141,24 +138,24 @@ sint64 ran = (sint64) rndm.next () ^ ((sint64) rndm.next () << 31); if (op->type != PLAYER) - return ((ran % diff) + min); + return ((ran % range) + r_min); int luck = op->stats.luck; - if (rndm (base) < MIN (10, abs (luck))) + if (rndm (base) < min (10, abs (luck))) { /* we have a winner */ ((luck > 0) ? (luck = 1) : (luck = -1)); - diff -= luck; - if (diff < 1) + range -= luck; + if (range < 1) return (omin); /*check again */ - ((goodbad) ? (min += luck) : (diff)); + ((goodbad) ? (r_min += luck) : (range)); - return (MAX (omin, MIN (max, (ran % diff) + min))); + return (max (omin, min (r_max, (ran % range) + r_min))); } - return ran % diff + min; + return ran % range + r_min; } /* @@ -210,9 +207,9 @@ /* convert materialname to materialtype_t */ materialtype_t * -name_to_material (const shstr &name) +name_to_material (const shstr_cmp name) { - for (materialtype_t *mt = materialt; mt && mt->next; mt = mt->next) + for (materialtype_t *mt = materialt; mt; mt = mt->next) if (name == mt->name) return mt; @@ -228,10 +225,10 @@ materialtype_t *mt; int j; - if (op->materialname == NULL) + if (!op->materialname) return; - if (change->materialname != NULL && strcmp (op->materialname, change->materialname)) + if (change->materialname && strcmp (op->materialname, change->materialname)) return; if (!op->is_armor ()) @@ -261,14 +258,16 @@ { materialtype_t *mt, *lmt; - if (op->materialname != NULL) + if (!op->materialname) return; - if (nmt == NULL) + if (nmt) + lmt = nmt; + else { - lmt = NULL; + lmt = 0; - for (mt = materialt; mt && mt->next; mt = mt->next) + for (mt = materialt; mt; mt = mt->next) if (op->materials & mt->material && rndm (1, 100) <= mt->chance && difficulty >= mt->difficulty && (op->magic >= mt->magic || mt->magic == 0)) { @@ -277,10 +276,8 @@ break; } } - else - lmt = nmt; - if (lmt != NULL) + if (lmt) { if (op->stats.dam && op->is_weapon ()) { @@ -459,10 +456,39 @@ { if (!fork ()) { - signal (SIGABRT, SIG_DFL); + signal (SIGINT , SIG_IGN); + signal (SIGTERM, SIG_IGN); + signal (SIGABRT, SIG_IGN); + + signal (SIGSEGV, SIG_DFL); + signal (SIGBUS , SIG_DFL); + signal (SIGILL , SIG_DFL); + signal (SIGTRAP, SIG_DFL); + // try to put corefiles into a subdirectory, if existing, to allow // an administrator to reduce the I/O load. chdir ("cores"); + + // try to detach us from as many external dependencies as possible + // as coredumping can take time by closing all fd's. + { + struct rlimit lim; + + if (getrlimit (RLIMIT_NOFILE, &lim)) + lim.rlim_cur = 1024; + + for (int i = 0; i < lim.rlim_cur; ++i) + close (i); + } + + { + sigset_t empty; + sigemptyset (&empty); + sigprocmask (SIG_SETMASK, &empty, 0); + } + + // try to coredump with SIGTRAP + kill (getpid (), SIGTRAP); abort (); } @@ -471,16 +497,12 @@ void *salloc_ (int n) throw (std::bad_alloc) { -#if PREFER_MALLOC - void *ptr = malloc (n); -#else - slice_alloc += n; void *ptr = g_slice_alloc (n); -#endif if (!ptr) throw std::bad_alloc (); + slice_alloc += n; return ptr; } @@ -517,14 +539,17 @@ void g_slice_free1 (unsigned long size, void *ptr) { + //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D if (expect_true (ptr)) { - //fprintf (stderr, "g_slice_free %ld %p\n", size, ptr);//D unsigned long *p = (unsigned long *)ptr; unsigned long s = *--p ^ MAGIC; if (size != (unsigned long)(*p ^ MAGIC)) - LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s); + { + LOG (logBacktrace | llevError, "slice free size (%lx) doesn't match alloc size (%lx)\n", size, s); + abort (); + } *p = MAGIC; @@ -650,3 +675,26 @@ 0x2d02ef8dL }; +void thread::start (void *(*start_routine)(void *), void *arg) +{ + pthread_attr_t attr; + + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN < sizeof (long) * 4096 + ? sizeof (long) * 4096 : PTHREAD_STACK_MIN); +#ifdef PTHREAD_SCOPE_PROCESS + pthread_attr_setscope (&attr, PTHREAD_SCOPE_PROCESS); +#endif + + sigset_t fullsigset, oldsigset; + sigfillset (&fullsigset); + + pthread_sigmask (SIG_SETMASK, &fullsigset, &oldsigset); + + if (pthread_create (&id, &attr, start_routine, arg)) + cleanup ("unable to create a new thread"); + + pthread_sigmask (SIG_SETMASK, &oldsigset, 0); +} +